From a55b05d734b3b278e2e49aa7b197688ce32be4d7 Mon Sep 17 00:00:00 2001 From: Clement Desmidt Date: Wed, 5 Apr 2023 14:44:57 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Begins=20to=20refactor=20f?= =?UTF-8?q?or=20media?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For #4 --- .gitignore | 2 + composer.json | 23 + composer.lock | 1752 +++++++++++++++++++++++++ src/Media/Content.php | 114 ++ src/Media/Group.php | 8 + src/SRSS.php | 478 +++++++ src/SRSSException.php | 18 + src/SRSSItem.php | 199 +++ src/SRSSTools.php | 190 +++ srss.php | 817 ------------ tests/BasicReader.php | 22 + tests/MediaTest.php | 18 + tests/resources/basic.xml | 20 + tests/resources/media/cnn.xml | 1383 +++++++++++++++++++ tests/resources/media/music-video.xml | 32 + tests/resources/media/trailer.xml | 19 + 16 files changed, 4278 insertions(+), 817 deletions(-) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 src/Media/Content.php create mode 100644 src/Media/Group.php create mode 100644 src/SRSS.php create mode 100644 src/SRSSException.php create mode 100644 src/SRSSItem.php create mode 100644 src/SRSSTools.php delete mode 100644 srss.php create mode 100644 tests/BasicReader.php create mode 100644 tests/MediaTest.php create mode 100644 tests/resources/basic.xml create mode 100644 tests/resources/media/cnn.xml create mode 100644 tests/resources/media/music-video.xml create mode 100644 tests/resources/media/trailer.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f45219c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +/.idea \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..c49cd62 --- /dev/null +++ b/composer.json @@ -0,0 +1,23 @@ +{ + "name": "shikiryu/shikiryurss", + "description": "A RSS reader and writer", + "minimum-stability": "stable", + "license": "proprietary", + "authors": [ + { + "name": "clement", + "email": "email@example.com" + } + ], + "autoload": { + "psr-4": { + "Shikiryu\\SRSS\\": "src/" + } + }, + "require-dev": { + "phpunit/phpunit": "^9" + }, + "require": { + "ext-dom": "*" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..1454f64 --- /dev/null +++ b/composer.lock @@ -0,0 +1,1752 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "f9098bb855d1eaf15a0ec531f0903ae9", + "packages": [], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:15:36+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.15.4", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" + }, + "time": "2023-03-05T19:49:14+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.26", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.15", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-03-06T12:58:08+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "b65d59a059d3004a040c16a82e07bbdf6cfdd115" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b65d59a059d3004a040c16a82e07bbdf6cfdd115", + "reference": "b65d59a059d3004a040c16a82e07bbdf6cfdd115", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.6" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-03-27T11:43:46+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:10:38+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:03:37+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-02-14T08:28:10+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.6", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-28T06:42:11+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "ext-dom": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.1.0" +} diff --git a/src/Media/Content.php b/src/Media/Content.php new file mode 100644 index 0000000..f518b53 --- /dev/null +++ b/src/Media/Content.php @@ -0,0 +1,114 @@ + 'link', + 'fileSize' => 'int', // TODO + 'type' => 'media_type', // TODO + 'medium' => 'media_medium', // TODO + 'isDefault' => 'bool', // TODO + 'expression' => 'medium_expression', // TODO + 'bitrate' => 'int', + 'framerate' => 'int', + 'samplingrate' => 'float', + 'channels' => 'int', + 'duration' => 'int', + 'height' => 'int', + 'width' => 'int', + 'lang' => '', + ]; + private array $attr = []; + + /** + * Constructor + * + * @param DomNode $node + */ + public function __construct(?\DOMNode $node = null) + { + parent::__construct('media:content'); + $this->_loadAttributes(); + } + + /** + * @return void + */ + private function _loadAttributes() + { + foreach ($this->attributes as $attributes) { + if (array_key_exists($attributes->name, $this->possibilities)) { + $this->{$attributes->name} = $attributes->value; + } + } + } + + + /** + * main getter for properties + * + * @param $name + * + * @return null|string + * @throws SRSSException + */ + public function __get($name) + { + if (array_key_exists($name, $this->attr)) { + return $this->attr[$name]; + } + + if (array_key_exists($name, $this->possibilities)) { + $tmp = $this->node->getElementsByTagName($name); + if ($tmp->length !== 1) { + return null; + } + + return $tmp->item(0)->nodeValue; + } + + throw new SRSSException(sprintf('%s is not a possible item (%s)', $name, implode(', ', array_keys($this->possibilities)))); + } + + /** + * @param $name + * + * @return bool + */ + public function __isset($name) + { + return isset($this->attr[$name]); + } + + /** + * main setter for properties + * + * @param $name + * @param $val + * + * @throws SRSSException + */ + public function __set($name, $val) + { + if (!array_key_exists($name, $this->possibilities)) { + throw new SRSSException(sprintf('%s is not a possible item (%s)', $name, implode(', ', array_keys($this->possibilities)))); + } + + $flag = $this->possibilities[$name]; + if ($flag !== '') + $val = SRSSTools::check($val, $flag); + if (!empty($val)) { + if ($this->$name === null) { + $this->node->appendChild(new DomElement($name, $val)); + } + $this->attr[$name] = $val; + } + } +} \ No newline at end of file diff --git a/src/Media/Group.php b/src/Media/Group.php new file mode 100644 index 0000000..f096468 --- /dev/null +++ b/src/Media/Group.php @@ -0,0 +1,8 @@ + 'nohtml', + 'link' => 'link', + 'description' => 'html', + 'language' => '', + //'language' => 'lang', + 'copyright' => 'nohtml', + 'pubDate' => 'date', + 'lastBuildDate' => 'date', + 'category' => 'nohtml', + 'docs' => 'link', + 'cloud' => '', + 'generator' => 'nohtml', + 'managingEditor' => 'email', + 'webMaster' => 'email', + 'ttl' => 'int', + 'image' => '', + 'rating' => 'nohtml', + //'textInput' => '', + 'skipHours' => 'hour', + 'skipDays' => 'day', + ]; + + /** + * Constructor + */ + public function __construct() + { + libxml_use_internal_errors(true); + parent::__construct(); + $this->xpath = new DOMXpath($this); + $this->attr = array(); + $this->items = array(); + $this->position = 0; + $this->formatOutput = true; + $this->preserveWhiteSpace = false; + } + + /** + * Destructor + * manage of libxml errors + */ + public function __destruct() + { + foreach (libxml_get_errors() as $error) { + error_log($error->message, 3, 'error.log'); + } + libxml_clear_errors(); + } + + /** + * @param $link string url of the rss + * @throws SRSSException + * @return SRSS + */ + public static function read($link): SRSS + { + $doc = new SRSS; + if(@$doc->load($link)) // We don't want the warning in case of bad XML. Let's manage it with an exception. + { + $channel = $doc->getElementsByTagName('channel'); + if($channel->length == 1){ // Good URL and good RSS + $doc->_loadAttributes(); // loading channel properties + $doc->getItems(); // loading all items + return $doc; + } + + throw new SRSSException('invalid file '.$link); + } + + throw new SRSSException('Can not open file '.$link); + } + + /** + * @return SRSS + */ + public static function create() + { + $doc = new SRSS; + $root = $doc->createElement('rss'); + $root->setAttribute('version', '2.0'); + $channel = $doc->createElement('channel'); + $root->appendChild($channel); + $doc->appendChild($root); + $doc->encoding = "UTF-8"; + $doc->generator = 'Shikiryu RSS'; + // $docs = 'http://www.scriptol.fr/rss/RSS-2.0.html'; + return $doc; + } + + /** + * getter of "image"'s channel attributes + * @return string|array + */ + public function image() + { + $args = func_get_args(); + if(func_num_args() == 0) $args[0] = 'url'; + $img = $this->xpath->query('//channel/image'); + if($img->length != 1) return null; // is not in channel + $img = $img->item(0); + $r = array(); + foreach($img->childNodes as $child) + { + if($child->nodeType == XML_ELEMENT_NODE && in_array($child->nodeName, $args)) + { + $r[$child->nodeName] = $child->nodeValue; + } + } + return (func_num_args() > 1) ? $r : $r[$args[0]]; + } + + /** + * setter of "image"'s channel attributes + * @param $url string picture's url + * @param $title string picture's title + * @param $link string link on the picture + * @param $width int width + * @param $height int height + * @param $description string description + */ + public function setImage($url, $title, $link, $width = 0, $height = 0, $description = '') + { + $channel = $this->_getChannel(); + $array = []; + $url = SRSSTools::checkLink($url); + $array['url'] = $url; + $title = SRSSTools::noHTML($title); + $array['title'] = $title; + $link = SRSSTools::checkLink($link); + $array['link'] = $link; + if($width != 0) + { + $width = SRSSTools::checkInt($width); + $array['width'] = $width; + } + if($height != 0) + { + $height = SRSSTools::checkInt($height); + $array['height'] = $height; + } + if($description != 0) + { + $description = SRSSTools::noHTML($description); + $array['description'] = $description; + } + if($this->image == null) + { + $node = $this->createElement('image'); + $urlNode = $this->createElement('url', $url); + $titleNode = $this->createElement('title', $title); + $linkNode = $this->createElement('link', $link); + $node->appendChild($urlNode); + $node->appendChild($titleNode); + $node->appendChild($linkNode); + if($width != 0) + { + $widthNode = $this->createElement('width', $width); + $node->appendChild($widthNode); + } + if($height != 0) + { + $heightNode = $this->createElement('height', $height); + $node->appendChild($heightNode); + } + if($description != '') + { + $descNode = $this->createElement('description', $description); + $node->appendChild($descNode); + } + $channel->appendChild($node); + } + $this->attr['image'] = $array; + } + + /** + * setter of "cloud"'s channel attributes + * @param $domain string domain + * @param $port int port + * @param $path string path + * @param $registerProcedure string register procedure + * @param $protocol string protocol + */ + public function setCloud($domain, $port, $path, $registerProcedure, $protocol) + { + $channel = $this->_getChannel(); + $array = array(); + $domain = SRSSTools::noHTML($domain); + $array['domain'] = $domain; + $port = SRSSTools::checkInt($port); + $array['port'] = $port; + $path = SRSSTools::noHTML($path); + $array['path'] = $path; + $registerProcedure = SRSSTools::noHTML($registerProcedure); + $array['registerProcedure'] = $registerProcedure; + $protocol = SRSSTools::noHTML($protocol); + $array['protocol'] = $protocol; + if($this->cloud == null) + { + $node = $this->createElement('cloud'); + $node->setAttribute('domain', $domain); + $node->setAttribute('port', $port); + $node->setAttribute('path', $path); + $node->setAttribute('registerProcedure', $registerProcedure); + $node->setAttribute('protocol', $protocol); + $channel->appendChild($node); + } + $this->attr['cloud'] = $array; + } + + /** + * check if current RSS is a valid one (based on specifications) + * @return bool + */ + public function isValid() + { + $valid = true; + $items = $this->getItems(); + $invalidItems = array(); + $i = 1; + foreach($items as $item){ + if($item->isValid() === false){ + $invalidItems[] = $i; + $valid = false; + } + $i++; + } + return ($valid && $this->title != null && $this->link != null && $this->description != null); + } + + /** + * getter of current RSS channel + * @return DOMElement + * @throws SRSSException + */ + private function _getChannel() + { + $channel = $this->getElementsByTagName('channel'); + if($channel->length != 1) throw new SRSSException('channel node not created, or too many channel nodes'); + return $channel->item(0); + } + + /** + * @param $name + * + * @return bool + */ + public function __isset($name) + { + return isset($this->attr[$name]); + } + + /** + * setter of others attributes + * @param $name + * @param $val + * @throws SRSSException + */ + public function __set($name, $val) + { + $channel = $this->_getChannel(); + if(array_key_exists($name, $this->possibleAttr)){ + $flag = $this->possibleAttr[$name]; + $val = SRSSTools::check($val, $flag); + if(!empty($val)){ + if($this->$name == null){ + $node = $this->createElement($name, $val); + $channel->appendChild($node); + } + $this->attr[$name] = $val; + } + }else{ + throw new SRSSException($name.' is not a possible item'); + } + } + + /** + * getter of others attributes + * @param $name + * @return null|string + * @throws SRSSException + */ + public function __get($name) + { + if(isset($this->attr[$name])) + return $this->attr[$name]; +// $channel = $this->_getChannel(); + if(array_key_exists($name, $this->possibleAttr)){ + $tmp = $this->xpath->query('//channel/'.$name); + if($tmp->length != 1) return null; + return $tmp->item(0)->nodeValue; + }else{ + throw new SRSSException($name.' is not a possible value.'); + } + } + + /** + * add a SRSS Item as an item into current RSS as first item + * @param SRSSItem $item + */ + public function addItemBefore(SRSSItem $item) + { + $node = $this->importNode($item->getItem(), true); + $items = $this->getElementsByTagName('item'); + if($items->length != 0){ + $firstNode = $items->item(0); + if($firstNode != null) + $firstNode->parentNode->insertBefore($node, $firstNode); + else + $this->addItem($item); + } + else + $this->addItem($item); + } + + /** + * add a SRSS Item as an item into current RSS + * @param SRSSItem $item + */ + public function addItem(SRSSItem $item) + { + $node = $this->importNode($item->getItem(), true); + $channel = $this->_getChannel(); + $channel->appendChild($node); + } + + /** + * rewind from Iterator + */ + public function rewind() { + $this->position = 0; + } + + /** + * current from Iterator + */ + public function current() { + return $this->items[$this->position]; + } + + /** + * key from Iterator + */ + public function key() { + return $this->position; + } + + /** + * next from Iterator + */ + public function next() { + ++$this->position; + } + + /** + * valid from Iterator + */ + public function valid() { + return isset($this->items[$this->position]); + } + + /** + * getter of 1st item + * @return SRSSItem + */ + public function getFirst() + { + return $this->getItem(1); + } + + /** + * getter of last item + * @return SRSSItem + */ + public function getLast() + { + $items = $this->getItems(); + return $items[count($items)-1]; + } + + /** + * getter of an item + * @param $i int + * @return SRSSItem + */ + public function getItem($i) + { + $i--; + return isset($this->items[$i]) ? $this->items[$i] : null; + } + + /** + * getter of all items + * @return SRSSItem[] + * @throws SRSSException + */ + public function getItems() + { + $channel = $this->_getChannel(); + $item = $channel->getElementsByTagName('item'); + $length = $item->length; + $this->items = []; + if($length > 0){ + for($i = 0; $i < $length; $i++) + { + $this->items[$i] = new SRSSItem($item->item($i)); + } + } + return $this->items; + } + + /** + * display XML + * see DomDocument's docs + */ + public function show() + { + return $this->saveXml(); + } + + + /** + * putting all RSS attributes into the object + */ + private function _loadAttributes() + { + $channel = $this->_getChannel(); + foreach($channel->childNodes as $child) + { + if($child->nodeType == XML_ELEMENT_NODE && $child->nodeName != 'item') + { + if($child->nodeName == 'image'){ + foreach($child->childNodes as $children) + { + if($children->nodeType == XML_ELEMENT_NODE) + $this->attr['image'][$children->nodeName] = $children->nodeValue; + } + } + else + $this->attr[$child->nodeName] = $child->nodeValue; + } + } + } + + /** + * transform current object into an array + * @return array + */ + public function toArray() + { + $doc = array(); + foreach($this->attr as $attrName => $attrVal) + { + $doc[$attrName] = $attrVal; + } + foreach($this->getItems() as $item) + { + $doc['items'][] = $item->toArray(); + } + return $doc; + } +} \ No newline at end of file diff --git a/src/SRSSException.php b/src/SRSSException.php new file mode 100644 index 0000000..eca3cc8 --- /dev/null +++ b/src/SRSSException.php @@ -0,0 +1,18 @@ +Message : ' . $this->getMessage() . ' à la ligne : ' . $this->getLine(); + } +} \ No newline at end of file diff --git a/src/SRSSItem.php b/src/SRSSItem.php new file mode 100644 index 0000000..09af81a --- /dev/null +++ b/src/SRSSItem.php @@ -0,0 +1,199 @@ + 'nohtml', + 'link' => 'link', + 'description' => 'html', + 'author' => 'email', + 'category' => 'nohtml', + 'comments' => 'link', + 'enclosure' => '', + 'guid' => 'nohtml', + 'pubDate' => 'date', + 'source' => 'link', + 'media:group' => 'folder', + 'media:content' => '', + ]; + + /** + * Constructor + * + * @param DomNode $node + */ + public function __construct($node = null) + { + parent::__construct(); + if ($node instanceof DOMElement) $this->node = $this->importNode($node, true); + else $this->node = $this->importNode(new DomElement('item')); + $this->_loadAttributes(); + } + + /** + * putting all item attributes into the object + */ + private function _loadAttributes(): void + { + $this->_loadChildAttributes($this->node->childNodes); + } + + /** + * @param $nodes + * + * @return void + */ + private function _loadChildAttributes($nodes): void + { + foreach ($nodes as $child) { + if ($child->nodeType === XML_ELEMENT_NODE && $child->nodeName !== 'item') { + if (array_key_exists($child->nodeName, $this->possibilities) && $this->possibilities[$child->nodeName] === 'folder') { + $this->_loadChildAttributes($child->childNodes); + } + if ($child->nodeName === 'media:content') { + $this->{$child->nodeName} = new Content($child); + } else { + $this->{$child->nodeName} = $child->nodeValue; + } + } + } + } + + /** + * getter of item DomElement + */ + public function getItem() + { + $this->appendChild($this->node); + + return $this->getElementsByTagName('item')->item(0); + } + + /** + * setter for enclosure's properties + * + * @param $url string url + * @param $length int length + * @param $type string type + */ + public function setEnclosure($url, $length, $type) + { + $array = []; + $url = SRSSTools::checkLink($url); + $array['url'] = $url; + $length = SRSSTools::checkInt($length); + $array['length'] = $length; + $type = SRSSTools::noHTML($type); + $array['type'] = $type; + if ($this->enclosure == null) { + $node = $this->createElement('enclosure'); + $node->setAttribute('url', $url); + $node->setAttribute('length', $length); + $node->setAttribute('type', $type); + $this->node->appendChild($node); + } + $this->attr['enclosure'] = $array; + } + + /** + * check if current item is valid (following specifications) + * @return bool + */ + public function isValid() + { + return $this->description != null ? true : false; + } + + /** + * @param $name + * + * @return bool + */ + public function __isset($name) + { + return isset($this->attr[$name]); + } + + /** + * main setter for properties + * + * @param $name + * @param $val + * + * @throws SRSSException + */ + public function __set($name, $val) + { + if (!array_key_exists($name, $this->possibilities)) { + throw new SRSSException(sprintf('%s is not a possible item (%s)', $name, implode(', ', array_keys($this->possibilities)))); + } + + $flag = $this->possibilities[$name]; + if ($flag !== '') + $val = SRSSTools::check($val, $flag); + if (!empty($val)) { + if ($this->$name == null) { + $this->node->appendChild(new DomElement($name, $val)); + } + $this->attr[$name] = $val; + } + } + + /** + * main getter for properties + * + * @param $name + * + * @return null|string + * @throws SRSSException + */ + public function __get($name) + { + if (isset($this->attr[$name])) + return $this->attr[$name]; + if (array_key_exists($name, $this->possibilities)) { + $tmp = $this->node->getElementsByTagName($name); + if ($tmp->length != 1) return null; + + return $tmp->item(0)->nodeValue; + } + + throw new SRSSException(sprintf('%s is not a possible item (%s)', $name, implode(', ', array_keys($this->possibilities)))); + } + + /** + * display item's XML + * see DomDocument's docs + */ + public function show() + { + return $this->saveXml(); + } + + /** + * transform current item's object into an array + * @return array + */ + public function toArray() + { + $infos = []; + foreach ($this->attr as $attrName => $attrVal) { + $infos[$attrName] = $attrVal; + } + + return $infos; + } +} \ No newline at end of file diff --git a/src/SRSSTools.php b/src/SRSSTools.php new file mode 100644 index 0000000..1a2e2a9 --- /dev/null +++ b/src/SRSSTools.php @@ -0,0 +1,190 @@ + 2 ? '20'.substr($dateArray['tm_year'], -2) : '19'.$dateArray['tm_year']; + $date = $annee.'-'.$mois.'-'.$dateArray['tm_mday']; + return date("D, d M Y H:i:s T", strtotime($date)); + } + return ''; + } + + if(strtotime($date) !==false ){ + return date("D, d M Y H:i:s T", strtotime($date)); + } + + [$j, $m, $a] = explode('/', $date); + + return date("D, d M Y H:i:s T", strtotime($a.'-'.$m.'-'.$j)); + } + + /** + * check if it's an url + * @param $check string to check + * @return string|boolean the filtered data, or FALSE if the filter fails. + */ + public static function checkLink($check) + { + return filter_var($check, FILTER_VALIDATE_URL); + } + + /** + * make a string XML-compatible + * @param $check string to format + * @return string formatted string + * TODO CDATA ? + */ + public static function HTML4XML($check) + { + return htmlspecialchars($check); + } + + /** + * delete html tags + * @param $check string to format + * @return string formatted string + */ + public static function noHTML($check) + { + return strip_tags($check); + } + + /** + * check if it's a day (in RSS terms) + * @param $check string to check + * @return string the day, or empty string + */ + public static function checkDay($check) + { + $possibleDay = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']; + return in_array(strtolower($check), $possibleDay) ? $check : ''; + } + + /** + * check if it's an email + * @param $check string to check + * @return string|boolean the filtered data, or FALSE if the filter fails. + */ + public static function checkEmail($check) + { + return filter_var($check, FILTER_VALIDATE_EMAIL); + } + + /** + * check if it's an hour (in RSS terms) + * @param $check string to check + * @return string|boolean the filtered data, or FALSE if the filter fails. + */ + public static function checkHour($check) + { + $options = [ + 'options' => [ + 'default' => 0, + 'min_range' => 0, + 'max_range' => 23 + ] + ]; + return filter_var($check, FILTER_VALIDATE_INT, $options); + } + + /** + * check if it's an int + * @param $check int to check + * @return int|boolean the filtered data, or FALSE if the filter fails. + */ + public static function checkInt($check) + { + return filter_var($check, FILTER_VALIDATE_INT); + } + + /** + * @param $check + * + * @return mixed + */ + private static function checkMediaType($check) + { + return $check; + } + + /** + * @param $check + * + * @return mixed|null + */ + private static function checkMediaMedium($check) + { + return in_array($check, ['image', 'audio', 'video', 'document', 'executable']) ? $check : null; + } + + /** + * @param $check + * + * @return mixed|null + */ + private static function checkBool($check) + { + return in_array($check, ['true', 'false']) ? $check : null; + } + + /** + * @param $check + * + * @return mixed|null + */ + private static function checkMediumExpression($check) + { + return in_array($check, ['sample', 'full', 'nonstop']) ? $check : null; + } +} \ No newline at end of file diff --git a/srss.php b/srss.php deleted file mode 100644 index 2d3fdeb..0000000 --- a/srss.php +++ /dev/null @@ -1,817 +0,0 @@ - 'nohtml', - 'link' => 'link', - 'description' => 'html', - 'language' => '', - //'language' => 'lang', - 'copyright' => 'nohtml', - 'pubDate' => 'date', - 'lastBuildDate' => 'date', - 'category' => 'nohtml', - 'docs' => 'link', - 'cloud' => '', - 'generator' => 'nohtml', - 'managingEditor' => 'email', - 'webMaster' => 'email', - 'ttl' => 'int', - 'image' => '', - 'rating' => 'nohtml', - //'textInput' => '', - 'skipHours' => 'hour', - 'skipDays' => 'day', - ); - - /** - * Constructor - */ - public function __construct() - { - libxml_use_internal_errors(true); - parent::__construct(); - $this->xpath = new DOMXpath($this); - $this->attr = array(); - $this->items = array(); - $this->position = 0; - $this->formatOutput = true; - $this->preserveWhiteSpace = false; - } - - /** - * Destructor - * manage of libxml errors - */ - public function __destruct() - { - foreach (libxml_get_errors() as $error) { - error_log($error->message, 3, 'error.log'); - } - libxml_clear_errors(); - } - - /** - * @param $link string url of the rss - * @throws SRSSException - * @return SRSS - */ - public static function read($link) - { - $doc = new SRSS; - if(@$doc->load($link)) // We don't want the warning in case of bad XML. Let's manage it with an exception. - { - $channel = $doc->getElementsByTagName('channel'); - if($channel->length == 1){ // Good URL and good RSS - $doc->_loadAttributes(); // loading channel properties - $doc->getItems(); // loading all items - return $doc; - } - else - { - throw new SRSSException('invalid file '.$link); - } - } - else - { - throw new SRSSException('Can not open file '.$link); - } - } - - /** - * @return SRSS - */ - public static function create() - { - $doc = new SRSS; - $root = $doc->createElement('rss'); - $root->setAttribute('version', '2.0'); - $channel = $doc->createElement('channel'); - $root->appendChild($channel); - $doc->appendChild($root); - $doc->encoding = "UTF-8"; - $doc->generator = 'Shikiryu RSS'; - // $docs = 'http://www.scriptol.fr/rss/RSS-2.0.html'; - return $doc; - } - - /** - * getter of "image"'s channel attributes - * @return string|array - */ - public function image() - { - $args = func_get_args(); - if(func_num_args() == 0) $args[0] = 'url'; - $img = $this->xpath->query('//channel/image'); - if($img->length != 1) return null; // is not in channel - $img = $img->item(0); - $r = array(); - foreach($img->childNodes as $child) - { - if($child->nodeType == XML_ELEMENT_NODE && in_array($child->nodeName, $args)) - { - $r[$child->nodeName] = $child->nodeValue; - } - } - return (func_num_args() > 1) ? $r : $r[$args[0]]; - } - - /** - * setter of "image"'s channel attributes - * @param $url string picture's url - * @param $title string picture's title - * @param $link string link on the picture - * @param $width int width - * @param $height int height - * @param $description string description - */ - public function setImage($url, $title, $link, $width = 0, $height = 0, $description = '') - { - $channel = $this->_getChannel(); - $array = array(); - $url = SRSSTools::checkLink($url); - $array['url'] = $url; - $title = SRSSTools::noHTML($title); - $array['title'] = $title; - $link = SRSSTools::checkLink($link); - $array['link'] = $link; - if($width != 0) - { - $width = SRSSTools::checkInt($width); - $array['width'] = $width; - } - if($height != 0) - { - $height = SRSSTools::checkInt($height); - $array['height'] = $height; - } - if($description != 0) - { - $description = SRSSTools::noHTML($description); - $array['description'] = $description; - } - if($this->image == null) - { - $node = $this->createElement('image'); - $urlNode = $this->createElement('url', $url); - $titleNode = $this->createElement('title', $title); - $linkNode = $this->createElement('link', $link); - $node->appendChild($urlNode); - $node->appendChild($titleNode); - $node->appendChild($linkNode); - if($width != 0) - { - $widthNode = $this->createElement('width', $width); - $node->appendChild($widthNode); - } - if($height != 0) - { - $heightNode = $this->createElement('height', $height); - $node->appendChild($heightNode); - } - if($description != '') - { - $descNode = $this->createElement('description', $description); - $node->appendChild($descNode); - } - $channel->appendChild($node); - } - $this->attr['image'] = $array; - } - - /** - * setter of "cloud"'s channel attributes - * @param $domain string domain - * @param $port int port - * @param $path string path - * @param $registerProcedure string register procedure - * @param $protocol string protocol - */ - public function setCloud($domain, $port, $path, $registerProcedure, $protocol) - { - $channel = $this->_getChannel(); - $array = array(); - $domain = SRSSTools::noHTML($domain); - $array['domain'] = $domain; - $port = SRSSTools::checkInt($port); - $array['port'] = $port; - $path = SRSSTools::noHTML($path); - $array['path'] = $path; - $registerProcedure = SRSSTools::noHTML($registerProcedure); - $array['registerProcedure'] = $registerProcedure; - $protocol = SRSSTools::noHTML($protocol); - $array['protocol'] = $protocol; - if($this->cloud == null) - { - $node = $this->createElement('cloud'); - $node->setAttribute('domain', $domain); - $node->setAttribute('port', $port); - $node->setAttribute('path', $path); - $node->setAttribute('registerProcedure', $registerProcedure); - $node->setAttribute('protocol', $protocol); - $channel->appendChild($node); - } - $this->attr['cloud'] = $array; - } - - /** - * check if current RSS is a valid one (based on specifications) - * @return bool - */ - public function isValid() - { - $valid = true; - $items = $this->getItems(); - $invalidItems = array(); - $i = 1; - foreach($items as $item){ - if($item->isValid() === false){ - $invalidItems[] = $i; - $valid = false; - } - $i++; - } - return ($valid && $this->title != null && $this->link != null && $this->description != null); - } - - /** - * getter of current RSS channel - * @return DOMElement - * @throws SRSSException - */ - private function _getChannel() - { - $channel = $this->getElementsByTagName('channel'); - if($channel->length != 1) throw new SRSSException('channel node not created, or too many channel nodes'); - return $channel->item(0); - } - - /** - * setter of others attributes - * @param $name - * @param $val - * @throws SRSSException - */ - public function __set($name, $val) - { - $channel = $this->_getChannel(); - if(array_key_exists($name, $this->possibleAttr)){ - $flag = $this->possibleAttr[$name]; - $val = SRSSTools::check($val, $flag); - if(!empty($val)){ - if($this->$name == null){ - $node = $this->createElement($name, $val); - $channel->appendChild($node); - } - $this->attr[$name] = $val; - } - }else{ - throw new SRSSException($name.' is not a possible item'); - } - } - - /** - * getter of others attributes - * @param $name - * @return null|string - * @throws SRSSException - */ - public function __get($name) - { - if(isset($this->attr[$name])) - return $this->attr[$name]; -// $channel = $this->_getChannel(); - if(array_key_exists($name, $this->possibleAttr)){ - $tmp = $this->xpath->query('//channel/'.$name); - if($tmp->length != 1) return null; - return $tmp->item(0)->nodeValue; - }else{ - throw new SRSSException($name.' is not a possible value.'); - } - } - - /** - * add a SRSS Item as an item into current RSS as first item - * @param SRSSItem $item - */ - public function addItemBefore(SRSSItem $item) - { - $node = $this->importNode($item->getItem(), true); - $items = $this->getElementsByTagName('item'); - if($items->length != 0){ - $firstNode = $items->item(0); - if($firstNode != null) - $firstNode->parentNode->insertBefore($node, $firstNode); - else - $this->addItem($item); - } - else - $this->addItem($item); - } - - /** - * add a SRSS Item as an item into current RSS - * @param SRSSItem $item - */ - public function addItem(SRSSItem $item) - { - $node = $this->importNode($item->getItem(), true); - $channel = $this->_getChannel(); - $channel->appendChild($node); - } - - /** - * rewind from Iterator - */ - public function rewind() { - $this->position = 0; - } - - /** - * current from Iterator - */ - public function current() { - return $this->items[$this->position]; - } - - /** - * key from Iterator - */ - public function key() { - return $this->position; - } - - /** - * next from Iterator - */ - public function next() { - ++$this->position; - } - - /** - * valid from Iterator - */ - public function valid() { - return isset($this->items[$this->position]); - } - - /** - * getter of 1st item - * @return SRSSItem - */ - public function getFirst() - { - return $this->getItem(1); - } - - /** - * getter of last item - * @return SRSSItem - */ - public function getLast() - { - $items = $this->getItems(); - return $items[count($items)-1]; - } - - /** - * getter of an item - * @param $i int - * @return SRSSItem - */ - public function getItem($i) - { - $i--; - return isset($this->items[$i]) ? $this->items[$i] : null; - } - - /** - * getter of all items - * @return SRSSItem[] - * @throws SRSSException - */ - public function getItems() - { - $channel = $this->_getChannel(); - $item = $channel->getElementsByTagName('item'); - $length = $item->length; - $this->items = array(); - if($length > 0){ - for($i = 0; $i < $length; $i++) - { - $this->items[$i] = new SRSSItem($item->item($i)); - } - } - return $this->items; - } - - /** - * display XML - * see DomDocument's docs - */ - public function show() - { - return $this->saveXml(); - } - - - /** - * putting all RSS attributes into the object - */ - private function _loadAttributes() - { - $channel = $this->_getChannel(); - foreach($channel->childNodes as $child) - { - if($child->nodeType == XML_ELEMENT_NODE && $child->nodeName != 'item') - { - if($child->nodeName == 'image'){ - foreach($child->childNodes as $children) - { - if($children->nodeType == XML_ELEMENT_NODE) - $this->attr['image'][$children->nodeName] = $children->nodeValue; - } - } - else - $this->attr[$child->nodeName] = $child->nodeValue; - } - } - } - - /** - * transform current object into an array - * @return array - */ - public function toArray() - { - $doc = array(); - foreach($this->attr as $attrName => $attrVal) - { - $doc[$attrName] = $attrVal; - } - foreach($this->getItems() as $item) - { - $doc['items'][] = $item->toArray(); - } - return $doc; - } -} - -/** - * @property null|string enclosure - * @property null|string description - */ -class SRSSItem extends DomDocument -{ - - /** - * @var DOMElement - */ - protected $node; // item node - protected $attr; // item's properties - - // possible properties' names - protected $possibilities = array( - 'title' => 'nohtml', - 'link' => 'link', - 'description' => 'html', - 'author' => 'email', - 'category' => 'nohtml', - 'comments' => 'link', - 'enclosure' => '', - 'guid' => 'nohtml', - 'pubDate' => 'date', - 'source' => 'link', - ); - - /** - * Constructor - * @param DomNode $node - */ - public function __construct($node = null) - { - parent::__construct(); - if($node instanceof DOMElement) $this->node = $this->importNode($node, true); - else $this->node = $this->importNode(new DomElement('item')); - $this->_loadAttributes(); - } - - /** - * putting all item attributes into the object - */ - private function _loadAttributes() - { - foreach($this->node->childNodes as $child) - { - if($child->nodeType == XML_ELEMENT_NODE && $child->nodeName != 'item') - { - $this->{$child->nodeName} = $child->nodeValue; - } - } - } - - /** - * getter of item DomElement - */ - public function getItem() - { - $this->appendChild($this->node); - return $this->getElementsByTagName('item')->item(0); - } - - /** - * setter for enclosure's properties - * @param $url string url - * @param $length int length - * @param $type string type - */ - public function setEnclosure($url, $length, $type) - { - $array = array(); - $url = SRSSTools::checkLink($url); - $array['url'] = $url; - $length = SRSSTools::checkInt($length); - $array['length'] = $length; - $type = SRSSTools::noHTML($type); - $array['type'] = $type; - if($this->enclosure == null) - { - $node = $this->createElement('enclosure'); - $node->setAttribute('url', $url); - $node->setAttribute('length', $length); - $node->setAttribute('type', $type); - $this->node->appendChild($node); - } - $this->attr['enclosure'] = $array; - } - - /** - * check if current item is valid (following specifications) - * @return bool - */ - public function isValid() - { - return $this->description != null ? true : false; - } - - /** - * main setter for properties - * @param $name - * @param $val - * @throws SRSSException - */ - public function __set($name, $val) - { - if(array_key_exists($name, $this->possibilities)) - { - $flag = $this->possibilities[$name]; - if($flag != '') - $val = SRSSTools::check($val, $flag); - if(!empty($val)){ - if($this->$name == null){ - $this->node->appendChild(new DomElement($name, $val)); - } - $this->attr[$name] = $val; - } - } - else - { - throw New SRSSException($name.' is not a possible item : '.print_r($this->possibilities)); - } - } - - /** - * main getter for properties - * @param $name - * @return null|string - * @throws SRSSException - */ - public function __get($name) - { - if(isset($this->attr[$name])) - return $this->attr[$name]; - if(array_key_exists($name, $this->possibilities)) - { - $tmp = $this->node->getElementsByTagName($name); - if($tmp->length != 1) return null; - return $tmp->item(0)->nodeValue; - } - else - { - throw New SRSSException($name.' is not a possible item : '.print_r($this->possibilities)); - } - } - - /** - * display item's XML - * see DomDocument's docs - */ - public function show() - { - return $this->saveXml(); - } - - /** - * transform current item's object into an array - * @return array - */ - public function toArray() - { - $infos = array(); - foreach($this->attr as $attrName => $attrVal) - { - $infos[$attrName] = $attrVal; - } - return $infos; - } -} - -class SRSSException extends Exception -{ - public function __construct($msg) - { - parent :: __construct($msg); - } - - public function getError() - { - $return = 'Une exception a été générée : Message : ' . $this->getMessage() . ' à la ligne : ' . $this->getLine(); - return $return; - } -} - -class SRSSTools -{ - public static function check($check, $flag) - { - switch($flag){ - case 'nohtml': - return self::noHTML($check); - break; - case 'link': - return self::checkLink($check); - break; - case 'html': - return self::HTML4XML($check); - break; - /*case 'lang': - return self::noHTML($check); - break;*/ - case 'date': - return self::getRSSDate($check); - break; - case 'email': - return self::checkEmail($check); - break; - case 'int': - return self::checkInt($check); - break; - case 'hour': - return self::checkHour($check); - break; - case 'day': - return self::checkDay($check); - break; - case '': - return $check; - break; - default: - throw new SRSSEXception('flag '.$flag.' does not exist.'); - } - } - - /** - * format the RSS to the wanted format - * @param $format string wanted format - * @param $date string RSS date - * @return string date - */ - public static function formatDate($format, $date) - { - return date($format, strtotime($date)); - } - - /** - * format a date for RSS format - * @param string $date date to format - * @param string $format - * @return string - */ - public static function getRSSDate($date, $format='') - { - $datepos = 'dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU'; - if($format != '' && preg_match('~^(['.$datepos.']{1})(-|/)(['.$datepos.']{1})(-|/)(['.$datepos.']{1})$~', $format, $match)){ - $sep = $match[2]; - $format = '%'.$match[1].$sep.'%'.$match[3].$sep.'%'.$match[5]; - if($dateArray = strptime($date, $format)){ - $mois = intval($dateArray['tm_mon']) + 1; - $annee = strlen($dateArray['tm_year']) > 2 ? '20'.substr($dateArray['tm_year'], -2) : '19'.$dateArray['tm_year']; - $date = $annee.'-'.$mois.'-'.$dateArray['tm_mday']; - return date("D, d M Y H:i:s T", strtotime($date)); - } - return ''; - } - else if(strtotime($date) !==false ){ - return date("D, d M Y H:i:s T", strtotime($date)); - } - else - { - list($j, $m, $a) = explode('/', $date); - return date("D, d M Y H:i:s T", strtotime($a.'-'.$m.'-'.$j)); - } - } - - /** - * check if it's an url - * @param $check string to check - * @return string|boolean the filtered data, or FALSE if the filter fails. - */ - public static function checkLink($check) - { - return filter_var($check, FILTER_VALIDATE_URL); - } - - /** - * make a string XML-compatible - * @param $check string to format - * @return string formatted string - * TODO CDATA ? - */ - public static function HTML4XML($check) - { - return htmlspecialchars($check); - } - - /** - * delete html tags - * @param $check string to format - * @return string formatted string - */ - public static function noHTML($check) - { - return strip_tags($check); - } - - /** - * check if it's a day (in RSS terms) - * @param $check string to check - * @return string the day, or empty string - */ - public static function checkDay($check) - { - $possibleDay = array('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'); - return in_array(strtolower($check), $possibleDay) ? $check : ''; - } - - /** - * check if it's an email - * @param $check string to check - * @return string|boolean the filtered data, or FALSE if the filter fails. - */ - public static function checkEmail($check) - { - return filter_var($check, FILTER_VALIDATE_EMAIL); - } - - /** - * check if it's an hour (in RSS terms) - * @param $check string to check - * @return string|boolean the filtered data, or FALSE if the filter fails. - */ - public static function checkHour($check) - { - $options = array( - 'options' => array( - 'default' => 0, - 'min_range' => 0, - 'max_range' => 23 - ) - ); - return filter_var($check, FILTER_VALIDATE_INT, $options); - } - - /** - * check if it's an int - * @param $check int to check - * @return int|boolean the filtered data, or FALSE if the filter fails. - */ - public static function checkInt($check) - { - return filter_var($check, FILTER_VALIDATE_INT); - } -} \ No newline at end of file diff --git a/tests/BasicReader.php b/tests/BasicReader.php new file mode 100644 index 0000000..36d9468 --- /dev/null +++ b/tests/BasicReader.php @@ -0,0 +1,22 @@ +title); + $first_item = $rss->getFirst(); + self::assertEquals('RSS Tutorial', $first_item->title); + } + + public function testRssNotFound() + { + $this->expectException(SRSSException::class); + $rss = SRSS::read('not_found.xml'); + } +} \ No newline at end of file diff --git a/tests/MediaTest.php b/tests/MediaTest.php new file mode 100644 index 0000000..fec2729 --- /dev/null +++ b/tests/MediaTest.php @@ -0,0 +1,18 @@ +title); + + $first_item = $rss->getFirst(); + self::assertEquals('Kirstie Alley, \'Cheers\' and \'Veronica\'s Closet\' star, dead at 71', $first_item->title); + + self::assertEquals('https://cdn.cnn.com/cnnnext/dam/assets/221205172141-kirstie-alley-2005-super-169.jpg', $first_item->{'media:group'}->{'media:content'}->url); + } +} \ No newline at end of file diff --git a/tests/resources/basic.xml b/tests/resources/basic.xml new file mode 100644 index 0000000..11dd2f7 --- /dev/null +++ b/tests/resources/basic.xml @@ -0,0 +1,20 @@ + + + + + test Home Page + https://www.test.com + Free web building tutorials + + RSS Tutorial + https://www.test.com/xml/xml_rss.asp + New RSS tutorial on test + + + XML Tutorial + https://www.test.com/xml + New XML tutorial on test + + + + \ No newline at end of file diff --git a/tests/resources/media/cnn.xml b/tests/resources/media/cnn.xml new file mode 100644 index 0000000..f0ad899 --- /dev/null +++ b/tests/resources/media/cnn.xml @@ -0,0 +1,1383 @@ + + + + <![CDATA[CNN.com - RSS Channel - Entertainment]]> + + + https://www.cnn.com/entertainment/index.html + + http://i2.cdn.turner.com/cnn/2015/images/09/24/cnn.digital.png + CNN.com - RSS Channel - Entertainment + https://www.cnn.com/entertainment/index.html + + coredev-bumblebee + Wed, 05 Apr 2023 08:57:36 GMT + Tue, 06 Dec 2022 20:13:31 GMT + + + 10 + + <![CDATA[Kirstie Alley, 'Cheers' and 'Veronica's Closet' star, dead at 71]]> + + + https://www.cnn.com/2022/12/05/entertainment/kirstie-alley-obit/index.html + https://www.cnn.com/2022/12/05/entertainment/kirstie-alley-obit/index.html + Tue, 06 Dec 2022 12:59:28 GMT + + + + + + + + + + + + + + + + <![CDATA[John Travolta and Kirstie Alley: A love story]]> + + + https://www.cnn.com/2022/12/06/entertainment/john-travolta-kirstie-alley/index.html + + https://www.cnn.com/2022/12/06/entertainment/john-travolta-kirstie-alley/index.html + + Tue, 06 Dec 2022 14:22:24 GMT + + + + + + + + + + + + + + + + + <![CDATA[Chelsea Handler, Leslie Jones and John Leguizamo among guest hosts to step in for Trevor Noah on 'The Daily Show']]> + + + https://www.cnn.com/2022/12/06/entertainment/chelsea-handler-leslie-jones-daily-show/index.html + + https://www.cnn.com/2022/12/06/entertainment/chelsea-handler-leslie-jones-daily-show/index.html + + Tue, 06 Dec 2022 20:30:42 GMT + + + + + + + + + + + + + + + + <![CDATA[Ashton Kutcher and twin Michael talk health, guilt and rift between them]]> + + + https://www.cnn.com/2022/12/06/entertainment/ashton-kutcher-michael/index.html + https://www.cnn.com/2022/12/06/entertainment/ashton-kutcher-michael/index.html + + Tue, 06 Dec 2022 15:42:43 GMT + + + + + + + + + + + + + + + + <![CDATA[Bong Joon Ho's 'Mickey 17' gets trailer and release date]]> + + + https://www.cnn.com/2022/12/06/entertainment/bong-joon-ho-mickey-17-trailer-new-movie/index.html + + + https://www.cnn.com/2022/12/06/entertainment/bong-joon-ho-mickey-17-trailer-new-movie/index.html + + Tue, 06 Dec 2022 17:01:45 GMT + + + + + + + + + + + + + + + + <![CDATA[K-pop band Blackpink selected as Time Entertainer of the Year 2022]]> + + + + https://www.cnn.com/2022/12/06/entertainment/blackpink-time-entertainer-of-the-year-2022-intl-scli/index.html + + + https://www.cnn.com/2022/12/06/entertainment/blackpink-time-entertainer-of-the-year-2022-intl-scli/index.html + + Tue, 06 Dec 2022 11:18:19 GMT + + + + + + + + + + + + + + + + <![CDATA[Gabourey Sidibe reveals she's been secretly married for over a year]]> + + + https://www.cnn.com/2022/12/05/entertainment/gabourey-sidibe-married-brandon-frankel/index.html + + https://www.cnn.com/2022/12/05/entertainment/gabourey-sidibe-married-brandon-frankel/index.html + + Mon, 05 Dec 2022 21:53:05 GMT + + + + + + + + + + + + + + + + <![CDATA['Harry & Meghan' series gets release date and new trailer ]]> + + + https://www.cnn.com/2022/12/05/entertainment/harry-meghan-netflix-date/index.html + https://www.cnn.com/2022/12/05/entertainment/harry-meghan-netflix-date/index.html + + Mon, 05 Dec 2022 14:13:14 GMT + + + + + + + + + + + + + + + + + <![CDATA[Jill Scott announces 'Who is Jill Scott? Words & Sounds Vol. 1' 23rd anniversary tour]]> + + + https://www.cnn.com/2022/12/05/entertainment/jill-scott-tour-music/index.html + https://www.cnn.com/2022/12/05/entertainment/jill-scott-tour-music/index.html + + Mon, 05 Dec 2022 18:20:24 GMT + + + + + + + + + + + + + + + + <![CDATA[Adam Sandler still gets emotional singing sweet Chris Farley song]]> + + https://www.cnn.com/2022/12/05/entertainment/adam-sandler-chris-farley-song-snl/index.html + + https://www.cnn.com/2022/12/05/entertainment/adam-sandler-chris-farley-song-snl/index.html + + Mon, 05 Dec 2022 15:04:40 GMT + + + + + + + + + + + + + + + + + <![CDATA[Neil Diamond surprises audience with 'Sweet Caroline' performance at Broadway opening of 'A Beautiful Noise']]> + + + https://www.cnn.com/2022/12/05/entertainment/neil-diamond-sweet-caroline-broadway-sing/index.html + + + https://www.cnn.com/2022/12/05/entertainment/neil-diamond-sweet-caroline-broadway-sing/index.html + + Tue, 06 Dec 2022 13:41:03 GMT + + + + + + + + + + + + + + + + <![CDATA[George Clooney has a simple strategy for being a star in the age of social media]]> + + + https://www.cnn.com/2022/12/04/entertainment/george-clooney-star-social-media/index.html + + https://www.cnn.com/2022/12/04/entertainment/george-clooney-star-social-media/index.html + + Sun, 04 Dec 2022 23:42:59 GMT + + + + + + + + + + + + + + + + + <![CDATA[Ben Affleck says Netflix's 'assembly line' approach to making quality films is 'an impossible job']]> + + + https://www.cnn.com/2022/12/04/entertainment/ben-affleck-netflix-assembly-line/index.html + + https://www.cnn.com/2022/12/04/entertainment/ben-affleck-netflix-assembly-line/index.html + + Mon, 05 Dec 2022 02:21:54 GMT + + + + + + + + + + + + + + + + + <![CDATA[Keke Palmer reveals baby bump as part of her 'Saturday Night Live' opening monologue]]> + + + https://www.cnn.com/2022/12/04/entertainment/keke-palmer-baby-bump-snl-monologue/index.html + + https://www.cnn.com/2022/12/04/entertainment/keke-palmer-baby-bump-snl-monologue/index.html + + Sun, 04 Dec 2022 18:33:52 GMT + + + + + + + + + + + + + + + + <![CDATA[Christine McVie's music: 5 songs to listen to in her honor]]> + + + https://www.cnn.com/2022/12/01/entertainment/christine-mcvie-music/index.html + https://www.cnn.com/2022/12/01/entertainment/christine-mcvie-music/index.html + + Thu, 01 Dec 2022 19:08:38 GMT + + + + + + + + + + + + + + + + <![CDATA[Axl Rose will stop tossing mic after a fan was reportedly injured ]]> + + https://www.cnn.com/2022/12/05/entertainment/axl-rose-microphone/index.html + https://www.cnn.com/2022/12/05/entertainment/axl-rose-microphone/index.html + Mon, 05 Dec 2022 14:15:44 GMT + + + + + + + + + + + + + + + + + <![CDATA[Harrison Ford cracks the whip in teaser trailer for 'Indiana Jones and the Dial of Destiny']]> + + + https://www.cnn.com/2022/12/01/entertainment/indiana-jones-dial-of-destiny-teaser-trailer/index.html + + + https://www.cnn.com/2022/12/01/entertainment/indiana-jones-dial-of-destiny-teaser-trailer/index.html + + Fri, 02 Dec 2022 03:04:00 GMT + + + + + + + + + + + + + + + + + <![CDATA['Willow' revives the Lucasfilm fantasy with a more contemporary streaming adventure]]> + + + https://www.cnn.com/2022/11/30/entertainment/willow-review/index.html + https://www.cnn.com/2022/11/30/entertainment/willow-review/index.html + Wed, 30 Nov 2022 17:23:24 GMT + + + + + + + + + + + + + + + + <![CDATA['Love Actually' director feels 'a bit stupid' about movie's lack of diversity]]> + + + + https://www.cnn.com/2022/12/01/entertainment/love-actually-richard-curtis-diversity-scli-intl/index.html + + + https://www.cnn.com/2022/12/01/entertainment/love-actually-richard-curtis-diversity-scli-intl/index.html + + Thu, 01 Dec 2022 14:24:40 GMT + + + + + + + + + + + + + + + + + <![CDATA[Joe Pesci says playing Harry in the 'Home Alone' films came with some 'serious' pain]]> + + + https://www.cnn.com/2022/11/30/entertainment/joe-pesci-burns-home-alone-2/index.html + + https://www.cnn.com/2022/11/30/entertainment/joe-pesci-burns-home-alone-2/index.html + + Thu, 01 Dec 2022 01:02:12 GMT + + + + + + + + + + + + + + + + <![CDATA[Inside Christine McVie's and Stevie Nicks' decades-long friendship]]> + + + https://www.cnn.com/2022/12/01/entertainment/stevie-nicks-christine-mcvie-friendship-cec/index.html + + + https://www.cnn.com/2022/12/01/entertainment/stevie-nicks-christine-mcvie-friendship-cec/index.html + + Thu, 01 Dec 2022 17:54:53 GMT + + + + + + + + + + + + + + + + + <![CDATA[Will Smith, opening up about Oscars slap, tells Trevor Noah 'hurt people hurt people']]> + + + https://www.cnn.com/2022/11/29/entertainment/will-smith-daily-show/index.html + https://www.cnn.com/2022/11/29/entertainment/will-smith-daily-show/index.html + + Tue, 29 Nov 2022 17:02:36 GMT + + + + + + + + + + + + + + + + <![CDATA['Super Mario Bros. Movie' trailer shows being a hero isn't all fun and games]]> + + + https://www.cnn.com/2022/11/30/entertainment/super-mario-bros-movie-trailer-two/index.html + + https://www.cnn.com/2022/11/30/entertainment/super-mario-bros-movie-trailer-two/index.html + + Wed, 30 Nov 2022 17:10:09 GMT + + + + + + + + + + + + + + + + + <![CDATA['The Phantom of the Opera' extends Broadway run for eight weeks due to high demand]]> + + + + https://www.cnn.com/2022/11/29/entertainment/the-phantom-of-the-opera-broadway-longer-extension/index.html + + + https://www.cnn.com/2022/11/29/entertainment/the-phantom-of-the-opera-broadway-longer-extension/index.html + + Tue, 29 Nov 2022 18:40:18 GMT + + + + + + + + + + + + + + + + <![CDATA[Kim Kardashian and Kanye West reach divorce settlement]]> + + + https://www.cnn.com/2022/11/29/entertainment/kim-kardashian-kanye-west-divorce/index.html + + https://www.cnn.com/2022/11/29/entertainment/kim-kardashian-kanye-west-divorce/index.html + + Wed, 30 Nov 2022 15:56:36 GMT + + + + + + + + + + + + + + + + <![CDATA[Marsai Martin and Omari Harwick play to win in 'Fantasy Football']]> + + + + https://www.cnn.com/2022/11/23/entertainment/marsai-martin-omari-hardwick-fantasy-football/index.html + + + https://www.cnn.com/2022/11/23/entertainment/marsai-martin-omari-hardwick-fantasy-football/index.html + + Wed, 23 Nov 2022 14:10:45 GMT + + + + + + + + + + + + + + + + + <![CDATA[In 'Wednesday,' Jenna Ortega makes Netflix's Addams Family series look like a snap]]> + + + https://www.cnn.com/2022/11/22/entertainment/wednesday-review/index.html + https://www.cnn.com/2022/11/22/entertainment/wednesday-review/index.html + Tue, 22 Nov 2022 14:45:05 GMT + + + + + + + + + + + + + + + + <![CDATA['Glass Onion' sharpens the 'Knives Out' formula in a polished Netflix sequel]]> + + + https://www.cnn.com/2022/11/23/entertainment/glass-onion-a-knives-out-mystery-review/index.html + + https://www.cnn.com/2022/11/23/entertainment/glass-onion-a-knives-out-mystery-review/index.html + + Wed, 23 Nov 2022 14:00:36 GMT + + + + + + + + + + + + + + + + <![CDATA['Love Actually' cast to reunite for 20th anniversary TV special]]> + + + https://www.cnn.com/2022/11/22/entertainment/love-actually-20th-anniversary-abc-special/index.html + + + https://www.cnn.com/2022/11/22/entertainment/love-actually-20th-anniversary-abc-special/index.html + + Wed, 23 Nov 2022 23:02:35 GMT + + + + + + + + + + + + + + + + + <![CDATA[James Cameron almost didn't choose Leonardo DiCaprio or Kate Winslet to star in 'Titanic']]> + + + + https://www.cnn.com/2022/11/22/entertainment/james-cameron-leonardo-dicaprio-kate-winslet-titanic/index.html + + + https://www.cnn.com/2022/11/22/entertainment/james-cameron-leonardo-dicaprio-kate-winslet-titanic/index.html + + Wed, 23 Nov 2022 15:24:00 GMT + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/resources/media/music-video.xml b/tests/resources/media/music-video.xml new file mode 100644 index 0000000..9563047 --- /dev/null +++ b/tests/resources/media/music-video.xml @@ -0,0 +1,32 @@ + + + + Music Videos 101 + http://www.foo.com + Discussions of great videos + + The latest video from an artist + http://www.foo.com/item1.htm + + + dfdec888b72151965a34b4b59031290a + producer's name + artist's name + + music/artistname/album/song + + + Oh, say, can you see, by the dawn's early light + + nonadult + + start=2002-10-13T09:00+01:00; + end=2002-10-17T17:00+01:00; + scheme=W3C-DTF + + + + + \ No newline at end of file diff --git a/tests/resources/media/trailer.xml b/tests/resources/media/trailer.xml new file mode 100644 index 0000000..91dd506 --- /dev/null +++ b/tests/resources/media/trailer.xml @@ -0,0 +1,19 @@ + + + + My Movie Review Site + http://www.foo.com + I review movies. + + Movie Title: Is this a good movie? + http://www.foo.com/item1.htm + + + http://www.creativecommons.org/licenses/by-nc/1.0 + + nonadult + + + \ No newline at end of file