├── .gitignore ├── README.md ├── composer.json ├── composer.lock ├── configure.phtml ├── extension.php ├── metadata.json ├── static └── style.css └── vendor ├── autoload.php ├── composer ├── ClassLoader.php ├── InstalledVersions.php ├── LICENSE ├── autoload_classmap.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php ├── autoload_static.php ├── installed.json ├── installed.php └── platform_check.php ├── fivefilters └── readability.php │ ├── .editorconfig │ ├── .gitattributes │ ├── .github │ └── workflows │ │ └── main.yml │ ├── .gitignore │ ├── AUTHORS.md │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── composer.json │ └── src │ ├── Configuration.php │ ├── Nodes │ ├── DOM │ │ ├── DOMAttr.php │ │ ├── DOMCdataSection.php │ │ ├── DOMCharacterData.php │ │ ├── DOMComment.php │ │ ├── DOMDocument.php │ │ ├── DOMDocumentFragment.php │ │ ├── DOMDocumentType.php │ │ ├── DOMElement.php │ │ ├── DOMEntity.php │ │ ├── DOMEntityReference.php │ │ ├── DOMNode.php │ │ ├── DOMNodeList.php │ │ ├── DOMNotation.php │ │ ├── DOMProcessingInstruction.php │ │ └── DOMText.php │ ├── NodeTrait.php │ └── NodeUtility.php │ ├── ParseException.php │ └── Readability.php ├── league ├── uri-interfaces │ ├── Contracts │ │ ├── AuthorityInterface.php │ │ ├── DataPathInterface.php │ │ ├── DomainHostInterface.php │ │ ├── FragmentInterface.php │ │ ├── HostInterface.php │ │ ├── IpHostInterface.php │ │ ├── PathInterface.php │ │ ├── PortInterface.php │ │ ├── QueryInterface.php │ │ ├── SegmentedPathInterface.php │ │ ├── UriAccess.php │ │ ├── UriComponentInterface.php │ │ ├── UriException.php │ │ ├── UriInterface.php │ │ └── UserInfoInterface.php │ ├── Encoder.php │ ├── Exceptions │ │ ├── ConversionFailed.php │ │ ├── MissingFeature.php │ │ ├── OffsetOutOfBounds.php │ │ └── SyntaxError.php │ ├── FeatureDetection.php │ ├── IPv4 │ │ ├── BCMathCalculator.php │ │ ├── Calculator.php │ │ ├── Converter.php │ │ ├── GMPCalculator.php │ │ └── NativeCalculator.php │ ├── IPv6 │ │ └── Converter.php │ ├── Idna │ │ ├── Converter.php │ │ ├── Error.php │ │ ├── Option.php │ │ └── Result.php │ ├── KeyValuePair │ │ └── Converter.php │ ├── LICENSE │ ├── QueryString.php │ ├── UriString.php │ └── composer.json └── uri │ ├── BaseUri.php │ ├── Http.php │ ├── HttpFactory.php │ ├── LICENSE │ ├── Uri.php │ ├── UriInfo.php │ ├── UriResolver.php │ ├── UriTemplate.php │ ├── UriTemplate │ ├── Expression.php │ ├── Operator.php │ ├── Template.php │ ├── TemplateCanNotBeExpanded.php │ ├── VarSpecifier.php │ └── VariableBag.php │ └── composer.json ├── masterminds └── html5 │ ├── CREDITS │ ├── LICENSE.txt │ ├── README.md │ ├── RELEASE.md │ ├── UPGRADING.md │ ├── bin │ └── entities.php │ ├── composer.json │ └── src │ ├── HTML5.php │ └── HTML5 │ ├── Elements.php │ ├── Entities.php │ ├── Exception.php │ ├── InstructionProcessor.php │ ├── Parser │ ├── CharacterReference.php │ ├── DOMTreeBuilder.php │ ├── EventHandler.php │ ├── FileInputStream.php │ ├── InputStream.php │ ├── ParseError.php │ ├── README.md │ ├── Scanner.php │ ├── StringInputStream.php │ ├── Tokenizer.php │ ├── TreeBuildingRules.php │ └── UTF8Utils.php │ └── Serializer │ ├── HTML5Entities.php │ ├── OutputRules.php │ ├── README.md │ ├── RulesInterface.php │ └── Traverser.php └── psr ├── http-factory ├── .gitignore ├── .pullapprove.yml ├── LICENSE ├── README.md ├── composer.json └── src │ ├── RequestFactoryInterface.php │ ├── ResponseFactoryInterface.php │ ├── ServerRequestFactoryInterface.php │ ├── StreamFactoryInterface.php │ ├── UploadedFileFactoryInterface.php │ └── UriFactoryInterface.php ├── http-message ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── docs │ ├── PSR7-Interfaces.md │ └── PSR7-Usage.md └── src │ ├── MessageInterface.php │ ├── RequestInterface.php │ ├── ResponseInterface.php │ ├── ServerRequestInterface.php │ ├── StreamInterface.php │ ├── UploadedFileInterface.php │ └── UriInterface.php └── log ├── LICENSE ├── README.md ├── composer.json └── src ├── AbstractLogger.php ├── InvalidArgumentException.php ├── LogLevel.php ├── LoggerAwareInterface.php ├── LoggerAwareTrait.php ├── LoggerInterface.php ├── LoggerTrait.php └── NullLogger.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/fivefilters/readability.php/test 2 | vendor/masterminds/html5/test 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Article Full Text FreshRSS Extension 2 | 3 | This FreshRSS extension uses the [Fivefilters Readability.php library](https://github.com/fivefilters/readability.php) to extract the full text of an article. Most importantly, it does **not** require any docker containers or external services to work. 4 | 5 | ## Features 6 | - Extracts full article content using [Readability.php library by Fivefilters](https://github.com/fivefilters/readability.php) 7 | - Works entirely client-side (no external services required) 8 | - Preserves original formatting when possible 9 | 10 | ## Requirements 11 | - PHP 8.1+, ext-dom, ext-xml, and ext-mbstring 12 | 13 | ## Installation 14 | 15 | ### Step-by-Step Installation Guide 16 | 17 | 1. **Download the extension**: 18 | - Clone this repository or download the ZIP file and extract it 19 | - The extension folder should be named `af_readability` 20 | 21 | 2. **Copy to FreshRSS extensions folder**: 22 | - Place the `af_readability` folder in your FreshRSS `extensions` directory 23 | - Typical paths: 24 | - Docker: `/usr/share/freshrss/extensions/` 25 | - Manual install: `/path/to/FreshRSS/extensions/` 26 | 27 | 3. **Set proper permissions**: 28 | - Ensure the web server has read access to the extension files 29 | - Example: `chown -R www-data:www-data /path/to/extensions/af_readability` 30 | 31 | ## Activation 32 | 33 | 1. **Log in** to your FreshRSS instance as an administrator 34 | 2. **Navigate** to the "System configuration" section in the admin panel 35 | 3. **Click** on the "Extensions" tab 36 | 4. **Find** "Af_Readability" in the list of available extensions 37 | 5. **Click** the toggle switch to enable the extension 38 | 6. **Click** "Save" to apply changes 39 | 40 | ## Configuration 41 | 42 | ### Enabling the plugin for a feed 43 | 44 | 1. After activation, go back to the "Extensions" tab in System configuration 45 | 2. Find "Af_Readability" in the list of active extensions 46 | 3. Click the gear/settings icon next to the extension name 47 | 4. Activate the checkbox for the feeds for which you want the plugin to fetch full article contents 48 | 5. Click "Save" to apply your settings 49 | 50 | ## Usage Notes 51 | 52 | - The extension processes **NEW** articles when they are first fetched 53 | - Existing articles won't be automatically reprocessed 54 | 55 | To reprocess existing articles: 56 | 1. Go to "Manage" → "Archiving" → "Delete all articles" (consider this step carefully) 57 | 2. Refresh your feeds to fetch articles again 58 | - "Clear cache" won't reprocess existing articles 59 | 60 | ## Troubleshooting 61 | 62 | - If articles aren't showing full text: 63 | - Ensure the extension is properly activated 64 | - Try deleting and refetching articles as described above 65 | - Check FreshRSS protocol for error messages related to the plugin 66 | 67 | ## Based on: 68 | - [ttrss-af_readability](https://gitlab.tt-rss.org/tt-rss/plugins/ttrss-af-readability) for Tiny Tiny RSS by Andrew Dolgov 69 | - [xExtension-Readable](https://github.com/printfuck/xExtension-Readable) for FreshRSS by printfuck 70 | 71 | [Official FreshRSS documentation](https://freshrss.github.io/FreshRSS/en/developers/03_Backend/05_Extensions.html) on writing extensions. 72 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimum-stability": "dev", 3 | "prefer-stable": true, 4 | "repositories": [ 5 | { 6 | "name": "fivefilters/readability.php", 7 | "type": "vcs", 8 | "url": "https://github.com/fivefilters/readability.php.git" 9 | }, 10 | { 11 | "name": "masterminds/html5", 12 | "type": "vcs", 13 | "url": "https://github.com/Masterminds/html5-php.git" 14 | } 15 | ], 16 | "config": { 17 | "platform": { 18 | "php": "8.1.0" 19 | } 20 | }, 21 | "require": { 22 | "fivefilters/readability.php": "*", 23 | "psr/http-factory": "1.0.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /configure.phtml: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 | 8 |
9 |

Shown below are the feeds for which full-text extraction will be applied using the Readability library. The extension will automatically process new articles as they are fetched. Existing articles won't be reprocessed automatically. To reprocess previous articles, you'll need to delete and refetch them. Remember to click Submit to save your changes

10 | 11 | getCategories() as $c) { 13 | ?> 14 | 15 |

name()?>

16 | 17 | 18 | 19 | 20 | 21 | 22 | 28 | 29 | 30 | 31 | feeds() as $f) { 33 | ?> 34 | 35 | 36 | 47 | 48 | 49 | 50 | 53 | 54 |
Readability
Feed
getConfigCategories($c->id()) ? 'checked="checked"' : ''; ?> > 27 | Whole Category: name()?>
getConfigFeeds($f->id()) ? 'checked="checked"' : ''; 43 | ?> 44 | > 45 | 46 | name() ?>
55 | 56 | 59 | 60 |
61 |
62 | 63 |
64 |
65 | 66 | 67 |
68 |
69 |
70 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Af_Readability", 3 | "author": "niehztog", 4 | "description": "Try to inline article content using Readability", 5 | "version": "0.1", 6 | "entrypoint": "Af_Readability", 7 | "type": "user" 8 | } 9 | -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | td.rotate { 2 | /* Something you can count on */ 3 | /*height: 60px; */ 4 | white-space: nowrap; 5 | padding-bottom: 63px; 6 | border-width: 0px; 7 | padding-top: 0px; 8 | } 9 | 10 | td.rotate > div { 11 | transform: 12 | /* Magic Numbers */ 13 | translate(25px, 51px) 14 | /* 45 is really 360 - 45 */ 15 | rotate(315deg); 16 | width: 33px; 17 | margin-left: -8px; 18 | margin-bottom: 4px; 19 | } 20 | td.rotate > div > span { 21 | #padding: 20px 26px; 22 | border-top: 1px solid; 23 | margin: 0px -33px; 24 | margin-top: 6px; 25 | #padding-top: 8px; 26 | padding-left: 38px; 27 | } 28 | td.rotatelast { 29 | /* Something you can count on */ 30 | /* height: 60px; */ 31 | white-space: nowrap; 32 | padding-bottom: 63px; 33 | border-width: 0px; 34 | padding-top: 0px; 35 | } 36 | td.rotatelast > div { 37 | transform: 38 | /* Magic Numbers */ 39 | translate(25px, 51px) 40 | /* 45 is really 360 - 45 */ 41 | rotate(315deg); 42 | width: 33px; 43 | margin-left: -8px; 44 | margin-bottom: 4px; 45 | } 46 | td.rotatelast > div > span { 47 | #padding: 20px 26px; 48 | border-top: 1px solid; 49 | margin: 0px -33px; 50 | margin-top: 6px; 51 | #padding-top: 8px; 52 | padding-left: 34px; 53 | padding-right: 29px; 54 | } 55 | 56 | .form-group.form-fix { 57 | display: grid; 58 | } 59 | 60 | .boldtd { 61 | font-size: larger; 62 | font-weight: bold; 63 | } 64 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | $vendorDir . '/composer/InstalledVersions.php', 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_namespaces.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/fivefilters/readability.php/src'), 10 | 'Psr\\Log\\' => array($vendorDir . '/psr/log/src'), 11 | 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), 12 | 'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'), 13 | 'League\\Uri\\' => array($vendorDir . '/league/uri', $vendorDir . '/league/uri-interfaces'), 14 | ); 15 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | register(true); 35 | 36 | return $loader; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | 11 | array ( 12 | 'fivefilters\\Readability\\' => 24, 13 | ), 14 | 'P' => 15 | array ( 16 | 'Psr\\Log\\' => 8, 17 | 'Psr\\Http\\Message\\' => 17, 18 | ), 19 | 'M' => 20 | array ( 21 | 'Masterminds\\' => 12, 22 | ), 23 | 'L' => 24 | array ( 25 | 'League\\Uri\\' => 11, 26 | ), 27 | ); 28 | 29 | public static $prefixDirsPsr4 = array ( 30 | 'fivefilters\\Readability\\' => 31 | array ( 32 | 0 => __DIR__ . '/..' . '/fivefilters/readability.php/src', 33 | ), 34 | 'Psr\\Log\\' => 35 | array ( 36 | 0 => __DIR__ . '/..' . '/psr/log/src', 37 | ), 38 | 'Psr\\Http\\Message\\' => 39 | array ( 40 | 0 => __DIR__ . '/..' . '/psr/http-factory/src', 41 | 1 => __DIR__ . '/..' . '/psr/http-message/src', 42 | ), 43 | 'Masterminds\\' => 44 | array ( 45 | 0 => __DIR__ . '/..' . '/masterminds/html5/src', 46 | ), 47 | 'League\\Uri\\' => 48 | array ( 49 | 0 => __DIR__ . '/..' . '/league/uri', 50 | 1 => __DIR__ . '/..' . '/league/uri-interfaces', 51 | ), 52 | ); 53 | 54 | public static $classMap = array ( 55 | 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 56 | ); 57 | 58 | public static function getInitializer(ClassLoader $loader) 59 | { 60 | return \Closure::bind(function () use ($loader) { 61 | $loader->prefixLengthsPsr4 = ComposerStaticInitb44cc79a0eaef9cd9c2f2ac697cbe9c0::$prefixLengthsPsr4; 62 | $loader->prefixDirsPsr4 = ComposerStaticInitb44cc79a0eaef9cd9c2f2ac697cbe9c0::$prefixDirsPsr4; 63 | $loader->classMap = ComposerStaticInitb44cc79a0eaef9cd9c2f2ac697cbe9c0::$classMap; 64 | 65 | }, null, ClassLoader::class); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /vendor/composer/installed.php: -------------------------------------------------------------------------------- 1 | array( 3 | 'name' => '__root__', 4 | 'pretty_version' => 'dev-master', 5 | 'version' => 'dev-master', 6 | 'reference' => 'ecc96987909acb2ed49fd750cdac5921ae04b8c6', 7 | 'type' => 'library', 8 | 'install_path' => __DIR__ . '/../../', 9 | 'aliases' => array(), 10 | 'dev' => true, 11 | ), 12 | 'versions' => array( 13 | '__root__' => array( 14 | 'pretty_version' => 'dev-master', 15 | 'version' => 'dev-master', 16 | 'reference' => 'ecc96987909acb2ed49fd750cdac5921ae04b8c6', 17 | 'type' => 'library', 18 | 'install_path' => __DIR__ . '/../../', 19 | 'aliases' => array(), 20 | 'dev_requirement' => false, 21 | ), 22 | 'fivefilters/readability.php' => array( 23 | 'pretty_version' => 'v3.3.3', 24 | 'version' => '3.3.3.0', 25 | 'reference' => 'e2ee7b9e49eae89ac7ed2c74b15718100a73b4c8', 26 | 'type' => 'library', 27 | 'install_path' => __DIR__ . '/../fivefilters/readability.php', 28 | 'aliases' => array(), 29 | 'dev_requirement' => false, 30 | ), 31 | 'league/uri' => array( 32 | 'pretty_version' => '7.5.1', 33 | 'version' => '7.5.1.0', 34 | 'reference' => '81fb5145d2644324614cc532b28efd0215bda430', 35 | 'type' => 'library', 36 | 'install_path' => __DIR__ . '/../league/uri', 37 | 'aliases' => array(), 38 | 'dev_requirement' => false, 39 | ), 40 | 'league/uri-interfaces' => array( 41 | 'pretty_version' => '7.5.0', 42 | 'version' => '7.5.0.0', 43 | 'reference' => '08cfc6c4f3d811584fb09c37e2849e6a7f9b0742', 44 | 'type' => 'library', 45 | 'install_path' => __DIR__ . '/../league/uri-interfaces', 46 | 'aliases' => array(), 47 | 'dev_requirement' => false, 48 | ), 49 | 'masterminds/html5' => array( 50 | 'pretty_version' => '2.9.0', 51 | 'version' => '2.9.0.0', 52 | 'reference' => 'f5ac2c0b0a2eefca70b2ce32a5809992227e75a6', 53 | 'type' => 'library', 54 | 'install_path' => __DIR__ . '/../masterminds/html5', 55 | 'aliases' => array(), 56 | 'dev_requirement' => false, 57 | ), 58 | 'psr/http-factory' => array( 59 | 'pretty_version' => '1.0.1', 60 | 'version' => '1.0.1.0', 61 | 'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be', 62 | 'type' => 'library', 63 | 'install_path' => __DIR__ . '/../psr/http-factory', 64 | 'aliases' => array(), 65 | 'dev_requirement' => false, 66 | ), 67 | 'psr/http-message' => array( 68 | 'pretty_version' => '1.1', 69 | 'version' => '1.1.0.0', 70 | 'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba', 71 | 'type' => 'library', 72 | 'install_path' => __DIR__ . '/../psr/http-message', 73 | 'aliases' => array(), 74 | 'dev_requirement' => false, 75 | ), 76 | 'psr/log' => array( 77 | 'pretty_version' => '3.0.2', 78 | 'version' => '3.0.2.0', 79 | 'reference' => 'f16e1d5863e37f8d8c2a01719f5b34baa2b714d3', 80 | 'type' => 'library', 81 | 'install_path' => __DIR__ . '/../psr/log', 82 | 'aliases' => array(), 83 | 'dev_requirement' => false, 84 | ), 85 | ), 86 | ); 87 | -------------------------------------------------------------------------------- /vendor/composer/platform_check.php: -------------------------------------------------------------------------------- 1 | = 80100)) { 8 | $issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.'; 9 | } 10 | 11 | if ($issues) { 12 | if (!headers_sent()) { 13 | header('HTTP/1.1 500 Internal Server Error'); 14 | } 15 | if (!ini_get('display_errors')) { 16 | if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { 17 | fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); 18 | } elseif (!headers_sent()) { 19 | 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; 20 | } 21 | } 22 | trigger_error( 23 | 'Composer detected issues in your platform: ' . implode(' ', $issues), 24 | E_USER_ERROR 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = false -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/.gitattributes: -------------------------------------------------------------------------------- 1 | # Ignore test-related files 2 | /test/ export-ignore 3 | /phpunit.xml export-ignore 4 | /Makefile export-ignore 5 | /docker export-ignore 6 | /docker-compose.yml export-ignore 7 | 8 | test/* linguist-language=PHP 9 | * text=auto eol=lf -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | push: 9 | branches: [master] 10 | pull_request: 11 | branches: [master] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | 23 | strategy: 24 | matrix: 25 | php: ['8.1', '8.2', '8.3', '8.4'] 26 | libxml: ['2.9.14'] 27 | 28 | # Steps represent a sequence of tasks that will be executed as part of the job 29 | steps: 30 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 31 | - uses: actions/checkout@v3 32 | 33 | - name: Set up PHP 34 | uses: shivammathur/setup-php@v2 35 | with: 36 | php-version: ${{matrix.php}} 37 | tools: composer:v2 38 | 39 | - name: Install dependencies 40 | run: composer install 41 | 42 | # Runs a set of commands using the runners shell 43 | - name: Run tests 44 | run: | 45 | docker build --build-arg PHP_VERSION=${{matrix.php}} --build-arg LIBXML_VERSION=${{matrix.libxml}} -t gh-action - < ./docker/php/Dockerfile 46 | docker run --volume $PWD:/app --workdir="/app" --env XDEBUG_MODE=coverage gh-action php ./vendor/bin/phpunit --coverage-clover /app/test/clover.xml 47 | -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | vendor 3 | composer.lock 4 | /test.* 5 | /test/changed/ -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/AUTHORS.md: -------------------------------------------------------------------------------- 1 | # Authors 2 | 3 | Readability.php developed by **Andres Rey**. 4 | 5 | Based on Arc90's readability.js (1.7.1) script available at: http://code.google.com/p/arc90labs-readability. 6 | Copyright (c) 2010 Arc90 Inc 7 | 8 | The AUTHORS/Contributors are (and/or have been): 9 | 10 | * Andres Rey 11 | * Sergiy Lavryk 12 | * Pedro Amorim 13 | * Malu Decks 14 | * Keyvan Minoukadeh 15 | -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are **welcome** and will be fully **credited**. 4 | 5 | When it comes to the core article-extraction functionality, please contribute to [Mozilla's Readability](https://github.com/mozilla/readability/) repository, as we're trying to mirror that here. 6 | 7 | For anything else, we accept contributions via Pull Requests on [Github](https://github.com/fivefilters/readability.php/). 8 | 9 | ## Pull Requests 10 | 11 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. 12 | 13 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests. 14 | 15 | - **Create feature branches** - Don't ask us to pull from your master branch. 16 | 17 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 18 | 19 | - **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](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. 20 | 21 | - **Don't forget to add yourself to AUTHORS.md** - If you want to be credited, make sure you add your information (whatever you want to include) in `AUTHORS.md`. 22 | 23 | 24 | ## Running Tests 25 | 26 | ``` bash 27 | $ make test-all #requires docker and docker-compose 28 | ``` 29 | 30 | 31 | **Happy coding**! 32 | -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fivefilters/readability.php", 3 | "type": "library", 4 | "description": "A PHP port of Readability.js", 5 | "keywords": ["readability", "html"], 6 | "homepage": "https://github.com/fivefilters/readability.php", 7 | "license": "Apache-2.0", 8 | "authors": [ 9 | { 10 | "name": "Andres Rey", 11 | "email": "andreskrey@gmail.com", 12 | "role": "Original Developer" 13 | }, 14 | { 15 | "name": "Keyvan Minoukadeh", 16 | "email": "keyvan@fivefilters.org", 17 | "homepage": "https://www.fivefilters.org", 18 | "role": "Developer/Maintainer" 19 | } 20 | ], 21 | "autoload": { 22 | "psr-4": { 23 | "fivefilters\\Readability\\": "src/" 24 | } 25 | }, 26 | "autoload-dev": { 27 | "psr-4": {"fivefilters\\Readability\\Test\\": "test"} 28 | }, 29 | "require": { 30 | "php": ">=8.1", 31 | "ext-dom": "*", 32 | "ext-xml": "*", 33 | "ext-mbstring": "*", 34 | "psr/log": "^1.0 || ^2.0 || ^3.0", 35 | "masterminds/html5": "^2.0", 36 | "league/uri": "^7.0" 37 | }, 38 | "require-dev": { 39 | "phpunit/phpunit": "^10.0 || ^11.0", 40 | "monolog/monolog": "^3.0" 41 | }, 42 | "suggest": { 43 | "monolog/monolog": "Allow logging debug information" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/src/Nodes/DOM/DOMAttr.php: -------------------------------------------------------------------------------- 1 | registerNodeClass('DOMAttr', DOMAttr::class); 16 | $this->registerNodeClass('DOMCdataSection', DOMCdataSection::class); 17 | $this->registerNodeClass('DOMCharacterData', DOMCharacterData::class); 18 | $this->registerNodeClass('DOMComment', DOMComment::class); 19 | $this->registerNodeClass('DOMDocument', self::class); 20 | $this->registerNodeClass('DOMDocumentFragment', DOMDocumentFragment::class); 21 | $this->registerNodeClass('DOMDocumentType', DOMDocumentType::class); 22 | $this->registerNodeClass('DOMElement', DOMElement::class); 23 | $this->registerNodeClass('DOMEntity', DOMEntity::class); 24 | $this->registerNodeClass('DOMEntityReference', DOMEntityReference::class); 25 | $this->registerNodeClass('DOMNode', DOMNode::class); 26 | $this->registerNodeClass('DOMNotation', DOMNotation::class); 27 | $this->registerNodeClass('DOMProcessingInstruction', DOMProcessingInstruction::class); 28 | $this->registerNodeClass('DOMText', DOMText::class); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/src/Nodes/DOM/DOMDocumentFragment.php: -------------------------------------------------------------------------------- 1 | childNodes as $node) { 20 | if ($node->nodeType === XML_ELEMENT_NODE) { 21 | $newList->add($node); 22 | } 23 | } 24 | return $newList; 25 | } 26 | 27 | /** 28 | * Returns the Element immediately prior to the specified one in its parent's children list, or null if the specified element is the first one in the list. 29 | * 30 | * @deprecated Use previousElementSibling instead - introduced in PHP 8.0. 31 | */ 32 | public function previousElementSibling(): ?DOMElement 33 | { 34 | return $this->previousElementSibling; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/src/Nodes/DOM/DOMEntity.php: -------------------------------------------------------------------------------- 1 | length is hidden 13 | * from the user and cannot be extended, changed, or tweaked. 14 | */ 15 | class DOMNodeList implements \Countable, \IteratorAggregate 16 | { 17 | /** 18 | * @var array 19 | */ 20 | protected $items = []; 21 | 22 | /** 23 | * @var int 24 | */ 25 | protected $length = 0; 26 | 27 | /** 28 | * To allow access to length in the same way that DOMNodeList allows. 29 | * 30 | * {@inheritdoc} 31 | */ 32 | public function __get($name) 33 | { 34 | switch ($name) { 35 | case 'length': 36 | return $this->length; 37 | default: 38 | trigger_error(sprintf('Undefined property: %s::%s', static::class, $name)); 39 | } 40 | } 41 | 42 | /** 43 | * Add node to the list. 44 | */ 45 | public function add(DOMNode|DOMElement|DOMText|DOMComment|DOMProcessingInstruction|DOMCdataSection $node): DOMNodeList 46 | { 47 | $this->items[] = $node; 48 | $this->length++; 49 | 50 | return $this; 51 | } 52 | 53 | /** 54 | * Get node. 55 | */ 56 | public function item(int $offset): DOMNode|DOMElement|DOMText|DOMComment|DOMProcessingInstruction|DOMCdataSection 57 | { 58 | return $this->items[$offset]; 59 | } 60 | 61 | /** 62 | * Number of items. 63 | */ 64 | public function count(): int 65 | { 66 | return $this->length; 67 | } 68 | 69 | /** 70 | * To make it compatible with iterator_to_array() function. 71 | * 72 | * {@inheritdoc} 73 | */ 74 | public function getIterator(): \ArrayIterator 75 | { 76 | return new \ArrayIterator($this->items); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /vendor/fivefilters/readability.php/src/Nodes/DOM/DOMNotation.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | use League\Uri\Exceptions\MissingFeature; 17 | use League\Uri\Exceptions\SyntaxError; 18 | use Stringable; 19 | 20 | interface AuthorityInterface extends UriComponentInterface 21 | { 22 | /** 23 | * Returns the host component of the authority. 24 | */ 25 | public function getHost(): ?string; 26 | 27 | /** 28 | * Returns the port component of the authority. 29 | */ 30 | public function getPort(): ?int; 31 | 32 | /** 33 | * Returns the user information component of the authority. 34 | */ 35 | public function getUserInfo(): ?string; 36 | 37 | /** 38 | * Returns an associative array containing all the Authority components. 39 | * 40 | * The returned a hashmap similar to PHP's parse_url return value 41 | * 42 | * @link https://tools.ietf.org/html/rfc3986 43 | * 44 | * @return array{user: ?string, pass : ?string, host: ?string, port: ?int} 45 | */ 46 | public function components(): array; 47 | 48 | /** 49 | * Return an instance with the specified host. 50 | * 51 | * This method MUST retain the state of the current instance, and return 52 | * an instance that contains the specified host. 53 | * 54 | * A null value provided for the host is equivalent to removing the host 55 | * information. 56 | * 57 | * @throws SyntaxError for invalid component or transformations 58 | * that would result in an object in invalid state. 59 | * @throws MissingFeature for component or transformations 60 | * requiring IDN support when IDN support is not present 61 | * or misconfigured. 62 | */ 63 | public function withHost(Stringable|string|null $host): self; 64 | 65 | /** 66 | * Return an instance with the specified port. 67 | * 68 | * This method MUST retain the state of the current instance, and return 69 | * an instance that contains the specified port. 70 | * 71 | * A null value provided for the port is equivalent to removing the port 72 | * information. 73 | * 74 | * @throws SyntaxError for invalid component or transformations 75 | * that would result in an object in invalid state. 76 | */ 77 | public function withPort(?int $port): self; 78 | 79 | /** 80 | * Return an instance with the specified user information. 81 | * 82 | * This method MUST retain the state of the current instance, and return 83 | * an instance that contains the specified user information. 84 | * 85 | * Password is optional, but the user information MUST include the 86 | * user; a null value for the user is equivalent to removing user 87 | * information. 88 | * 89 | * @throws SyntaxError for invalid component or transformations 90 | * that would result in an object in invalid state. 91 | */ 92 | public function withUserInfo(Stringable|string|null $user, Stringable|string|null $password = null): self; 93 | } 94 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/DataPathInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | use SplFileObject; 17 | use Stringable; 18 | 19 | interface DataPathInterface extends PathInterface 20 | { 21 | /** 22 | * Retrieve the data mime type associated to the URI. 23 | * 24 | * If no mimetype is present, this method MUST return the default mimetype 'text/plain'. 25 | * 26 | * @see http://tools.ietf.org/html/rfc2397#section-2 27 | */ 28 | public function getMimeType(): string; 29 | 30 | /** 31 | * Retrieve the parameters associated with the Mime Type of the URI. 32 | * 33 | * If no parameters is present, this method MUST return the default parameter 'charset=US-ASCII'. 34 | * 35 | * @see http://tools.ietf.org/html/rfc2397#section-2 36 | */ 37 | public function getParameters(): string; 38 | 39 | /** 40 | * Retrieve the mediatype associated with the URI. 41 | * 42 | * If no mediatype is present, this method MUST return the default parameter 'text/plain;charset=US-ASCII'. 43 | * 44 | * @see http://tools.ietf.org/html/rfc2397#section-3 45 | * 46 | * @return string The URI scheme. 47 | */ 48 | public function getMediaType(): string; 49 | 50 | /** 51 | * Retrieves the data string. 52 | * 53 | * Retrieves the data part of the path. If no data part is provided return 54 | * an empty string 55 | */ 56 | public function getData(): string; 57 | 58 | /** 59 | * Tells whether the data is binary safe encoded. 60 | */ 61 | public function isBinaryData(): bool; 62 | 63 | /** 64 | * Save the data to a specific file. 65 | */ 66 | public function save(string $path, string $mode = 'w'): SplFileObject; 67 | 68 | /** 69 | * Returns an instance where the data part is base64 encoded. 70 | * 71 | * This method MUST retain the state of the current instance, and return 72 | * an instance where the data part is base64 encoded 73 | */ 74 | public function toBinary(): self; 75 | 76 | /** 77 | * Returns an instance where the data part is url encoded following RFC3986 rules. 78 | * 79 | * This method MUST retain the state of the current instance, and return 80 | * an instance where the data part is url encoded 81 | */ 82 | public function toAscii(): self; 83 | 84 | /** 85 | * Return an instance with the specified mediatype parameters. 86 | * 87 | * This method MUST retain the state of the current instance, and return 88 | * an instance that contains the specified mediatype parameters. 89 | * 90 | * Users must provide encoded characters. 91 | * 92 | * An empty parameters value is equivalent to removing the parameter. 93 | */ 94 | public function withParameters(Stringable|string $parameters): self; 95 | } 96 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/DomainHostInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | use Countable; 17 | use Iterator; 18 | use IteratorAggregate; 19 | use League\Uri\Exceptions\SyntaxError; 20 | use Stringable; 21 | 22 | /** 23 | * @extends IteratorAggregate 24 | */ 25 | interface DomainHostInterface extends Countable, HostInterface, IteratorAggregate 26 | { 27 | /** 28 | * Returns the labels total number. 29 | */ 30 | public function count(): int; 31 | 32 | /** 33 | * Iterate over the Domain labels. 34 | * 35 | * @return Iterator 36 | */ 37 | public function getIterator(): Iterator; 38 | 39 | /** 40 | * Retrieves a single host label. 41 | * 42 | * If the label offset has not been set, returns the null value. 43 | */ 44 | public function get(int $offset): ?string; 45 | 46 | /** 47 | * Returns the associated key for a specific label or all the keys. 48 | * 49 | * @return int[] 50 | */ 51 | public function keys(?string $label = null): array; 52 | 53 | /** 54 | * Tells whether the domain is absolute. 55 | */ 56 | public function isAbsolute(): bool; 57 | 58 | /** 59 | * Prepends a label to the host. 60 | */ 61 | public function prepend(Stringable|string $label): self; 62 | 63 | /** 64 | * Appends a label to the host. 65 | */ 66 | public function append(Stringable|string $label): self; 67 | 68 | /** 69 | * Extracts a slice of $length elements starting at position $offset from the host. 70 | * 71 | * This method MUST retain the state of the current instance, and return 72 | * an instance that contains the selected slice. 73 | * 74 | * If $length is null it returns all elements from $offset to the end of the Domain. 75 | */ 76 | public function slice(int $offset, ?int $length = null): self; 77 | 78 | /** 79 | * Returns an instance with its Root label. 80 | * 81 | * @see https://tools.ietf.org/html/rfc3986#section-3.2.2 82 | */ 83 | public function withRootLabel(): self; 84 | 85 | /** 86 | * Returns an instance without its Root label. 87 | * 88 | * @see https://tools.ietf.org/html/rfc3986#section-3.2.2 89 | */ 90 | public function withoutRootLabel(): self; 91 | 92 | /** 93 | * Returns an instance with the modified label. 94 | * 95 | * This method MUST retain the state of the current instance, and return 96 | * an instance that contains the new label 97 | * 98 | * If $key is non-negative, the added label will be the label at $key position from the start. 99 | * If $key is negative, the added label will be the label at $key position from the end. 100 | * 101 | * @throws SyntaxError If the key is invalid 102 | */ 103 | public function withLabel(int $key, Stringable|string $label): self; 104 | 105 | /** 106 | * Returns an instance without the specified label. 107 | * 108 | * This method MUST retain the state of the current instance, and return 109 | * an instance that contains the modified component 110 | * 111 | * If $key is non-negative, the removed label will be the label at $key position from the start. 112 | * If $key is negative, the removed label will be the label at $key position from the end. 113 | * 114 | * @throws SyntaxError If the key is invalid 115 | */ 116 | public function withoutLabel(int ...$keys): self; 117 | } 118 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/FragmentInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | interface FragmentInterface extends UriComponentInterface 17 | { 18 | /** 19 | * Returns the decoded fragment. 20 | */ 21 | public function decoded(): ?string; 22 | } 23 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/HostInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | interface HostInterface extends UriComponentInterface 17 | { 18 | /** 19 | * Returns the ascii representation. 20 | */ 21 | public function toAscii(): ?string; 22 | 23 | /** 24 | * Returns the unicode representation. 25 | */ 26 | public function toUnicode(): ?string; 27 | 28 | /** 29 | * Returns the IP version. 30 | * 31 | * If the host is a not an IP this method will return null 32 | */ 33 | public function getIpVersion(): ?string; 34 | 35 | /** 36 | * Returns the IP component If the Host is an IP address. 37 | * 38 | * If the host is a not an IP this method will return null 39 | */ 40 | public function getIp(): ?string; 41 | 42 | /** 43 | * Tells whether the host is a domain name. 44 | */ 45 | public function isDomain(): bool; 46 | 47 | /** 48 | * Tells whether the host is an IP Address. 49 | */ 50 | public function isIp(): bool; 51 | 52 | /** 53 | * Tells whether the host is a registered name. 54 | */ 55 | public function isRegisteredName(): bool; 56 | } 57 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/IpHostInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | interface IpHostInterface extends HostInterface 17 | { 18 | /** 19 | * Tells whether the host is an IPv4 address. 20 | */ 21 | public function isIpv4(): bool; 22 | 23 | /** 24 | * Tells whether the host is an IPv6 address. 25 | */ 26 | public function isIpv6(): bool; 27 | 28 | /** 29 | * Tells whether the host is an IPv6 address. 30 | */ 31 | public function isIpFuture(): bool; 32 | 33 | /** 34 | * Tells whether the host has a ZoneIdentifier. 35 | * 36 | * @see http://tools.ietf.org/html/rfc6874#section-4 37 | */ 38 | public function hasZoneIdentifier(): bool; 39 | 40 | /** 41 | * Returns a host without its zone identifier according to RFC6874. 42 | * 43 | * This method MUST retain the state of the current instance, and return 44 | * an instance without the host zone identifier according to RFC6874 45 | * 46 | * @see http://tools.ietf.org/html/rfc6874#section-4 47 | */ 48 | public function withoutZoneIdentifier(): self; 49 | } 50 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/PathInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | use League\Uri\Exceptions\SyntaxError; 17 | 18 | interface PathInterface extends UriComponentInterface 19 | { 20 | /** 21 | * Returns the decoded path. 22 | */ 23 | public function decoded(): string; 24 | 25 | /** 26 | * Tells whether the path is absolute or relative. 27 | */ 28 | public function isAbsolute(): bool; 29 | 30 | /** 31 | * Tells whether the path has a trailing slash. 32 | */ 33 | public function hasTrailingSlash(): bool; 34 | 35 | /** 36 | * Returns an instance without dot segments. 37 | * 38 | * This method MUST retain the state of the current instance, and return 39 | * an instance that contains the path component normalized by removing 40 | * the dot segment. 41 | * 42 | * @throws SyntaxError for invalid component or transformations 43 | * that would result in a object in invalid state. 44 | */ 45 | public function withoutDotSegments(): self; 46 | 47 | /** 48 | * Returns an instance with a leading slash. 49 | * 50 | * This method MUST retain the state of the current instance, and return 51 | * an instance that contains the path component with a leading slash 52 | * 53 | * @throws SyntaxError for invalid component or transformations 54 | * that would result in a object in invalid state. 55 | */ 56 | public function withLeadingSlash(): self; 57 | 58 | /** 59 | * Returns an instance without a leading slash. 60 | * 61 | * This method MUST retain the state of the current instance, and return 62 | * an instance that contains the path component without a leading slash 63 | * 64 | * @throws SyntaxError for invalid component or transformations 65 | * that would result in a object in invalid state. 66 | */ 67 | public function withoutLeadingSlash(): self; 68 | 69 | /** 70 | * Returns an instance with a trailing slash. 71 | * 72 | * This method MUST retain the state of the current instance, and return 73 | * an instance that contains the path component with a trailing slash 74 | * 75 | * @throws SyntaxError for invalid component or transformations 76 | * that would result in a object in invalid state. 77 | */ 78 | public function withTrailingSlash(): self; 79 | 80 | /** 81 | * Returns an instance without a trailing slash. 82 | * 83 | * This method MUST retain the state of the current instance, and return 84 | * an instance that contains the path component without a trailing slash 85 | * 86 | * @throws SyntaxError for invalid component or transformations 87 | * that would result in a object in invalid state. 88 | */ 89 | public function withoutTrailingSlash(): self; 90 | } 91 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/PortInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | interface PortInterface extends UriComponentInterface 17 | { 18 | /** 19 | * Returns the integer representation of the Port. 20 | */ 21 | public function toInt(): ?int; 22 | } 23 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/SegmentedPathInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | use Countable; 17 | use Iterator; 18 | use IteratorAggregate; 19 | use League\Uri\Exceptions\SyntaxError; 20 | use Stringable; 21 | 22 | /** 23 | * @extends IteratorAggregate 24 | */ 25 | interface SegmentedPathInterface extends Countable, IteratorAggregate, PathInterface 26 | { 27 | /** 28 | * Returns the total number of segments in the path. 29 | */ 30 | public function count(): int; 31 | 32 | /** 33 | * Iterate over the path segment. 34 | * 35 | * @return Iterator 36 | */ 37 | public function getIterator(): Iterator; 38 | 39 | /** 40 | * Returns parent directory's path. 41 | */ 42 | public function getDirname(): string; 43 | 44 | /** 45 | * Returns the path basename. 46 | */ 47 | public function getBasename(): string; 48 | 49 | /** 50 | * Returns the basename extension. 51 | */ 52 | public function getExtension(): string; 53 | 54 | /** 55 | * Retrieves a single path segment. 56 | * 57 | * If the segment offset has not been set, returns null. 58 | */ 59 | public function get(int $offset): ?string; 60 | 61 | /** 62 | * Returns the associated key for a specific segment. 63 | * 64 | * If a value is specified only the keys associated with 65 | * the given value will be returned 66 | * 67 | * @return array 68 | */ 69 | public function keys(Stringable|string|null $segment = null): array; 70 | 71 | /** 72 | * Appends a segment to the path. 73 | */ 74 | public function append(Stringable|string $segment): self; 75 | 76 | /** 77 | * Extracts a slice of $length elements starting at position $offset from the host. 78 | * 79 | * This method MUST retain the state of the current instance, and return 80 | * an instance that contains the selected slice. 81 | * 82 | * If $length is null it returns all elements from $offset to the end of the Path. 83 | */ 84 | public function slice(int $offset, ?int $length = null): self; 85 | 86 | /** 87 | * Prepends a segment to the path. 88 | */ 89 | public function prepend(Stringable|string $segment): self; 90 | 91 | /** 92 | * Returns an instance with the modified segment. 93 | * 94 | * This method MUST retain the state of the current instance, and return 95 | * an instance that contains the new segment 96 | * 97 | * If $key is non-negative, the added segment will be the segment at $key position from the start. 98 | * If $key is negative, the added segment will be the segment at $key position from the end. 99 | * 100 | * @throws SyntaxError If the key is invalid 101 | */ 102 | public function withSegment(int $key, Stringable|string $segment): self; 103 | 104 | /** 105 | * Returns an instance without the specified segment. 106 | * 107 | * This method MUST retain the state of the current instance, and return 108 | * an instance that contains the modified component 109 | * 110 | * If $key is non-negative, the removed segment will be the segment at $key position from the start. 111 | * If $key is negative, the removed segment will be the segment at $key position from the end. 112 | * 113 | * @throws SyntaxError If the key is invalid 114 | */ 115 | public function withoutSegment(int ...$keys): self; 116 | 117 | /** 118 | * Returns an instance without duplicate delimiters. 119 | * 120 | * This method MUST retain the state of the current instance, and return 121 | * an instance that contains the path component normalized by removing 122 | * multiple consecutive empty segment 123 | */ 124 | public function withoutEmptySegments(): self; 125 | 126 | /** 127 | * Returns an instance with the specified parent directory's path. 128 | * 129 | * This method MUST retain the state of the current instance, and return 130 | * an instance that contains the extension basename modified. 131 | */ 132 | public function withDirname(Stringable|string $path): self; 133 | 134 | /** 135 | * Returns an instance with the specified basename. 136 | * 137 | * This method MUST retain the state of the current instance, and return 138 | * an instance that contains the extension basename modified. 139 | */ 140 | public function withBasename(Stringable|string $basename): self; 141 | 142 | /** 143 | * Returns an instance with the specified basename extension. 144 | * 145 | * This method MUST retain the state of the current instance, and return 146 | * an instance that contains the extension basename modified. 147 | */ 148 | public function withExtension(Stringable|string $extension): self; 149 | } 150 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/UriAccess.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | use Psr\Http\Message\UriInterface as Psr7UriInterface; 17 | 18 | interface UriAccess 19 | { 20 | public function getUri(): UriInterface|Psr7UriInterface; 21 | 22 | /** 23 | * Returns the RFC3986 string representation of the complete URI. 24 | */ 25 | public function getUriString(): string; 26 | } 27 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/UriComponentInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | use JsonSerializable; 17 | use Stringable; 18 | 19 | interface UriComponentInterface extends JsonSerializable, Stringable 20 | { 21 | /** 22 | * Returns the instance string representation. 23 | * 24 | * If the instance is defined, the value returned MUST be percent-encoded, 25 | * but MUST NOT double-encode any characters. To determine what characters 26 | * to encode, please refer to RFC 3986, Sections 2 and 3. 27 | * 28 | * If the instance is not defined null is returned 29 | */ 30 | public function value(): ?string; 31 | 32 | /** 33 | * Returns the instance string representation. 34 | * 35 | * If the instance is defined, the value returned MUST be percent-encoded, 36 | * but MUST NOT double-encode any characters. To determine what characters 37 | * to encode, please refer to RFC 3986, Sections 2 and 3. 38 | * 39 | * If the instance is not defined an empty string is returned 40 | */ 41 | public function toString(): string; 42 | 43 | /** 44 | * Returns the instance string representation. 45 | * 46 | * If the instance is defined, the value returned MUST be percent-encoded, 47 | * but MUST NOT double-encode any characters. To determine what characters 48 | * to encode, please refer to RFC 3986, Sections 2 and 3. 49 | * 50 | * If the instance is not defined an empty string is returned 51 | */ 52 | public function __toString(): string; 53 | 54 | /** 55 | * Returns the instance json representation. 56 | * 57 | * If the instance is defined, the value returned MUST be percent-encoded, 58 | * but MUST NOT double-encode any characters. To determine what characters 59 | * to encode, please refer to RFC 3986 or RFC 1738. 60 | * 61 | * If the instance is not defined null is returned 62 | */ 63 | public function jsonSerialize(): ?string; 64 | 65 | /** 66 | * Returns the instance string representation with its optional URI delimiters. 67 | * 68 | * The value returned MUST be percent-encoded, but MUST NOT double-encode any 69 | * characters. To determine what characters to encode, please refer to RFC 3986, 70 | * Sections 2 and 3. 71 | * 72 | * If the instance is not defined an empty string is returned 73 | */ 74 | public function getUriComponent(): string; 75 | } 76 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/UriException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | use Throwable; 17 | 18 | interface UriException extends Throwable 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Contracts/UserInfoInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Contracts; 15 | 16 | use Stringable; 17 | 18 | interface UserInfoInterface extends UriComponentInterface 19 | { 20 | /** 21 | * Returns the user component part. 22 | */ 23 | public function getUser(): ?string; 24 | 25 | /** 26 | * Returns the pass component part. 27 | */ 28 | public function getPass(): ?string; 29 | 30 | /** 31 | * Returns an associative array containing all the User Info components. 32 | * 33 | * The returned a hashmap similar to PHP's parse_url return value 34 | * 35 | * @link https://tools.ietf.org/html/rfc3986 36 | * 37 | * @return array{user: ?string, pass : ?string} 38 | */ 39 | public function components(): array; 40 | 41 | /** 42 | * Returns an instance with the specified user and/or pass. 43 | * 44 | * This method MUST retain the state of the current instance, and return 45 | * an instance that contains the specified new username 46 | * otherwise it returns the same instance unchanged. 47 | * 48 | * A variable equal to null is equivalent to removing the complete user information. 49 | */ 50 | public function withUser(Stringable|string|null $username): self; 51 | 52 | /** 53 | * Returns an instance with the specified user and/or pass. 54 | * 55 | * This method MUST retain the state of the current instance, and return 56 | * an instance that contains the specified password if the user is specified 57 | * otherwise it returns the same instance unchanged. 58 | * 59 | * An empty user is equivalent to removing the user information. 60 | */ 61 | public function withPass(Stringable|string|null $password): self; 62 | } 63 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Exceptions/ConversionFailed.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Exceptions; 15 | 16 | use League\Uri\Idna\Error; 17 | use League\Uri\Idna\Result; 18 | use Stringable; 19 | 20 | final class ConversionFailed extends SyntaxError 21 | { 22 | private function __construct( 23 | string $message, 24 | private readonly string $host, 25 | private readonly Result $result 26 | ) { 27 | parent::__construct($message); 28 | } 29 | 30 | public static function dueToIdnError(Stringable|string $host, Result $result): self 31 | { 32 | $reasons = array_map(fn (Error $error): string => $error->description(), $result->errors()); 33 | 34 | return new self('Host `'.$host.'` is invalid: '.implode('; ', $reasons).'.', (string) $host, $result); 35 | } 36 | 37 | public function getHost(): string 38 | { 39 | return $this->host; 40 | } 41 | 42 | public function getResult(): Result 43 | { 44 | return $this->result; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Exceptions/MissingFeature.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Exceptions; 15 | 16 | use League\Uri\Contracts\UriException; 17 | use RuntimeException; 18 | 19 | class MissingFeature extends RuntimeException implements UriException 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Exceptions/OffsetOutOfBounds.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Exceptions; 15 | 16 | class OffsetOutOfBounds extends SyntaxError 17 | { 18 | } 19 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Exceptions/SyntaxError.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Exceptions; 15 | 16 | use InvalidArgumentException; 17 | use League\Uri\Contracts\UriException; 18 | 19 | class SyntaxError extends InvalidArgumentException implements UriException 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/FeatureDetection.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri; 15 | 16 | use finfo; 17 | use League\Uri\Exceptions\MissingFeature; 18 | use League\Uri\IPv4\Calculator; 19 | 20 | use const PHP_INT_SIZE; 21 | 22 | /** 23 | * Allow detecting features needed to make the packages work. 24 | */ 25 | final class FeatureDetection 26 | { 27 | public static function supportsFileDetection(): void 28 | { 29 | static $isSupported = null; 30 | $isSupported = $isSupported ?? class_exists(finfo::class); 31 | 32 | if (!$isSupported) { 33 | throw new MissingFeature('Support for file type detection requires the `fileinfo` extension.'); 34 | } 35 | } 36 | 37 | public static function supportsIdn(): void 38 | { 39 | static $isSupported = null; 40 | $isSupported = $isSupported ?? (function_exists('\idn_to_ascii') && defined('\INTL_IDNA_VARIANT_UTS46')); 41 | 42 | if (!$isSupported) { 43 | throw new MissingFeature('Support for IDN host requires the `intl` extension for best performance or run "composer require symfony/polyfill-intl-idn" to install a polyfill.'); 44 | } 45 | } 46 | 47 | public static function supportsIPv4Conversion(): void 48 | { 49 | static $isSupported = null; 50 | $isSupported = $isSupported ?? (extension_loaded('gmp') || extension_loaded('bcmath') || (4 < PHP_INT_SIZE)); 51 | 52 | if (!$isSupported) { 53 | throw new MissingFeature('A '.Calculator::class.' implementation could not be automatically loaded. To perform IPv4 conversion use a x.64 PHP build or install one of the following extension GMP or BCMath. You can also ship your own implmentation.'); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/IPv4/BCMathCalculator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\IPv4; 15 | 16 | use function bcadd; 17 | use function bccomp; 18 | use function bcdiv; 19 | use function bcmod; 20 | use function bcmul; 21 | use function bcpow; 22 | use function bcsub; 23 | use function str_split; 24 | 25 | final class BCMathCalculator implements Calculator 26 | { 27 | private const SCALE = 0; 28 | private const CONVERSION_TABLE = [ 29 | '0' => '0', '1' => '1', '2' => '2', '3' => '3', 30 | '4' => '4', '5' => '5', '6' => '6', '7' => '7', 31 | '8' => '8', '9' => '9', 'a' => '10', 'b' => '11', 32 | 'c' => '12', 'd' => '13', 'e' => '14', 'f' => '15', 33 | ]; 34 | 35 | public function baseConvert(mixed $value, int $base): string 36 | { 37 | $value = (string) $value; 38 | if (10 === $base) { 39 | return $value; 40 | } 41 | 42 | $base = (string) $base; 43 | $decimal = '0'; 44 | foreach (str_split($value) as $char) { 45 | $decimal = bcadd($this->multiply($decimal, $base), self::CONVERSION_TABLE[$char], self::SCALE); 46 | } 47 | 48 | return $decimal; 49 | } 50 | 51 | public function pow(mixed $value, int $exponent): string 52 | { 53 | return bcpow((string) $value, (string) $exponent, self::SCALE); 54 | } 55 | 56 | public function compare(mixed $value1, $value2): int 57 | { 58 | return bccomp((string) $value1, (string) $value2, self::SCALE); 59 | } 60 | 61 | public function multiply(mixed $value1, $value2): string 62 | { 63 | return bcmul((string) $value1, (string) $value2, self::SCALE); 64 | } 65 | 66 | public function div(mixed $value, mixed $base): string 67 | { 68 | return bcdiv((string) $value, (string) $base, self::SCALE); 69 | } 70 | 71 | public function mod(mixed $value, mixed $base): string 72 | { 73 | return bcmod((string) $value, (string) $base, self::SCALE); 74 | } 75 | 76 | public function add(mixed $value1, mixed $value2): string 77 | { 78 | return bcadd((string) $value1, (string) $value2, self::SCALE); 79 | } 80 | 81 | public function sub(mixed $value1, mixed $value2): string 82 | { 83 | return bcsub((string) $value1, (string) $value2, self::SCALE); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/IPv4/Calculator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\IPv4; 15 | 16 | interface Calculator 17 | { 18 | /** 19 | * Add numbers. 20 | * 21 | * @param mixed $value1 a number that will be added to $value2 22 | * @param mixed $value2 a number that will be added to $value1 23 | * 24 | * @return mixed the addition result 25 | */ 26 | public function add(mixed $value1, mixed $value2); 27 | 28 | /** 29 | * Subtract one number from another. 30 | * 31 | * @param mixed $value1 a number that will be subtracted of $value2 32 | * @param mixed $value2 a number that will be subtracted to $value1 33 | * 34 | * @return mixed the subtraction result 35 | */ 36 | public function sub(mixed $value1, mixed $value2); 37 | 38 | /** 39 | * Multiply numbers. 40 | * 41 | * @param mixed $value1 a number that will be multiplied by $value2 42 | * @param mixed $value2 a number that will be multiplied by $value1 43 | * 44 | * @return mixed the multiplication result 45 | */ 46 | public function multiply(mixed $value1, mixed $value2); 47 | 48 | /** 49 | * Divide numbers. 50 | * 51 | * @param mixed $value The number being divided. 52 | * @param mixed $base The number that $value is being divided by. 53 | * 54 | * @return mixed the result of the division 55 | */ 56 | public function div(mixed $value, mixed $base); 57 | 58 | /** 59 | * Raise an number to the power of exponent. 60 | * 61 | * @param mixed $value scalar, the base to use 62 | * 63 | * @return mixed the value raised to the power of exp. 64 | */ 65 | public function pow(mixed $value, int $exponent); 66 | 67 | /** 68 | * Returns the int point remainder (modulo) of the division of the arguments. 69 | * 70 | * @param mixed $value The dividend 71 | * @param mixed $base The divisor 72 | * 73 | * @return mixed the remainder 74 | */ 75 | public function mod(mixed $value, mixed $base); 76 | 77 | /** 78 | * Number comparison. 79 | * 80 | * @param mixed $value1 the first value 81 | * @param mixed $value2 the second value 82 | * 83 | * @return int Returns < 0 if value1 is less than value2; > 0 if value1 is greater than value2, and 0 if they are equal. 84 | */ 85 | public function compare(mixed $value1, mixed $value2): int; 86 | 87 | /** 88 | * Get the decimal integer value of a variable. 89 | * 90 | * @param mixed $value The scalar value being converted to an integer 91 | * 92 | * @return mixed the integer value 93 | */ 94 | public function baseConvert(mixed $value, int $base); 95 | } 96 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/IPv4/GMPCalculator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\IPv4; 15 | 16 | use GMP; 17 | 18 | use function gmp_add; 19 | use function gmp_cmp; 20 | use function gmp_div_q; 21 | use function gmp_init; 22 | use function gmp_mod; 23 | use function gmp_mul; 24 | use function gmp_pow; 25 | use function gmp_sub; 26 | 27 | use const GMP_ROUND_MINUSINF; 28 | 29 | final class GMPCalculator implements Calculator 30 | { 31 | public function baseConvert(mixed $value, int $base): GMP 32 | { 33 | return gmp_init($value, $base); 34 | } 35 | 36 | public function pow(mixed $value, int $exponent): GMP 37 | { 38 | return gmp_pow($value, $exponent); 39 | } 40 | 41 | public function compare(mixed $value1, mixed $value2): int 42 | { 43 | return gmp_cmp($value1, $value2); 44 | } 45 | 46 | public function multiply(mixed $value1, mixed $value2): GMP 47 | { 48 | return gmp_mul($value1, $value2); 49 | } 50 | 51 | public function div(mixed $value, mixed $base): GMP 52 | { 53 | return gmp_div_q($value, $base, GMP_ROUND_MINUSINF); 54 | } 55 | 56 | public function mod(mixed $value, mixed $base): GMP 57 | { 58 | return gmp_mod($value, $base); 59 | } 60 | 61 | public function add(mixed $value1, mixed $value2): GMP 62 | { 63 | return gmp_add($value1, $value2); 64 | } 65 | 66 | public function sub(mixed $value1, mixed $value2): GMP 67 | { 68 | return gmp_sub($value1, $value2); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/IPv4/NativeCalculator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\IPv4; 15 | 16 | use function floor; 17 | use function intval; 18 | 19 | final class NativeCalculator implements Calculator 20 | { 21 | public function baseConvert(mixed $value, int $base): int 22 | { 23 | return intval((string) $value, $base); 24 | } 25 | 26 | public function pow(mixed $value, int $exponent) 27 | { 28 | return $value ** $exponent; 29 | } 30 | 31 | public function compare(mixed $value1, mixed $value2): int 32 | { 33 | return $value1 <=> $value2; 34 | } 35 | 36 | public function multiply(mixed $value1, mixed $value2): int 37 | { 38 | return $value1 * $value2; 39 | } 40 | 41 | public function div(mixed $value, mixed $base): int 42 | { 43 | return (int) floor($value / $base); 44 | } 45 | 46 | public function mod(mixed $value, mixed $base): int 47 | { 48 | return $value % $base; 49 | } 50 | 51 | public function add(mixed $value1, mixed $value2): int 52 | { 53 | return $value1 + $value2; 54 | } 55 | 56 | public function sub(mixed $value1, mixed $value2): int 57 | { 58 | return $value1 - $value2; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/IPv6/Converter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\IPv6; 15 | 16 | use Stringable; 17 | use ValueError; 18 | 19 | use function filter_var; 20 | use function implode; 21 | use function inet_pton; 22 | use function str_split; 23 | use function strtolower; 24 | use function unpack; 25 | 26 | use const FILTER_FLAG_IPV6; 27 | use const FILTER_VALIDATE_IP; 28 | 29 | final class Converter 30 | { 31 | /** 32 | * Significant 10 bits of IP to detect Zone ID regular expression pattern. 33 | * 34 | * @var string 35 | */ 36 | private const HOST_ADDRESS_BLOCK = "\xfe\x80"; 37 | 38 | public static function compressIp(string $ipAddress): string 39 | { 40 | return match (filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { 41 | false => throw new ValueError('The submitted IP is not a valid IPv6 address.'), 42 | default => strtolower((string) inet_ntop((string) inet_pton($ipAddress))), 43 | }; 44 | } 45 | 46 | public static function expandIp(string $ipAddress): string 47 | { 48 | if (false === filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { 49 | throw new ValueError('The submitted IP is not a valid IPv6 address.'); 50 | } 51 | 52 | $hex = (array) unpack('H*hex', (string) inet_pton($ipAddress)); 53 | 54 | return implode(':', str_split(strtolower($hex['hex'] ?? ''), 4)); 55 | } 56 | 57 | public static function compress(Stringable|string|null $host): ?string 58 | { 59 | $components = self::parse($host); 60 | if (null === $components['ipAddress']) { 61 | return match ($host) { 62 | null => $host, 63 | default => (string) $host, 64 | }; 65 | } 66 | 67 | $components['ipAddress'] = self::compressIp($components['ipAddress']); 68 | 69 | return self::build($components); 70 | } 71 | 72 | public static function expand(Stringable|string|null $host): ?string 73 | { 74 | $components = self::parse($host); 75 | if (null === $components['ipAddress']) { 76 | return match ($host) { 77 | null => $host, 78 | default => (string) $host, 79 | }; 80 | } 81 | 82 | $components['ipAddress'] = self::expandIp($components['ipAddress']); 83 | 84 | return self::build($components); 85 | } 86 | 87 | private static function build(array $components): string 88 | { 89 | $components['ipAddress'] ??= null; 90 | $components['zoneIdentifier'] ??= null; 91 | 92 | if (null === $components['ipAddress']) { 93 | return ''; 94 | } 95 | 96 | return '['.$components['ipAddress'].match ($components['zoneIdentifier']) { 97 | null => '', 98 | default => '%'.$components['zoneIdentifier'], 99 | }.']'; 100 | } 101 | 102 | /**] 103 | * @param Stringable|string|null $host 104 | * 105 | * @return array{ipAddress:string|null, zoneIdentifier:string|null} 106 | */ 107 | private static function parse(Stringable|string|null $host): array 108 | { 109 | if (null === $host) { 110 | return ['ipAddress' => null, 'zoneIdentifier' => null]; 111 | } 112 | 113 | $host = (string) $host; 114 | if ('' === $host) { 115 | return ['ipAddress' => null, 'zoneIdentifier' => null]; 116 | } 117 | 118 | if (!str_starts_with($host, '[')) { 119 | return ['ipAddress' => null, 'zoneIdentifier' => null]; 120 | } 121 | 122 | if (!str_ends_with($host, ']')) { 123 | return ['ipAddress' => null, 'zoneIdentifier' => null]; 124 | } 125 | 126 | [$ipv6, $zoneIdentifier] = explode('%', substr($host, 1, -1), 2) + [1 => null]; 127 | if (false === filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { 128 | return ['ipAddress' => null, 'zoneIdentifier' => null]; 129 | } 130 | 131 | return match (true) { 132 | null === $zoneIdentifier, 133 | is_string($ipv6) && str_starts_with((string)inet_pton($ipv6), self::HOST_ADDRESS_BLOCK) => ['ipAddress' => $ipv6, 'zoneIdentifier' => $zoneIdentifier], 134 | default => ['ipAddress' => null, 'zoneIdentifier' => null], 135 | }; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Idna/Error.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace League\Uri\Idna; 13 | 14 | enum Error: int 15 | { 16 | case NONE = 0; 17 | case EMPTY_LABEL = 1; 18 | case LABEL_TOO_LONG = 2; 19 | case DOMAIN_NAME_TOO_LONG = 4; 20 | case LEADING_HYPHEN = 8; 21 | case TRAILING_HYPHEN = 0x10; 22 | case HYPHEN_3_4 = 0x20; 23 | case LEADING_COMBINING_MARK = 0x40; 24 | case DISALLOWED = 0x80; 25 | case PUNYCODE = 0x100; 26 | case LABEL_HAS_DOT = 0x200; 27 | case INVALID_ACE_LABEL = 0x400; 28 | case BIDI = 0x800; 29 | case CONTEXTJ = 0x1000; 30 | case CONTEXTO_PUNCTUATION = 0x2000; 31 | case CONTEXTO_DIGITS = 0x4000; 32 | 33 | public function description(): string 34 | { 35 | return match ($this) { 36 | self::NONE => 'No error has occurred', 37 | self::EMPTY_LABEL => 'a non-final domain name label (or the whole domain name) is empty', 38 | self::LABEL_TOO_LONG => 'a domain name label is longer than 63 bytes', 39 | self::DOMAIN_NAME_TOO_LONG => 'a domain name is longer than 255 bytes in its storage form', 40 | self::LEADING_HYPHEN => 'a label starts with a hyphen-minus ("-")', 41 | self::TRAILING_HYPHEN => 'a label ends with a hyphen-minus ("-")', 42 | self::HYPHEN_3_4 => 'a label contains hyphen-minus ("-") in the third and fourth positions', 43 | self::LEADING_COMBINING_MARK => 'a label starts with a combining mark', 44 | self::DISALLOWED => 'a label or domain name contains disallowed characters', 45 | self::PUNYCODE => 'a label starts with "xn--" but does not contain valid Punycode', 46 | self::LABEL_HAS_DOT => 'a label contains a dot=full stop', 47 | self::INVALID_ACE_LABEL => 'An ACE label does not contain a valid label string', 48 | self::BIDI => 'a label does not meet the IDNA BiDi requirements (for right-to-left characters)', 49 | self::CONTEXTJ => 'a label does not meet the IDNA CONTEXTJ requirements', 50 | self::CONTEXTO_DIGITS => 'a label does not meet the IDNA CONTEXTO requirements for digits', 51 | self::CONTEXTO_PUNCTUATION => 'a label does not meet the IDNA CONTEXTO requirements for punctuation characters. Some punctuation characters "Would otherwise have been DISALLOWED" but are allowed in certain contexts', 52 | }; 53 | } 54 | 55 | public static function filterByErrorBytes(int $errors): array 56 | { 57 | return array_values( 58 | array_filter( 59 | self::cases(), 60 | fn (self $error): bool => 0 !== ($error->value & $errors) 61 | ) 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Idna/Option.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Idna; 15 | 16 | use ReflectionClass; 17 | use ReflectionClassConstant; 18 | 19 | /** 20 | * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html 21 | */ 22 | final class Option 23 | { 24 | private const DEFAULT = 0; 25 | private const ALLOW_UNASSIGNED = 1; 26 | private const USE_STD3_RULES = 2; 27 | private const CHECK_BIDI = 4; 28 | private const CHECK_CONTEXTJ = 8; 29 | private const NONTRANSITIONAL_TO_ASCII = 0x10; 30 | private const NONTRANSITIONAL_TO_UNICODE = 0x20; 31 | private const CHECK_CONTEXTO = 0x40; 32 | 33 | private function __construct(private readonly int $value) 34 | { 35 | } 36 | 37 | private static function cases(): array 38 | { 39 | static $assoc; 40 | if (null === $assoc) { 41 | $assoc = []; 42 | $fooClass = new ReflectionClass(self::class); 43 | foreach ($fooClass->getConstants(ReflectionClassConstant::IS_PRIVATE) as $name => $value) { 44 | $assoc[$name] = $value; 45 | } 46 | } 47 | 48 | return $assoc; 49 | } 50 | 51 | public static function new(int $bytes = self::DEFAULT): self 52 | { 53 | return new self(array_reduce( 54 | self::cases(), 55 | fn (int $value, int $option) => 0 !== ($option & $bytes) ? ($value | $option) : $value, 56 | self::DEFAULT 57 | )); 58 | } 59 | 60 | public static function forIDNA2008Ascii(): self 61 | { 62 | return self::new() 63 | ->nonTransitionalToAscii() 64 | ->checkBidi() 65 | ->useSTD3Rules() 66 | ->checkContextJ(); 67 | } 68 | 69 | public static function forIDNA2008Unicode(): self 70 | { 71 | return self::new() 72 | ->nonTransitionalToUnicode() 73 | ->checkBidi() 74 | ->useSTD3Rules() 75 | ->checkContextJ(); 76 | } 77 | 78 | public function toBytes(): int 79 | { 80 | return $this->value; 81 | } 82 | 83 | /** array */ 84 | public function list(): array 85 | { 86 | return array_keys(array_filter( 87 | self::cases(), 88 | fn (int $value) => 0 !== ($value & $this->value) 89 | )); 90 | } 91 | 92 | public function allowUnassigned(): self 93 | { 94 | return $this->add(self::ALLOW_UNASSIGNED); 95 | } 96 | 97 | public function disallowUnassigned(): self 98 | { 99 | return $this->remove(self::ALLOW_UNASSIGNED); 100 | } 101 | 102 | public function useSTD3Rules(): self 103 | { 104 | return $this->add(self::USE_STD3_RULES); 105 | } 106 | 107 | public function prohibitSTD3Rules(): self 108 | { 109 | return $this->remove(self::USE_STD3_RULES); 110 | } 111 | 112 | public function checkBidi(): self 113 | { 114 | return $this->add(self::CHECK_BIDI); 115 | } 116 | 117 | public function ignoreBidi(): self 118 | { 119 | return $this->remove(self::CHECK_BIDI); 120 | } 121 | 122 | public function checkContextJ(): self 123 | { 124 | return $this->add(self::CHECK_CONTEXTJ); 125 | } 126 | 127 | public function ignoreContextJ(): self 128 | { 129 | return $this->remove(self::CHECK_CONTEXTJ); 130 | } 131 | 132 | public function checkContextO(): self 133 | { 134 | return $this->add(self::CHECK_CONTEXTO); 135 | } 136 | 137 | public function ignoreContextO(): self 138 | { 139 | return $this->remove(self::CHECK_CONTEXTO); 140 | } 141 | 142 | public function nonTransitionalToAscii(): self 143 | { 144 | return $this->add(self::NONTRANSITIONAL_TO_ASCII); 145 | } 146 | 147 | public function transitionalToAscii(): self 148 | { 149 | return $this->remove(self::NONTRANSITIONAL_TO_ASCII); 150 | } 151 | 152 | public function nonTransitionalToUnicode(): self 153 | { 154 | return $this->add(self::NONTRANSITIONAL_TO_UNICODE); 155 | } 156 | 157 | public function transitionalToUnicode(): self 158 | { 159 | return $this->remove(self::NONTRANSITIONAL_TO_UNICODE); 160 | } 161 | 162 | public function add(Option|int|null $option = null): self 163 | { 164 | return match (true) { 165 | null === $option => $this, 166 | $option instanceof self => self::new($this->value | $option->value), 167 | default => self::new($this->value | $option), 168 | }; 169 | } 170 | 171 | public function remove(Option|int|null $option = null): self 172 | { 173 | return match (true) { 174 | null === $option => $this, 175 | $option instanceof self => self::new($this->value & ~$option->value), 176 | default => self::new($this->value & ~$option), 177 | }; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/Idna/Result.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\Idna; 15 | 16 | /** 17 | * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html 18 | */ 19 | final class Result 20 | { 21 | private function __construct( 22 | private readonly string $domain, 23 | private readonly bool $isTransitionalDifferent, 24 | /** @var array */ 25 | private readonly array $errors 26 | ) { 27 | } 28 | 29 | /** 30 | * @param array{result:string, isTransitionalDifferent:bool, errors:int} $infos 31 | */ 32 | public static function fromIntl(array $infos): self 33 | { 34 | return new self($infos['result'], $infos['isTransitionalDifferent'], Error::filterByErrorBytes($infos['errors'])); 35 | } 36 | 37 | public function domain(): string 38 | { 39 | return $this->domain; 40 | } 41 | 42 | public function isTransitionalDifferent(): bool 43 | { 44 | return $this->isTransitionalDifferent; 45 | } 46 | 47 | /** 48 | * @return array 49 | */ 50 | public function errors(): array 51 | { 52 | return $this->errors; 53 | } 54 | 55 | public function hasErrors(): bool 56 | { 57 | return [] !== $this->errors; 58 | } 59 | 60 | public function hasError(Error $error): bool 61 | { 62 | return in_array($error, $this->errors, true); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 ignace nyamagana butera 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/league/uri-interfaces/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "league/uri-interfaces", 3 | "type": "library", 4 | "description" : "Common interfaces and classes for URI representation and interaction", 5 | "keywords": [ 6 | "url", 7 | "uri", 8 | "rfc3986", 9 | "rfc3987", 10 | "rfc6570", 11 | "psr-7", 12 | "parse_url", 13 | "http", 14 | "https", 15 | "ws", 16 | "ftp", 17 | "data-uri", 18 | "file-uri", 19 | "parse_str", 20 | "query-string", 21 | "querystring", 22 | "hostname" 23 | ], 24 | "license": "MIT", 25 | "homepage": "https://uri.thephpleague.com", 26 | "authors": [ 27 | { 28 | "name" : "Ignace Nyamagana Butera", 29 | "email" : "nyamsprod@gmail.com", 30 | "homepage" : "https://nyamsprod.com" 31 | } 32 | ], 33 | "funding": [ 34 | { 35 | "type": "github", 36 | "url": "https://github.com/sponsors/nyamsprod" 37 | } 38 | ], 39 | "require": { 40 | "php" : "^8.1", 41 | "ext-filter": "*", 42 | "psr/http-message": "^1.1 || ^2.0", 43 | "psr/http-factory": "^1" 44 | }, 45 | "autoload": { 46 | "psr-4": { 47 | "League\\Uri\\": "" 48 | } 49 | }, 50 | "suggest": { 51 | "ext-bcmath": "to improve IPV4 host parsing", 52 | "ext-gmp": "to improve IPV4 host parsing", 53 | "ext-intl": "to handle IDN host with the best performance", 54 | "php-64bit": "to improve IPV4 host parsing", 55 | "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" 56 | }, 57 | "extra": { 58 | "branch-alias": { 59 | "dev-master": "7.x-dev" 60 | } 61 | }, 62 | "support": { 63 | "forum": "https://thephpleague.slack.com", 64 | "docs": "https://uri.thephpleague.com", 65 | "issues": "https://github.com/thephpleague/uri-src/issues" 66 | }, 67 | "config": { 68 | "sort-packages": true 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /vendor/league/uri/HttpFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri; 15 | 16 | use Psr\Http\Message\UriFactoryInterface; 17 | use Psr\Http\Message\UriInterface; 18 | 19 | final class HttpFactory implements UriFactoryInterface 20 | { 21 | public function createUri(string $uri = ''): UriInterface 22 | { 23 | return Http::new($uri); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vendor/league/uri/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 ignace nyamagana butera 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/league/uri/UriInfo.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri; 15 | 16 | use Deprecated; 17 | use League\Uri\Contracts\UriInterface; 18 | use Psr\Http\Message\UriInterface as Psr7UriInterface; 19 | 20 | /** 21 | * @deprecated since version 7.0.0 22 | * @codeCoverageIgnore 23 | * @see BaseUri 24 | */ 25 | final class UriInfo 26 | { 27 | /** 28 | * @codeCoverageIgnore 29 | */ 30 | private function __construct() 31 | { 32 | } 33 | 34 | /** 35 | * Tells whether the URI represents an absolute URI. 36 | */ 37 | #[Deprecated(message:'use League\Uri\BaseUri::isAbsolute() instead', since:'league/uri:7.0.0')] 38 | public static function isAbsolute(Psr7UriInterface|UriInterface $uri): bool 39 | { 40 | return BaseUri::from($uri)->isAbsolute(); 41 | } 42 | 43 | /** 44 | * Tell whether the URI represents a network path. 45 | */ 46 | #[Deprecated(message:'use League\Uri\BaseUri::isNetworkPath() instead', since:'league/uri:7.0.0')] 47 | public static function isNetworkPath(Psr7UriInterface|UriInterface $uri): bool 48 | { 49 | return BaseUri::from($uri)->isNetworkPath(); 50 | } 51 | 52 | /** 53 | * Tells whether the URI represents an absolute path. 54 | */ 55 | #[Deprecated(message:'use League\Uri\BaseUri::isAbsolutePath() instead', since:'league/uri:7.0.0')] 56 | public static function isAbsolutePath(Psr7UriInterface|UriInterface $uri): bool 57 | { 58 | return BaseUri::from($uri)->isAbsolutePath(); 59 | } 60 | 61 | /** 62 | * Tell whether the URI represents a relative path. 63 | * 64 | */ 65 | #[Deprecated(message:'use League\Uri\BaseUri::isRelativePath() instead', since:'league/uri:7.0.0')] 66 | public static function isRelativePath(Psr7UriInterface|UriInterface $uri): bool 67 | { 68 | return BaseUri::from($uri)->isRelativePath(); 69 | } 70 | 71 | /** 72 | * Tells whether both URI refers to the same document. 73 | */ 74 | #[Deprecated(message:'use League\Uri\BaseUri::isSameDocument() instead', since:'league/uri:7.0.0')] 75 | public static function isSameDocument(Psr7UriInterface|UriInterface $uri, Psr7UriInterface|UriInterface $baseUri): bool 76 | { 77 | return BaseUri::from($baseUri)->isSameDocument($uri); 78 | } 79 | 80 | /** 81 | * Returns the URI origin property as defined by WHATWG URL living standard. 82 | * 83 | * {@see https://url.spec.whatwg.org/#origin} 84 | * 85 | * For URI without a special scheme the method returns null 86 | * For URI with the file scheme the method will return null (as this is left to the implementation decision) 87 | * For URI with a special scheme the method returns the scheme followed by its authority (without the userinfo part) 88 | */ 89 | #[Deprecated(message:'use League\Uri\BaseUri::origin() instead', since:'league/uri:7.0.0')] 90 | public static function getOrigin(Psr7UriInterface|UriInterface $uri): ?string 91 | { 92 | return BaseUri::from($uri)->origin()?->__toString(); 93 | } 94 | 95 | /** 96 | * Tells whether two URI do not share the same origin. 97 | * 98 | * @see UriInfo::getOrigin() 99 | */ 100 | #[Deprecated(message:'use League\Uri\BaseUri::isCrossOrigin() instead', since:'league/uri:7.0.0')] 101 | public static function isCrossOrigin(Psr7UriInterface|UriInterface $uri, Psr7UriInterface|UriInterface $baseUri): bool 102 | { 103 | return BaseUri::from($baseUri)->isCrossOrigin($uri); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /vendor/league/uri/UriResolver.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri; 15 | 16 | use Deprecated; 17 | use League\Uri\Contracts\UriInterface; 18 | use Psr\Http\Message\UriInterface as Psr7UriInterface; 19 | 20 | /** 21 | * @deprecated since version 7.0.0 22 | * @codeCoverageIgnore 23 | * @see BaseUri 24 | */ 25 | final class UriResolver 26 | { 27 | /** 28 | * Resolves a URI against a base URI using RFC3986 rules. 29 | * 30 | * This method MUST retain the state of the submitted URI instance, and return 31 | * a URI instance of the same type that contains the applied modifications. 32 | * 33 | * This method MUST be transparent when dealing with error and exceptions. 34 | * It MUST not alter or silence them apart from validating its own parameters. 35 | */ 36 | #[Deprecated(message:'use League\Uri\BaseUri::resolve() instead', since:'league/uri:7.0.0')] 37 | public static function resolve(Psr7UriInterface|UriInterface $uri, Psr7UriInterface|UriInterface $baseUri): Psr7UriInterface|UriInterface 38 | { 39 | return BaseUri::from($baseUri)->resolve($uri)->getUri(); 40 | } 41 | 42 | /** 43 | * Relativizes a URI according to a base URI. 44 | * 45 | * This method MUST retain the state of the submitted URI instance, and return 46 | * a URI instance of the same type that contains the applied modifications. 47 | * 48 | * This method MUST be transparent when dealing with error and exceptions. 49 | * It MUST not alter or silence them apart from validating its own parameters. 50 | */ 51 | #[Deprecated(message:'use League\Uri\BaseUri::relativize() instead', since:'league/uri:7.0.0')] 52 | public static function relativize(Psr7UriInterface|UriInterface $uri, Psr7UriInterface|UriInterface $baseUri): Psr7UriInterface|UriInterface 53 | { 54 | return BaseUri::from($baseUri)->relativize($uri)->getUri(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vendor/league/uri/UriTemplate.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri; 15 | 16 | use League\Uri\Contracts\UriException; 17 | use League\Uri\Contracts\UriInterface; 18 | use League\Uri\Exceptions\SyntaxError; 19 | use League\Uri\UriTemplate\Template; 20 | use League\Uri\UriTemplate\TemplateCanNotBeExpanded; 21 | use League\Uri\UriTemplate\VariableBag; 22 | use Stringable; 23 | 24 | use function array_fill_keys; 25 | use function array_key_exists; 26 | 27 | /** 28 | * Defines the URI Template syntax and the process for expanding a URI Template into a URI reference. 29 | * 30 | * @link https://tools.ietf.org/html/rfc6570 31 | * @package League\Uri 32 | * @author Ignace Nyamagana Butera 33 | * @since 6.1.0 34 | */ 35 | final class UriTemplate 36 | { 37 | private readonly Template $template; 38 | private readonly VariableBag $defaultVariables; 39 | 40 | /** 41 | * @throws SyntaxError if the template syntax is invalid 42 | * @throws TemplateCanNotBeExpanded if the template or the variables are invalid 43 | */ 44 | public function __construct(Stringable|string $template, iterable $defaultVariables = []) 45 | { 46 | $this->template = $template instanceof Template ? $template : Template::new($template); 47 | $this->defaultVariables = $this->filterVariables($defaultVariables); 48 | } 49 | 50 | private function filterVariables(iterable $variables): VariableBag 51 | { 52 | if (!$variables instanceof VariableBag) { 53 | $variables = new VariableBag($variables); 54 | } 55 | 56 | return $variables 57 | ->filter(fn ($value, string|int $name) => array_key_exists( 58 | $name, 59 | array_fill_keys($this->template->variableNames, 1) 60 | )); 61 | } 62 | 63 | public function getTemplate(): string 64 | { 65 | return $this->template->value; 66 | } 67 | 68 | /** 69 | * @return array 70 | */ 71 | public function getVariableNames(): array 72 | { 73 | return $this->template->variableNames; 74 | } 75 | 76 | public function getDefaultVariables(): array 77 | { 78 | return iterator_to_array($this->defaultVariables); 79 | } 80 | 81 | /** 82 | * Returns a new instance with the updated default variables. 83 | * 84 | * This method MUST retain the state of the current instance, and return 85 | * an instance that contains the modified default variables. 86 | * 87 | * If present, variables whose name is not part of the current template 88 | * possible variable names are removed. 89 | * 90 | * @throws TemplateCanNotBeExpanded if the variables are invalid 91 | */ 92 | public function withDefaultVariables(iterable $defaultVariables): self 93 | { 94 | $defaultVariables = $this->filterVariables($defaultVariables); 95 | if ($defaultVariables == $this->defaultVariables) { 96 | return $this; 97 | } 98 | 99 | return new self($this->template, $defaultVariables); 100 | } 101 | 102 | /** 103 | * @throws TemplateCanNotBeExpanded if the variables are invalid 104 | * @throws UriException if the resulting expansion cannot be converted to a UriInterface instance 105 | */ 106 | public function expand(iterable $variables = []): UriInterface 107 | { 108 | return Uri::new($this->template->expand( 109 | $this->filterVariables($variables)->replace($this->defaultVariables) 110 | )); 111 | } 112 | 113 | /** 114 | * @throws TemplateCanNotBeExpanded if the variables are invalid or missing 115 | * @throws UriException if the resulting expansion cannot be converted to a UriInterface instance 116 | */ 117 | public function expandOrFail(iterable $variables = []): UriInterface 118 | { 119 | return Uri::new($this->template->expandOrFail( 120 | $this->filterVariables($variables)->replace($this->defaultVariables) 121 | )); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /vendor/league/uri/UriTemplate/Expression.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\UriTemplate; 15 | 16 | use Deprecated; 17 | use League\Uri\Exceptions\SyntaxError; 18 | use Stringable; 19 | 20 | use function array_filter; 21 | use function array_map; 22 | use function array_unique; 23 | use function explode; 24 | use function implode; 25 | 26 | /** 27 | * @internal The class exposes the internal representation of an Expression and its usage 28 | * @link https://www.rfc-editor.org/rfc/rfc6570#section-2.2 29 | */ 30 | final class Expression 31 | { 32 | /** @var array */ 33 | private readonly array $varSpecifiers; 34 | /** @var array */ 35 | public readonly array $variableNames; 36 | public readonly string $value; 37 | 38 | private function __construct(public readonly Operator $operator, VarSpecifier ...$varSpecifiers) 39 | { 40 | $this->varSpecifiers = $varSpecifiers; 41 | $this->variableNames = array_unique( 42 | array_map( 43 | static fn (VarSpecifier $varSpecifier): string => $varSpecifier->name, 44 | $varSpecifiers 45 | ) 46 | ); 47 | $this->value = '{'.$operator->value.implode(',', array_map( 48 | static fn (VarSpecifier $varSpecifier): string => $varSpecifier->toString(), 49 | $varSpecifiers 50 | )).'}'; 51 | } 52 | 53 | /** 54 | * @throws SyntaxError if the expression is invalid 55 | */ 56 | public static function new(Stringable|string $expression): self 57 | { 58 | $parts = Operator::parseExpression($expression); 59 | 60 | return new Expression($parts['operator'], ...array_map( 61 | static fn (string $varSpec): VarSpecifier => VarSpecifier::new($varSpec), 62 | explode(',', $parts['variables']) 63 | )); 64 | } 65 | 66 | /** 67 | * DEPRECATION WARNING! This method will be removed in the next major point release. 68 | * 69 | * @throws SyntaxError if the expression is invalid 70 | * @see Expression::new() 71 | * 72 | * @deprecated Since version 7.0.0 73 | * @codeCoverageIgnore 74 | */ 75 | #[Deprecated(message:'use League\Uri\UriTemplate\Exppression::new() instead', since:'league/uri:7.0.0')] 76 | public static function createFromString(Stringable|string $expression): self 77 | { 78 | return self::new($expression); 79 | } 80 | 81 | public function expand(VariableBag $variables): string 82 | { 83 | $expanded = implode( 84 | $this->operator->separator(), 85 | array_filter( 86 | array_map( 87 | fn (VarSpecifier $varSpecifier): string => $this->operator->expand($varSpecifier, $variables), 88 | $this->varSpecifiers 89 | ), 90 | static fn ($value): bool => '' !== $value 91 | ) 92 | ); 93 | 94 | return match ('') { 95 | $expanded => '', 96 | default => $this->operator->first().$expanded, 97 | }; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /vendor/league/uri/UriTemplate/Template.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\UriTemplate; 15 | 16 | use Deprecated; 17 | use League\Uri\Exceptions\SyntaxError; 18 | use Stringable; 19 | 20 | use function array_filter; 21 | use function array_map; 22 | use function array_reduce; 23 | use function array_unique; 24 | use function preg_match_all; 25 | use function preg_replace; 26 | use function str_contains; 27 | use function str_replace; 28 | 29 | use const PREG_SET_ORDER; 30 | 31 | /** 32 | * @internal The class exposes the internal representation of a Template and its usage 33 | */ 34 | final class Template implements Stringable 35 | { 36 | /** 37 | * Expression regular expression pattern. 38 | */ 39 | private const REGEXP_EXPRESSION_DETECTOR = '/(?\{[^}]*})/x'; 40 | 41 | /** @var array */ 42 | private readonly array $expressions; 43 | /** @var array */ 44 | public readonly array $variableNames; 45 | 46 | private function __construct(public readonly string $value, Expression ...$expressions) 47 | { 48 | $this->expressions = $expressions; 49 | $this->variableNames = array_unique( 50 | array_merge( 51 | ...array_map( 52 | static fn (Expression $expression): array => $expression->variableNames, 53 | $expressions 54 | ) 55 | ) 56 | ); 57 | } 58 | 59 | /** 60 | * @throws SyntaxError if the template contains invalid expressions 61 | * @throws SyntaxError if the template contains invalid variable specification 62 | */ 63 | public static function new(Stringable|string $template): self 64 | { 65 | $template = (string) $template; 66 | /** @var string $remainder */ 67 | $remainder = preg_replace(self::REGEXP_EXPRESSION_DETECTOR, '', $template); 68 | if (str_contains($remainder, '{') || str_contains($remainder, '}')) { 69 | throw new SyntaxError('The template "'.$template.'" contains invalid expressions.'); 70 | } 71 | 72 | preg_match_all(self::REGEXP_EXPRESSION_DETECTOR, $template, $founds, PREG_SET_ORDER); 73 | 74 | return new self($template, ...array_values( 75 | array_reduce($founds, function (array $carry, array $found): array { 76 | if (!isset($carry[$found['expression']])) { 77 | $carry[$found['expression']] = Expression::new($found['expression']); 78 | } 79 | 80 | return $carry; 81 | }, []) 82 | )); 83 | } 84 | 85 | /** 86 | * @throws TemplateCanNotBeExpanded if the variables are invalid 87 | */ 88 | public function expand(iterable $variables = []): string 89 | { 90 | if (!$variables instanceof VariableBag) { 91 | $variables = new VariableBag($variables); 92 | } 93 | 94 | return $this->expandAll($variables); 95 | } 96 | 97 | /** 98 | * @throws TemplateCanNotBeExpanded if the variables are invalid or missing 99 | */ 100 | public function expandOrFail(iterable $variables = []): string 101 | { 102 | if (!$variables instanceof VariableBag) { 103 | $variables = new VariableBag($variables); 104 | } 105 | 106 | $missing = array_filter($this->variableNames, fn (string $name): bool => !isset($variables[$name])); 107 | if ([] !== $missing) { 108 | throw TemplateCanNotBeExpanded::dueToMissingVariables(...$missing); 109 | } 110 | 111 | return $this->expandAll($variables); 112 | } 113 | 114 | private function expandAll(VariableBag $variables): string 115 | { 116 | return array_reduce( 117 | $this->expressions, 118 | fn (string $uri, Expression $expr): string => str_replace($expr->value, $expr->expand($variables), $uri), 119 | $this->value 120 | ); 121 | } 122 | 123 | public function __toString(): string 124 | { 125 | return $this->value; 126 | } 127 | 128 | /** 129 | * DEPRECATION WARNING! This method will be removed in the next major point release. 130 | * 131 | * @throws SyntaxError if the template contains invalid expressions 132 | * @throws SyntaxError if the template contains invalid variable specification 133 | * @deprecated Since version 7.0.0 134 | * @codeCoverageIgnore 135 | * @see Template::new() 136 | * 137 | * Create a new instance from a string. 138 | * 139 | */ 140 | #[Deprecated(message:'use League\Uri\UriTemplate\Template::new() instead', since:'league/uri:7.0.0')] 141 | public static function createFromString(Stringable|string $template): self 142 | { 143 | return self::new($template); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /vendor/league/uri/UriTemplate/TemplateCanNotBeExpanded.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\UriTemplate; 15 | 16 | use InvalidArgumentException; 17 | use League\Uri\Contracts\UriException; 18 | 19 | class TemplateCanNotBeExpanded extends InvalidArgumentException implements UriException 20 | { 21 | public readonly array $variablesNames; 22 | 23 | public function __construct(string $message = '', string ...$variableNames) 24 | { 25 | parent::__construct($message, 0, null); 26 | 27 | $this->variablesNames = $variableNames; 28 | } 29 | 30 | public static function dueToUnableToProcessValueListWithPrefix(string $variableName): self 31 | { 32 | return new self('The ":" modifier cannot be applied on "'.$variableName.'" since it is a list of values.', $variableName); 33 | } 34 | 35 | public static function dueToNestedListOfValue(string $variableName): self 36 | { 37 | return new self('The "'.$variableName.'" cannot be a nested list.', $variableName); 38 | } 39 | 40 | public static function dueToMissingVariables(string ...$variableNames): self 41 | { 42 | return new self('The following required variables are missing: `'.implode('`, `', $variableNames).'`.', ...$variableNames); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /vendor/league/uri/UriTemplate/VarSpecifier.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\UriTemplate; 15 | 16 | use League\Uri\Exceptions\SyntaxError; 17 | 18 | use function preg_match; 19 | 20 | /** 21 | * @internal The class exposes the internal representation of a Var Specifier 22 | * @link https://www.rfc-editor.org/rfc/rfc6570#section-2.3 23 | */ 24 | final class VarSpecifier 25 | { 26 | /** 27 | * Variables specification regular expression pattern. 28 | * 29 | * @link https://tools.ietf.org/html/rfc6570#section-2.3 30 | */ 31 | private const REGEXP_VARSPEC = '/^(?(?:[A-z0-9_\.]|%[0-9a-fA-F]{2})+)(?\:(?\d+)|\*)?$/'; 32 | 33 | private const MODIFIER_POSITION_MAX_POSITION = 10_000; 34 | 35 | private function __construct( 36 | public readonly string $name, 37 | public readonly string $modifier, 38 | public readonly int $position 39 | ) { 40 | } 41 | 42 | public static function new(string $specification): self 43 | { 44 | if (1 !== preg_match(self::REGEXP_VARSPEC, $specification, $parsed)) { 45 | throw new SyntaxError('The variable specification "'.$specification.'" is invalid.'); 46 | } 47 | 48 | $properties = ['name' => $parsed['name'], 'modifier' => $parsed['modifier'] ?? '', 'position' => $parsed['position'] ?? '']; 49 | 50 | if ('' !== $properties['position']) { 51 | $properties['position'] = (int) $properties['position']; 52 | $properties['modifier'] = ':'; 53 | } 54 | 55 | if ('' === $properties['position']) { 56 | $properties['position'] = 0; 57 | } 58 | 59 | if (self::MODIFIER_POSITION_MAX_POSITION <= $properties['position']) { 60 | throw new SyntaxError('The variable specification "'.$specification.'" is invalid the position modifier must be lower than 10000.'); 61 | } 62 | 63 | return new self($properties['name'], $properties['modifier'], $properties['position']); 64 | } 65 | 66 | public function toString(): string 67 | { 68 | return $this->name.$this->modifier.match (true) { 69 | 0 < $this->position => $this->position, 70 | default => '', 71 | }; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /vendor/league/uri/UriTemplate/VariableBag.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace League\Uri\UriTemplate; 15 | 16 | use ArrayAccess; 17 | use Closure; 18 | use Countable; 19 | use IteratorAggregate; 20 | use Stringable; 21 | use Traversable; 22 | 23 | use function array_filter; 24 | use function is_bool; 25 | use function is_scalar; 26 | 27 | use const ARRAY_FILTER_USE_BOTH; 28 | 29 | /** 30 | * @internal The class exposes the internal representation of variable bags 31 | * 32 | * @phpstan-type InputValue string|bool|int|float|array 33 | * 34 | * @implements ArrayAccess 35 | * @implements IteratorAggregate 36 | */ 37 | final class VariableBag implements ArrayAccess, Countable, IteratorAggregate 38 | { 39 | /** 40 | * @var array> 41 | */ 42 | private array $variables = []; 43 | 44 | /** 45 | * @param iterable $variables 46 | */ 47 | public function __construct(iterable $variables = []) 48 | { 49 | foreach ($variables as $name => $value) { 50 | $this->assign((string) $name, $value); 51 | } 52 | } 53 | 54 | public function count(): int 55 | { 56 | return count($this->variables); 57 | } 58 | 59 | public function getIterator(): Traversable 60 | { 61 | yield from $this->variables; 62 | } 63 | 64 | public function offsetExists(mixed $offset): bool 65 | { 66 | return array_key_exists($offset, $this->variables); 67 | } 68 | 69 | public function offsetUnset(mixed $offset): void 70 | { 71 | unset($this->variables[$offset]); 72 | } 73 | 74 | public function offsetSet(mixed $offset, mixed $value): void 75 | { 76 | $this->assign($offset, $value); /* @phpstan-ignore-line */ 77 | } 78 | 79 | public function offsetGet(mixed $offset): mixed 80 | { 81 | return $this->fetch($offset); 82 | } 83 | 84 | /** 85 | * Tells whether the bag is empty or not. 86 | */ 87 | public function isEmpty(): bool 88 | { 89 | return [] === $this->variables; 90 | } 91 | 92 | /** 93 | * Tells whether the bag is empty or not. 94 | */ 95 | public function isNotEmpty(): bool 96 | { 97 | return [] !== $this->variables; 98 | } 99 | 100 | /** 101 | * Fetches the variable value if none found returns null. 102 | * 103 | * @return null|string|array 104 | */ 105 | public function fetch(string $name): null|string|array 106 | { 107 | return $this->variables[$name] ?? null; 108 | } 109 | 110 | /** 111 | * @param Stringable|InputValue $value 112 | */ 113 | public function assign(string $name, Stringable|string|bool|int|float|array|null $value): void 114 | { 115 | $this->variables[$name] = $this->normalizeValue($value, $name, true); 116 | } 117 | 118 | /** 119 | * @param Stringable|InputValue $value 120 | * 121 | * @throws TemplateCanNotBeExpanded if the value contains nested list 122 | */ 123 | private function normalizeValue( 124 | Stringable|string|float|int|bool|array|null $value, 125 | string $name, 126 | bool $isNestedListAllowed 127 | ): array|string { 128 | return match (true) { 129 | is_bool($value) => true === $value ? '1' : '0', 130 | (null === $value || is_scalar($value) || $value instanceof Stringable) => (string) $value, 131 | !$isNestedListAllowed => throw TemplateCanNotBeExpanded::dueToNestedListOfValue($name), 132 | default => array_map(fn ($var): array|string => self::normalizeValue($var, $name, false), $value), 133 | }; 134 | } 135 | 136 | /** 137 | * Replaces elements from passed variables into the current instance. 138 | */ 139 | public function replace(VariableBag $variables): self 140 | { 141 | return new self($this->variables + $variables->variables); 142 | } 143 | 144 | /** 145 | * Filters elements using the closure. 146 | */ 147 | public function filter(Closure $fn): self 148 | { 149 | return new self(array_filter($this->variables, $fn, ARRAY_FILTER_USE_BOTH)); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /vendor/league/uri/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "league/uri", 3 | "type": "library", 4 | "description" : "URI manipulation library", 5 | "keywords": [ 6 | "url", 7 | "uri", 8 | "rfc3986", 9 | "rfc3987", 10 | "rfc6570", 11 | "psr-7", 12 | "parse_url", 13 | "http", 14 | "https", 15 | "ws", 16 | "ftp", 17 | "data-uri", 18 | "file-uri", 19 | "middleware", 20 | "parse_str", 21 | "query-string", 22 | "querystring", 23 | "hostname", 24 | "uri-template" 25 | ], 26 | "license": "MIT", 27 | "homepage": "https://uri.thephpleague.com", 28 | "authors": [ 29 | { 30 | "name" : "Ignace Nyamagana Butera", 31 | "email" : "nyamsprod@gmail.com", 32 | "homepage" : "https://nyamsprod.com" 33 | } 34 | ], 35 | "support": { 36 | "forum": "https://thephpleague.slack.com", 37 | "docs": "https://uri.thephpleague.com", 38 | "issues": "https://github.com/thephpleague/uri-src/issues" 39 | }, 40 | "funding": [ 41 | { 42 | "type": "github", 43 | "url": "https://github.com/sponsors/nyamsprod" 44 | } 45 | ], 46 | "require": { 47 | "php": "^8.1", 48 | "league/uri-interfaces": "^7.5" 49 | }, 50 | "autoload": { 51 | "psr-4": { 52 | "League\\Uri\\": "" 53 | } 54 | }, 55 | "conflict": { 56 | "league/uri-schemes": "^1.0" 57 | }, 58 | "suggest": { 59 | "ext-bcmath": "to improve IPV4 host parsing", 60 | "ext-fileinfo": "to create Data URI from file contennts", 61 | "ext-gmp": "to improve IPV4 host parsing", 62 | "ext-intl": "to handle IDN host with the best performance", 63 | "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", 64 | "league/uri-components" : "Needed to easily manipulate URI objects components", 65 | "php-64bit": "to improve IPV4 host parsing", 66 | "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" 67 | }, 68 | "extra": { 69 | "branch-alias": { 70 | "dev-master": "7.x-dev" 71 | } 72 | }, 73 | "config": { 74 | "sort-packages": true 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /vendor/masterminds/html5/CREDITS: -------------------------------------------------------------------------------- 1 | Matt Butcher [technosophos] (lead) 2 | Matt Farina [mattfarina] (lead) 3 | Asmir Mustafic [goetas] (contributor) 4 | Edward Z. Yang [ezyang] (contributor) 5 | Geoffrey Sneddon [gsnedders] (contributor) 6 | Kukhar Vasily [ngreduce] (contributor) 7 | Rune Christensen [MrElectronic] (contributor) 8 | Mišo Belica [miso-belica] (contributor) 9 | Asmir Mustafic [goetas] (contributor) 10 | KITAITI Makoto [KitaitiMakoto] (contributor) 11 | Jacob Floyd [cognifloyd] (contributor) 12 | -------------------------------------------------------------------------------- /vendor/masterminds/html5/LICENSE.txt: -------------------------------------------------------------------------------- 1 | ## HTML5-PHP License 2 | 3 | Copyright (c) 2013 The Authors of HTML5-PHP 4 | 5 | Matt Butcher - mattbutcher@google.com 6 | Matt Farina - matt@mattfarina.com 7 | Asmir Mustafic - goetas@gmail.com 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of 10 | this software and associated documentation files (the "Software"), to deal in 11 | the Software without restriction, including without limitation the rights to 12 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | the Software, and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 21 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 22 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 23 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | ## HTML5Lib License 27 | 28 | Portions of this are based on html5lib's PHP version, which was a 29 | sub-project of html5lib. The following is the list of contributors from 30 | html5lib: 31 | 32 | html5lib: 33 | 34 | Copyright (c) 2006-2009 The Authors 35 | 36 | Contributors: 37 | James Graham - jg307@cam.ac.uk 38 | Anne van Kesteren - annevankesteren@gmail.com 39 | Lachlan Hunt - lachlan.hunt@lachy.id.au 40 | Matt McDonald - kanashii@kanashii.ca 41 | Sam Ruby - rubys@intertwingly.net 42 | Ian Hickson (Google) - ian@hixie.ch 43 | Thomas Broyer - t.broyer@ltgt.net 44 | Jacques Distler - distler@golem.ph.utexas.edu 45 | Henri Sivonen - hsivonen@iki.fi 46 | Adam Barth - abarth@webkit.org 47 | Eric Seidel - eric@webkit.org 48 | The Mozilla Foundation (contributions from Henri Sivonen since 2008) 49 | David Flanagan (Mozilla) - dflanagan@mozilla.com 50 | 51 | Permission is hereby granted, free of charge, to any person obtaining a copy of 52 | this software and associated documentation files (the "Software"), to deal in 53 | the Software without restriction, including without limitation the rights to 54 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 55 | the Software, and to permit persons to whom the Software is furnished to do so, 56 | subject to the following conditions: 57 | 58 | The above copyright notice and this permission notice shall be included in all 59 | copies or substantial portions of the Software. 60 | 61 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 63 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 64 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 65 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 66 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 67 | -------------------------------------------------------------------------------- /vendor/masterminds/html5/RELEASE.md: -------------------------------------------------------------------------------- 1 | # Release Notes 2 | 3 | 2.7.6 (2021-08-18) 4 | 5 | - #218: Address comment handling issues 6 | 7 | 2.7.5 (2021-07-01) 8 | 9 | - #204: Travis: Enable tests on PHP 8.0 10 | - #207: Fix PHP 8.1 deprecations 11 | 12 | 2.7.4 (2020-10-01) 13 | 14 | - #191: Fix travisci build 15 | - #195: Add .gitattributes file with export-ignore rules 16 | - #194: Fix query parameter parsed as character entity 17 | 18 | 2.7.3 (2020-07-05) 19 | 20 | - #190: mitigate cyclic reference between output rules and the traverser objects 21 | 22 | 2.7.2 (2020-07-01) 23 | 24 | - #187: Fixed memory leak in HTML5::saveHTML() 25 | - #186: Add special case for end tag
26 | 27 | 2.7.1 (2020-06-14) 28 | 29 | - #171: add PHP 7.4 job 30 | - #178: Prevent infinite loop on un-terminated entity declaration at EOF 31 | 32 | 2.7.0 (2019-07-25) 33 | 34 | - #164: Drop HHVM support 35 | - #168: Set default encoding in the DOMDocument object 36 | 37 | 2.6.0 (2019-03-10) 38 | 39 | - #163: Allow to pass a charset to the Scanner 40 | 41 | 2.5.0 (2018-12-27) 42 | 43 | - #162, #161, #155, #154, #153, #151: big performance improvements 44 | - #156: fixed typos 45 | - #160: adopt and enforce code style 46 | - #159: remove deprecated php unit base test case 47 | - #150: backport changes from old master branch 48 | 49 | 2.4.0 (2018-11-17) 50 | 51 | - #148: Improve performance by moving sequence matching 52 | - #147: Improve the Tokenizer performance 53 | - #146: Improve performance by relying on a native string instead of InputStream 54 | - #144: Add DOM extension in composer.json 55 | - #145: Add more extensions on composer.json, improve phpdocs and remove dead code 56 | - #143: Remove experimental comment 57 | 58 | 2.3.1 (2018-10-18) 59 | 60 | - #121: Audio is not a block tag (fixed by #141) 61 | - #136: Handle illegal self-closing according to spec (fixed by #137) 62 | - #141: Minor fixes in the README 63 | 64 | 2.3.0 (2017-09-04) 65 | 66 | - #129: image within inline svg breaks system (fixed by #133) 67 | - #131: ² does not work (fixed by #132) 68 | - #134: Improve tokenizer performance by 20% (alternative version of #130 thanks to @MichaelHeerklotz) 69 | - #135: Raw & in attributes 70 | 71 | 2.2.2 (2016-09-22) 72 | 73 | - #116: In XML mode, tags are case sensitive 74 | - #115: Fix PHP Notice in OutputRules 75 | - #112: fix parsing of options of an optgroup 76 | - #111: Adding test for the address tag 77 | 78 | 2.2.1 (2016-05-10) 79 | 80 | - #109: Fixed issue where address tag could be written without closing tag (thanks sylus) 81 | 82 | 2.2.0 (2016-04-11) 83 | 84 | - #105: Enable composer cache (for CI/CD) 85 | - #100: Use mb_substitute_character inset of ini_set for environments where ini_set is disable (e.g., shared hosting) 86 | - #98: Allow link, meta, style tags in noscript tags 87 | - #96: Fixed xml:href on svgs that use the "use" breaking 88 | - #94: Counting UTF8 characters performance improvement 89 | - #93: Use newer version of coveralls package 90 | - #90: Remove duplicate test 91 | - #87: Allow multiple root nodes 92 | 93 | 2.1.2 (2015-06-07) 94 | - #82: Support for PHP7 95 | - #84: Improved boolean attribute handling 96 | 97 | 2.1.1 (2015-03-23) 98 | - #78: Fixes bug where unmatched entity like string drops everything after &. 99 | 100 | 2.1.0 (2015-02-01) 101 | - #74: Added `disable_html_ns` and `target_doc` dom parsing options 102 | - Unified option names 103 | - #73: Fixed alphabet, ß now can be detected 104 | - #75 and #76: Allow whitespace in RCDATA tags 105 | - #77: Fixed parsing blunder for json embeds 106 | - #72: Add options to HTML methods 107 | 108 | 2.0.2 (2014-12-17) 109 | - #50: empty document handling 110 | - #63: tags with strange capitalization 111 | - #65: dashes and underscores as allowed characters in tag names 112 | - #68: Fixed issue with non-inline elements inside inline containers 113 | 114 | 2.0.1 (2014-09-23) 115 | - #59: Fixed issue parsing some fragments. 116 | - #56: Incorrectly saw 0 as empty string 117 | - Sami as new documentation generator 118 | 119 | 2.0.0 (2014-07-28) 120 | - #53: Improved boolean attributes handling 121 | - #52: Facebook HHVM compatibility 122 | - #48: Adopted PSR-2 as coding standard 123 | - #47: Moved everything to Masterminds namespace 124 | - #45: Added custom namespaces 125 | - #44: Added support to XML-style namespaces 126 | - #37: Refactored HTML5 class removing static methods 127 | 128 | 1.0.5 (2014-06-10) 129 | - #38: Set the dev-master branch as the 1.0.x branch for composer (goetas) 130 | - #34: Tests use PSR-4 for autoloading. (goetas) 131 | - #40, #41: Fix entity handling in RCDATA sections. (KitaitiMakoto) 132 | - #32: Fixed issue where wharacter references were being incorrectly encoded in style tags. 133 | 134 | 1.0.4 (2014-04-29) 135 | - #30/#31 Don't throw an exception for invalid tag names. 136 | 137 | 1.0.3 (2014-02-28) 138 | - #23 and #29: Ignore attributes with illegal chars in name for the PHP DOM. 139 | 140 | 1.0.2 (2014-02-12) 141 | - #23: Handle missing tag close in attribute list. 142 | - #25: Fixed text escaping in the serializer (HTML% 8.3). 143 | - #27: Fixed tests on Windows: changed "\n" -> PHP_EOL. 144 | - #28: Fixed infinite loop for char "&" in unquoted attribute in parser. 145 | - #26: Updated tag name case handling to deal with uppercase usage. 146 | - #24: Newlines and tabs are allowed inside quoted attributes (HTML5 8.2.4). 147 | - Fixed Travis CI testing. 148 | 149 | 1.0.1 (2013-11-07) 150 | - CDATA encoding is improved. (Non-standard; Issue #19) 151 | - Some parser rules were not returning the new current element. (Issue #20) 152 | - Added, to the README, details on code test coverage and to packagist version. 153 | - Fixed processor instructions. 154 | - Improved test coverage and documentation coverage. 155 | 156 | 1.0.0 (2013-10-02) 157 | - Initial release. 158 | -------------------------------------------------------------------------------- /vendor/masterminds/html5/UPGRADING.md: -------------------------------------------------------------------------------- 1 | From 1.x to 2.x 2 | ================= 3 | 4 | - All classes uses `Masterminds` namespace. 5 | - All public static methods has been removed from `HTML5` class and the general API to access the HTML5 functionalities has changed. 6 | 7 | Before: 8 | 9 | $dom = \HTML5::loadHTML('....'); 10 | \HTML5::saveHTML($dom); 11 | 12 | After: 13 | 14 | use Masterminds\HTML5; 15 | 16 | $html5 = new HTML5(); 17 | 18 | $dom = $html5->loadHTML('....'); 19 | echo $html5->saveHTML($dom); 20 | 21 | 22 | -------------------------------------------------------------------------------- /vendor/masterminds/html5/bin/entities.php: -------------------------------------------------------------------------------- 1 | $obj) { 14 | $sname = substr($name, 1, -1); 15 | $table[$sname] = $obj->characters; 16 | } 17 | 18 | echo '=5.3.0" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit" : "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" 28 | }, 29 | "autoload": { 30 | "psr-4": {"Masterminds\\": "src"} 31 | }, 32 | "autoload-dev": { 33 | "psr-4": {"Masterminds\\HTML5\\Tests\\": "test/HTML5"} 34 | }, 35 | "extra": { 36 | "branch-alias": { 37 | "dev-master": "2.7-dev" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /vendor/masterminds/html5/src/HTML5/Exception.php: -------------------------------------------------------------------------------- 1 | ). 65 | * 66 | * @return int one of the Tokenizer::TEXTMODE_* constants 67 | */ 68 | public function startTag($name, $attributes = array(), $selfClosing = false); 69 | 70 | /** 71 | * An end-tag. 72 | */ 73 | public function endTag($name); 74 | 75 | /** 76 | * A comment section (unparsed character data). 77 | */ 78 | public function comment($cdata); 79 | 80 | /** 81 | * A unit of parsed character data. 82 | * 83 | * Entities in this text are *already decoded*. 84 | */ 85 | public function text($cdata); 86 | 87 | /** 88 | * Indicates that the document has been entirely processed. 89 | */ 90 | public function eof(); 91 | 92 | /** 93 | * Emitted when the parser encounters an error condition. 94 | */ 95 | public function parseError($msg, $line, $col); 96 | 97 | /** 98 | * A CDATA section. 99 | * 100 | * @param string $data 101 | * The unparsed character data 102 | */ 103 | public function cdata($data); 104 | 105 | /** 106 | * This is a holdover from the XML spec. 107 | * 108 | * While user agents don't get PIs, server-side does. 109 | * 110 | * @param string $name The name of the processor (e.g. 'php'). 111 | * @param string $data The unparsed data. 112 | */ 113 | public function processingInstruction($name, $data = null); 114 | } 115 | -------------------------------------------------------------------------------- /vendor/masterminds/html5/src/HTML5/Parser/FileInputStream.php: -------------------------------------------------------------------------------- 1 | 1, 20 | 'dd' => 1, 21 | 'dt' => 1, 22 | 'rt' => 1, 23 | 'rp' => 1, 24 | 'tr' => 1, 25 | 'th' => 1, 26 | 'td' => 1, 27 | 'thead' => 1, 28 | 'tfoot' => 1, 29 | 'tbody' => 1, 30 | 'table' => 1, 31 | 'optgroup' => 1, 32 | 'option' => 1, 33 | ); 34 | 35 | /** 36 | * Returns true if the given tagname has special processing rules. 37 | */ 38 | public function hasRules($tagname) 39 | { 40 | return isset(static::$tags[$tagname]); 41 | } 42 | 43 | /** 44 | * Evaluate the rule for the current tag name. 45 | * 46 | * This may modify the existing DOM. 47 | * 48 | * @return \DOMElement The new Current DOM element. 49 | */ 50 | public function evaluate($new, $current) 51 | { 52 | switch ($new->tagName) { 53 | case 'li': 54 | return $this->handleLI($new, $current); 55 | case 'dt': 56 | case 'dd': 57 | return $this->handleDT($new, $current); 58 | case 'rt': 59 | case 'rp': 60 | return $this->handleRT($new, $current); 61 | case 'optgroup': 62 | return $this->closeIfCurrentMatches($new, $current, array( 63 | 'optgroup', 64 | )); 65 | case 'option': 66 | return $this->closeIfCurrentMatches($new, $current, array( 67 | 'option', 68 | )); 69 | case 'tr': 70 | return $this->closeIfCurrentMatches($new, $current, array( 71 | 'tr', 72 | )); 73 | case 'td': 74 | case 'th': 75 | return $this->closeIfCurrentMatches($new, $current, array( 76 | 'th', 77 | 'td', 78 | )); 79 | case 'tbody': 80 | case 'thead': 81 | case 'tfoot': 82 | case 'table': // Spec isn't explicit about this, but it's necessary. 83 | 84 | return $this->closeIfCurrentMatches($new, $current, array( 85 | 'thead', 86 | 'tfoot', 87 | 'tbody', 88 | )); 89 | } 90 | 91 | return $current; 92 | } 93 | 94 | protected function handleLI($ele, $current) 95 | { 96 | return $this->closeIfCurrentMatches($ele, $current, array( 97 | 'li', 98 | )); 99 | } 100 | 101 | protected function handleDT($ele, $current) 102 | { 103 | return $this->closeIfCurrentMatches($ele, $current, array( 104 | 'dt', 105 | 'dd', 106 | )); 107 | } 108 | 109 | protected function handleRT($ele, $current) 110 | { 111 | return $this->closeIfCurrentMatches($ele, $current, array( 112 | 'rt', 113 | 'rp', 114 | )); 115 | } 116 | 117 | protected function closeIfCurrentMatches($ele, $current, $match) 118 | { 119 | if (in_array($current->tagName, $match, true)) { 120 | $current->parentNode->appendChild($ele); 121 | } else { 122 | $current->appendChild($ele); 123 | } 124 | 125 | return $ele; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /vendor/masterminds/html5/src/HTML5/Serializer/README.md: -------------------------------------------------------------------------------- 1 | # The Serializer (Writer) Model 2 | 3 | The serializer roughly follows sections _8.1 Writing HTML documents_ and section 4 | _8.3 Serializing HTML fragments_ by converting DOMDocument, DOMDocumentFragment, 5 | and DOMNodeList into HTML5. 6 | 7 | [ HTML5 ] // Interface for saving. 8 | || 9 | [ Traverser ] // Walk the DOM 10 | || 11 | [ Rules ] // Convert DOM elements into strings. 12 | || 13 | [ HTML5 ] // HTML5 document or fragment in text. 14 | 15 | 16 | ## HTML5 Class 17 | 18 | Provides the top level interface for saving. 19 | 20 | ## The Traverser 21 | 22 | Walks the DOM finding each element and passing it off to the output rules to 23 | convert to HTML5. 24 | 25 | ## Output Rules 26 | 27 | The output rules are defined in the RulesInterface which can have multiple 28 | implementations. Currently, the OutputRules is the default implementation that 29 | converts a DOM as is into HTML5. 30 | 31 | ## HTML5 String 32 | 33 | The output of the process it HTML5 as a string or saved to a file. -------------------------------------------------------------------------------- /vendor/masterminds/html5/src/HTML5/Serializer/RulesInterface.php: -------------------------------------------------------------------------------- 1 | 'html', 21 | 'http://www.w3.org/1998/Math/MathML' => 'math', 22 | 'http://www.w3.org/2000/svg' => 'svg', 23 | ); 24 | 25 | protected $dom; 26 | 27 | protected $options; 28 | 29 | protected $encode = false; 30 | 31 | protected $rules; 32 | 33 | protected $out; 34 | 35 | /** 36 | * Create a traverser. 37 | * 38 | * @param \DOMNode|\DOMNodeList $dom The document or node to traverse. 39 | * @param resource $out A stream that allows writing. The traverser will output into this 40 | * stream. 41 | * @param array $options An array of options for the traverser as key/value pairs. These include: 42 | * - encode_entities: A bool to specify if full encding should happen for all named 43 | * charachter references. Defaults to false which escapes &'<>". 44 | * - output_rules: The path to the class handling the output rules. 45 | */ 46 | public function __construct($dom, $out, RulesInterface $rules, $options = array()) 47 | { 48 | $this->dom = $dom; 49 | $this->out = $out; 50 | $this->rules = $rules; 51 | $this->options = $options; 52 | 53 | $this->rules->setTraverser($this); 54 | } 55 | 56 | /** 57 | * Tell the traverser to walk the DOM. 58 | * 59 | * @return resource $out Returns the output stream. 60 | */ 61 | public function walk() 62 | { 63 | if ($this->dom instanceof \DOMDocument) { 64 | $this->rules->document($this->dom); 65 | } elseif ($this->dom instanceof \DOMDocumentFragment) { 66 | // Document fragments are a special case. Only the children need to 67 | // be serialized. 68 | if ($this->dom->hasChildNodes()) { 69 | $this->children($this->dom->childNodes); 70 | } 71 | } // If NodeList, loop 72 | elseif ($this->dom instanceof \DOMNodeList) { 73 | // If this is a NodeList of DOMDocuments this will not work. 74 | $this->children($this->dom); 75 | } // Else assume this is a DOMNode-like datastructure. 76 | else { 77 | $this->node($this->dom); 78 | } 79 | 80 | return $this->out; 81 | } 82 | 83 | /** 84 | * Process a node in the DOM. 85 | * 86 | * @param mixed $node A node implementing \DOMNode. 87 | */ 88 | public function node($node) 89 | { 90 | // A listing of types is at http://php.net/manual/en/dom.constants.php 91 | switch ($node->nodeType) { 92 | case XML_ELEMENT_NODE: 93 | $this->rules->element($node); 94 | break; 95 | case XML_TEXT_NODE: 96 | $this->rules->text($node); 97 | break; 98 | case XML_CDATA_SECTION_NODE: 99 | $this->rules->cdata($node); 100 | break; 101 | case XML_PI_NODE: 102 | $this->rules->processorInstruction($node); 103 | break; 104 | case XML_COMMENT_NODE: 105 | $this->rules->comment($node); 106 | break; 107 | // Currently we don't support embedding DTDs. 108 | default: 109 | //print ''; 110 | break; 111 | } 112 | } 113 | 114 | /** 115 | * Walk through all the nodes on a node list. 116 | * 117 | * @param \DOMNodeList $nl A list of child elements to walk through. 118 | */ 119 | public function children($nl) 120 | { 121 | foreach ($nl as $node) { 122 | $this->node($node); 123 | } 124 | } 125 | 126 | /** 127 | * Is an element local? 128 | * 129 | * @param mixed $ele An element that implement \DOMNode. 130 | * 131 | * @return bool true if local and false otherwise. 132 | */ 133 | public function isLocalElement($ele) 134 | { 135 | $uri = $ele->namespaceURI; 136 | if (empty($uri)) { 137 | return false; 138 | } 139 | 140 | return isset(static::$local_ns[$uri]); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /vendor/psr/http-factory/.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | vendor/ 3 | -------------------------------------------------------------------------------- /vendor/psr/http-factory/.pullapprove.yml: -------------------------------------------------------------------------------- 1 | extends: default 2 | reviewers: 3 | - 4 | name: contributors 5 | required: 1 6 | teams: 7 | - http-factory-contributors 8 | -------------------------------------------------------------------------------- /vendor/psr/http-factory/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 PHP-FIG 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/psr/http-factory/README.md: -------------------------------------------------------------------------------- 1 | HTTP Factories 2 | ============== 3 | 4 | This repository holds all interfaces related to [PSR-17 (HTTP Message Factories)][psr-17]. 5 | Please refer to the specification for a description. 6 | 7 | You can find implementations of the specification by looking for packages providing the 8 | [psr/http-factory-implementation](https://packagist.org/providers/psr/http-factory-implementation) virtual package. 9 | 10 | [psr-17]: https://www.php-fig.org/psr/psr-17/ 11 | -------------------------------------------------------------------------------- /vendor/psr/http-factory/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "psr/http-factory", 3 | "description": "Common interfaces for PSR-7 HTTP message factories", 4 | "keywords": [ 5 | "psr", 6 | "psr-7", 7 | "psr-17", 8 | "http", 9 | "factory", 10 | "message", 11 | "request", 12 | "response" 13 | ], 14 | "license": "MIT", 15 | "authors": [ 16 | { 17 | "name": "PHP-FIG", 18 | "homepage": "http://www.php-fig.org/" 19 | } 20 | ], 21 | "require": { 22 | "php": ">=7.0.0", 23 | "psr/http-message": "^1.0" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "Psr\\Http\\Message\\": "src/" 28 | } 29 | }, 30 | "extra": { 31 | "branch-alias": { 32 | "dev-master": "1.0.x-dev" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /vendor/psr/http-factory/src/RequestFactoryInterface.php: -------------------------------------------------------------------------------- 1 | `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. 7 | > When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. 8 | 9 | 10 | The following examples will illustrate how basic operations are done in PSR-7. 11 | 12 | ##### Examples 13 | 14 | 15 | For this examples to work (at least) a PSR-7 implementation package is required. (eg: zendframework/zend-diactoros, guzzlehttp/psr7, slim/slim, etc) 16 | All PSR-7 implementations should have the same behaviour. 17 | 18 | The following will be assumed: 19 | `$request` is an object of `Psr\Http\Message\RequestInterface` and 20 | 21 | `$response` is an object implementing `Psr\Http\Message\RequestInterface` 22 | 23 | 24 | ### Working with HTTP Headers 25 | 26 | #### Adding headers to response: 27 | 28 | ```php 29 | $response->withHeader('My-Custom-Header', 'My Custom Message'); 30 | ``` 31 | 32 | #### Appending values to headers 33 | 34 | ```php 35 | $response->withAddedHeader('My-Custom-Header', 'The second message'); 36 | ``` 37 | 38 | #### Checking if header exists: 39 | 40 | ```php 41 | $request->hasHeader('My-Custom-Header'); // will return false 42 | $response->hasHeader('My-Custom-Header'); // will return true 43 | ``` 44 | 45 | > Note: My-Custom-Header was only added in the Response 46 | 47 | #### Getting comma-separated values from a header (also applies to request) 48 | 49 | ```php 50 | // getting value from request headers 51 | $request->getHeaderLine('Content-Type'); // will return: "text/html; charset=UTF-8" 52 | // getting value from response headers 53 | $response->getHeaderLine('My-Custom-Header'); // will return: "My Custom Message; The second message" 54 | ``` 55 | 56 | #### Getting array of value from a header (also applies to request) 57 | ```php 58 | // getting value from request headers 59 | $request->getHeader('Content-Type'); // will return: ["text/html", "charset=UTF-8"] 60 | // getting value from response headers 61 | $response->getHeader('My-Custom-Header'); // will return: ["My Custom Message", "The second message"] 62 | ``` 63 | 64 | #### Removing headers from HTTP Messages 65 | ```php 66 | // removing a header from Request, removing deprecated "Content-MD5" header 67 | $request->withoutHeader('Content-MD5'); 68 | 69 | // removing a header from Response 70 | // effect: the browser won't know the size of the stream 71 | // the browser will download the stream till it ends 72 | $response->withoutHeader('Content-Length'); 73 | ``` 74 | 75 | ### Working with HTTP Message Body 76 | 77 | When working with the PSR-7 there are two methods of implementation: 78 | #### 1. Getting the body separately 79 | 80 | > 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. 81 | 82 | ```php 83 | $body = $response->getBody(); 84 | // operations on body, eg. read, write, seek 85 | // ... 86 | // replacing the old body 87 | $response->withBody($body); 88 | // this last statement is optional as we working with objects 89 | // in this case the "new" body is same with the "old" one 90 | // the $body variable has the same value as the one in $request, only the reference is passed 91 | ``` 92 | 93 | #### 2. Working directly on response 94 | 95 | > This method is useful when only performing few operations as the `$request->getBody()` statement fragment is required 96 | 97 | ```php 98 | $response->getBody()->write('hello'); 99 | ``` 100 | 101 | ### Getting the body contents 102 | 103 | The following snippet gets the contents of a stream contents. 104 | > 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. 105 | ```php 106 | $body = $response->getBody(); 107 | $body->rewind(); // or $body->seek(0); 108 | $bodyText = $body->getContents(); 109 | ``` 110 | > 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. 111 | 112 | ### Append to body 113 | 114 | ```php 115 | $response->getBody()->write('Hello'); // writing directly 116 | $body = $request->getBody(); // which is a `StreamInterface` 117 | $body->write('xxxxx'); 118 | ``` 119 | 120 | ### Prepend to body 121 | Prepending is different when it comes to streams. The content must be copied before writing the content to be prepended. 122 | The following example will explain the behaviour of streams. 123 | 124 | ```php 125 | // assuming our response is initially empty 126 | $body = $repsonse->getBody(); 127 | // writing the string "abcd" 128 | $body->write('abcd'); 129 | 130 | // seeking to start of stream 131 | $body->seek(0); 132 | // writing 'ef' 133 | $body->write('ef'); // at this point the stream contains "efcd" 134 | ``` 135 | 136 | #### Prepending by rewriting separately 137 | 138 | ```php 139 | // assuming our response body stream only contains: "abcd" 140 | $body = $response->getBody(); 141 | $body->rewind(); 142 | $contents = $body->getContents(); // abcd 143 | // seeking the stream to beginning 144 | $body->rewind(); 145 | $body->write('ef'); // stream contains "efcd" 146 | $body->write($contents); // stream contains "efabcd" 147 | ``` 148 | 149 | > 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)`. 150 | 151 | #### Prepending by using contents as a string 152 | ```php 153 | $body = $response->getBody(); 154 | $body->rewind(); 155 | $contents = $body->getContents(); // efabcd 156 | $contents = 'ef'.$contents; 157 | $body->rewind(); 158 | $body->write($contents); 159 | ``` 160 | -------------------------------------------------------------------------------- /vendor/psr/http-message/src/RequestInterface.php: -------------------------------------------------------------------------------- 1 | logger = $logger; 34 | } 35 | 36 | public function doSomething() 37 | { 38 | if ($this->logger) { 39 | $this->logger->info('Doing work'); 40 | } 41 | 42 | try { 43 | $this->doSomethingElse(); 44 | } catch (Exception $exception) { 45 | $this->logger->error('Oh no!', array('exception' => $exception)); 46 | } 47 | 48 | // do something useful 49 | } 50 | } 51 | ``` 52 | 53 | You can then pick one of the implementations of the interface to get a logger. 54 | 55 | If you want to implement the interface, you can require this package and 56 | implement `Psr\Log\LoggerInterface` in your code. Please read the 57 | [specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) 58 | for details. 59 | -------------------------------------------------------------------------------- /vendor/psr/log/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "psr/log", 3 | "description": "Common interface for logging libraries", 4 | "keywords": ["psr", "psr-3", "log"], 5 | "homepage": "https://github.com/php-fig/log", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "PHP-FIG", 10 | "homepage": "https://www.php-fig.org/" 11 | } 12 | ], 13 | "require": { 14 | "php": ">=8.0.0" 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "Psr\\Log\\": "src" 19 | } 20 | }, 21 | "extra": { 22 | "branch-alias": { 23 | "dev-master": "3.x-dev" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/psr/log/src/AbstractLogger.php: -------------------------------------------------------------------------------- 1 | logger = $logger; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vendor/psr/log/src/LoggerInterface.php: -------------------------------------------------------------------------------- 1 | log(LogLevel::EMERGENCY, $message, $context); 21 | } 22 | 23 | /** 24 | * Action must be taken immediately. 25 | * 26 | * Example: Entire website down, database unavailable, etc. This should 27 | * trigger the SMS alerts and wake you up. 28 | */ 29 | public function alert(string|\Stringable $message, array $context = []): void 30 | { 31 | $this->log(LogLevel::ALERT, $message, $context); 32 | } 33 | 34 | /** 35 | * Critical conditions. 36 | * 37 | * Example: Application component unavailable, unexpected exception. 38 | */ 39 | public function critical(string|\Stringable $message, array $context = []): void 40 | { 41 | $this->log(LogLevel::CRITICAL, $message, $context); 42 | } 43 | 44 | /** 45 | * Runtime errors that do not require immediate action but should typically 46 | * be logged and monitored. 47 | */ 48 | public function error(string|\Stringable $message, array $context = []): void 49 | { 50 | $this->log(LogLevel::ERROR, $message, $context); 51 | } 52 | 53 | /** 54 | * Exceptional occurrences that are not errors. 55 | * 56 | * Example: Use of deprecated APIs, poor use of an API, undesirable things 57 | * that are not necessarily wrong. 58 | */ 59 | public function warning(string|\Stringable $message, array $context = []): void 60 | { 61 | $this->log(LogLevel::WARNING, $message, $context); 62 | } 63 | 64 | /** 65 | * Normal but significant events. 66 | */ 67 | public function notice(string|\Stringable $message, array $context = []): void 68 | { 69 | $this->log(LogLevel::NOTICE, $message, $context); 70 | } 71 | 72 | /** 73 | * Interesting events. 74 | * 75 | * Example: User logs in, SQL logs. 76 | */ 77 | public function info(string|\Stringable $message, array $context = []): void 78 | { 79 | $this->log(LogLevel::INFO, $message, $context); 80 | } 81 | 82 | /** 83 | * Detailed debug information. 84 | */ 85 | public function debug(string|\Stringable $message, array $context = []): void 86 | { 87 | $this->log(LogLevel::DEBUG, $message, $context); 88 | } 89 | 90 | /** 91 | * Logs with an arbitrary level. 92 | * 93 | * @param mixed $level 94 | * 95 | * @throws \Psr\Log\InvalidArgumentException 96 | */ 97 | abstract public function log($level, string|\Stringable $message, array $context = []): void; 98 | } 99 | -------------------------------------------------------------------------------- /vendor/psr/log/src/NullLogger.php: -------------------------------------------------------------------------------- 1 | logger) { }` 11 | * blocks. 12 | */ 13 | class NullLogger extends AbstractLogger 14 | { 15 | /** 16 | * Logs with an arbitrary level. 17 | * 18 | * @param mixed[] $context 19 | * 20 | * @throws \Psr\Log\InvalidArgumentException 21 | */ 22 | public function log($level, string|\Stringable $message, array $context = []): void 23 | { 24 | // noop 25 | } 26 | } 27 | --------------------------------------------------------------------------------