diff --git a/lib/Parser/HTTP/Message.php b/lib/Parser/HTTP/Message.php
index 411ef2e..515fe19 100644
--- a/lib/Parser/HTTP/Message.php
+++ b/lib/Parser/HTTP/Message.php
@@ -14,12 +14,15 @@ use Psr\Http\Message\MessageInterface;
class Message {
protected const TYPE_PATTERN = '/^[A-Za-z0-9!#$%&\'*+\-\.\^_`|~]+\/[A-Za-z0-9!#$%&\'*+\-\.\^_`|~]+\s*(;.*)?$/s';
- protected const DATE_PATTERN = '/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d\d (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d\d:\d\d:\d\d GMT|(?:Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day, \d\d-(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-\d\d \d\d:\d\d:\d\d GMT|(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun) (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (?:\d\d| \d) \d\d:\d\d:\d\d \d{4})$/';
+ protected const DATE_PATTERN = '/^(?|(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d\d (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d\d:\d\d:\d\d GMT|(Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day, \d\d-(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-\d\d \d\d:\d\d:\d\d GMT|(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (?:\d\d| \d) \d\d:\d\d:\d\d \d{4})$/';
protected const ETAG_PATTERN = '/^.+$/';
protected const CCON_PATTERN = '/(?:^|,)\s*[^=,]+(?:=(?:"(?:\\"|[^"])*"[^,]*|[^,]*))?/';
+ protected const SDAY_MAP = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
+ protected const FDAY_MAP = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
/** @var \Psr\Http\Message\MessageInterface */
protected $msg;
+ protected $url;
public function __construct(MessageInterface $msg, string $url = null) {
$this->msg = $msg;
@@ -29,6 +32,7 @@ class Message {
}
public function parse(FeedStruct $feed = null): FeedStruct {
+ $feed = $feed ?? new FeedStruct;
$feed->meta->url = strlen($this->url ?? "") ? new Url($this->url) : null;
$feed->meta->type = $this->getContentType();
$feed->meta->date = $this->getDate();
@@ -55,9 +59,17 @@ class Message {
}
protected function parseDate(string $name): ?Date {
- $d = $this->parseHeader($name, self::DATE_PATTERN);
- if ($d) {
- return Date::createFromString($d[0]);
+ foreach ($this->msg->getHeader($name) as $h) {
+ if (preg_match(self::DATE_PATTERN, $h, $match)) {
+ $out = Date::createFromString($match[0]);
+ if ($out) {
+ // ensure the weekday is the correct day for the date
+ $day = $out->format("w");
+ if (self::SDAY_MAP[$day] === $match[1] || self::FDAY_MAP[$day] === $match[1]) {
+ return $out;
+ }
+ }
+ }
}
return null;
}
@@ -88,7 +100,8 @@ class Message {
public function getMaxAge(): ?\DateInterval {
$c = $this->parseHeader("Cache-Control", self::CCON_PATTERN, true);
- var_export($c);
- exit;
+ //var_export($c);
+ //exit;
+ return null;
}
}
diff --git a/tests/cases/AbstractParserTestCase.php b/tests/cases/AbstractParserTestCase.php
index 4186e31..441551a 100644
--- a/tests/cases/AbstractParserTestCase.php
+++ b/tests/cases/AbstractParserTestCase.php
@@ -6,35 +6,6 @@
declare(strict_types=1);
namespace MensBeam\Lax\TestCase;
-/* Test format is as follows:
-
- Each test is a YAML map with the following keys:
-
- - `input`: The test input as a string
- - `output`: The result of the parsing upon success; described in more detail below
- - `exception`: The exception ID thrown upon failure
- - `type`: An HTTP Content-Type (with or without parameters) for the document
- - `doc_url`: A fictitious URL where a newsfeed might be located, used for relative URL resolution
-
- The 'input' key along with either 'output' or 'exception' are required for all tests.
-
- The test output is necessarily mangled due to the limits of YAML:
-
- - Any field which should be an absolute URL should be written as a string,
- which will be transformed accordingly. Relative URLs should be represented
- as a sequence with the relative part first, followed by the base that should
- be applied to it
- - Any collections should be represented as sequences of maps, which will
- all be transformed accordingly
- - Rich text can either be supplied as a string (which will yield a Text object
- with plain-text content) or as a map with any of the properties of the
- Text class listed
-
- The transformations as performed by the `makeFeed` and `makeEntry` methods
- of the abstract test case.
-
-*/
-
use MensBeam\Lax\Feed;
use MensBeam\Lax\Date;
use MensBeam\Lax\Text;
@@ -52,6 +23,7 @@ use MensBeam\Lax\Enclosure\Collection as EnclosureCollection;
use MensBeam\Lax\Parser\Exception;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Parser as YamlParser;
+use GuzzleHttp\Psr7\Response;
class AbstractParserTestCase extends \PHPUnit\Framework\TestCase {
protected function provideParserTests(string $glob): iterable {
@@ -62,6 +34,10 @@ class AbstractParserTestCase extends \PHPUnit\Framework\TestCase {
} else {
$test->output = $this->makeFeed($test->output);
}
+ if (is_object($test->input)) {
+ assert((isset($test->input->head) && $test->input->head instanceof \stdClass) || (isset($test->input->body) && is_string($test->input->body)), "Input is not in a correct format");
+ $test->input = new Response($test->input->status ?? 200, (array) ($test->input->head ?? []), $test->input->body ?? null);
+ }
yield "$file: {$description}" => [
$test->input,
$test->type ?? "",
@@ -203,6 +179,8 @@ class AbstractParserTestCase extends \PHPUnit\Framework\TestCase {
foreach ($meta as $k => $v) {
if ($k === 'url') {
$m->$k = new Url($v);
+ } elseif (in_array($k, ["date", "lastModified", "expires"])) {
+ $m->$k = new Date($v);
} else {
$m->$k = $v;
}
diff --git a/tests/cases/HTTP/HTTPTest.php b/tests/cases/HTTP/HTTPTest.php
new file mode 100644
index 0000000..29b2524
--- /dev/null
+++ b/tests/cases/HTTP/HTTPTest.php
@@ -0,0 +1,31 @@
+expectExceptionObject($exp);
+ $p->parse();
+ } else {
+ $act = $p->parse();
+ $this->assertEquals($exp, $act);
+ }
+ }
+
+ public function provideHTTPMessages(): iterable {
+ foreach ($this->provideParserTests(__DIR__."/*.yaml") as $k => $t) {
+ array_splice($t, 1, 1);
+ yield $k => $t;
+ }
+ }
+}
diff --git a/tests/cases/HTTP/http.yaml b/tests/cases/HTTP/http.yaml
new file mode 100644
index 0000000..b29e4b8
--- /dev/null
+++ b/tests/cases/HTTP/http.yaml
@@ -0,0 +1,20 @@
+Dates:
+ input:
+ head:
+ Date: 'Thu, 05 Mar 2020 23:08:55 GMT'
+ Expires: 'Fri, 06 Mar 2020 09:22:00 GMT'
+ Last-Modified: 'Tue, 03 Mar 2020 06:14:00 GMT'
+ output:
+ meta:
+ date: '2020-03-05T23:08:55Z'
+ expires: '2020-03-06T09:22:00Z'
+ lastModified: '2020-03-03T06:14:00Z'
+
+Invalid dates:
+ input:
+ head:
+ Date: 'Thu, 05 Mar 2020 25:08:55 GMT'
+ Expires: 'Fri, 06 Mar 2020 09:22:00 EST'
+ Last-Modified: 'Wed, 03 Mar 2020 06:14:00 GMT'
+ output:
+ meta: {}
diff --git a/tests/cases/README.md b/tests/cases/README.md
new file mode 100644
index 0000000..e068985
--- /dev/null
+++ b/tests/cases/README.md
@@ -0,0 +1,43 @@
+# The Lax test suite
+
+## Feed parsing tests
+
+The tests under the `JSON`, `XML`, and `HTTP` directories are parser tests
+with a shared format and test harness. The test harness is largely contained
+in the `AbstractParserTestCase.php` file, which contains the logic to
+transform the tests themselves into native PHP input and output.
+
+Tests are series of YAML files each containing a map (an object), each entry
+an individual test which is itself a map. Tests have the following keys:
+
+- `input`: The test input as a string, or a map (see below)
+- `output`: The result of the parsing upon success; described
+ in more detail below
+- `exception`: The exception ID thrown upon failure
+- `type`: An HTTP Content-Type (with or without parameters) for
+ the document
+- `doc_url`: A fictitious URL where a newsfeed might be located,
+ used for relative URL resolution
+
+The 'input' key along with either 'output' or 'exception' are required for
+all tests. All other keys may or may not be omitted in a test.
+
+The test output is necessarily mangled due to the limits of YAML:
+
+- Any field which should be an absolute URL is written as a string; relative
+ URLs are represented as a sequence with the relative part first, followed
+ by the base that is be applied to it
+- Any collections are represented as sequences of maps
+- Rich text can either be supplied as a string (which represents a Text object
+ with plain-text content) or as a map with any of the properties of the
+ Text class listed
+
+If the test input is a map, it represents a response from an HTTP server,
+with the following keys:
+
+- `status`: The response status code. This is usually omitted
+ and should be assumed to be 200 unless specified
+- `head`: The map of header-field in the response. Each entry
+ may be a string, or a sequence of strings
+- `body`: The message body as a a string; it may be omitted
+ if not relevant to the functionality being tested
diff --git a/tests/phpunit.dist.xml b/tests/phpunit.dist.xml
index 800e430..fac6e43 100644
--- a/tests/phpunit.dist.xml
+++ b/tests/phpunit.dist.xml
@@ -31,5 +31,8 @@
cases/XML
+
+ cases/HTTP
+
diff --git a/vendor-bin/phpunit/composer.json b/vendor-bin/phpunit/composer.json
index bc16564..962cc3b 100644
--- a/vendor-bin/phpunit/composer.json
+++ b/vendor-bin/phpunit/composer.json
@@ -1,6 +1,8 @@
{
"require-dev": {
"phpunit/phpunit": "^9.0",
- "symfony/yaml": "^5.0"
+ "symfony/yaml": "^5.0",
+ "guzzlehttp/guzzle": "^6.5",
+ "guzzlehttp/psr7": "^1.6"
}
}
diff --git a/vendor-bin/phpunit/composer.lock b/vendor-bin/phpunit/composer.lock
index b4bc2ea..3b76126 100644
--- a/vendor-bin/phpunit/composer.lock
+++ b/vendor-bin/phpunit/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "5f6ef85b0137813e2008ed286079c104",
+ "content-hash": "4259aa457f6935c16ad776bc1a3897ea",
"packages": [],
"packages-dev": [
{
@@ -63,6 +63,195 @@
],
"time": "2019-10-21T16:45:58+00:00"
},
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "6.5.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aab4ebd862aa7d04f01a4b51849d657db56d882e",
+ "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.0",
+ "guzzlehttp/psr7": "^1.6.1",
+ "php": ">=5.5",
+ "symfony/polyfill-intl-idn": "^1.11"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
+ "psr/log": "^1.1"
+ },
+ "suggest": {
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.5-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ],
+ "time": "2020-04-18T10:38:46+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "v1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+ "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "time": "2016-12-20T10:07:11+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "1.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "239400de7a173fe9901b9ac7c06497751f00727a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a",
+ "reference": "239400de7a173fe9901b9ac7c06497751f00727a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0",
+ "psr/http-message": "~1.0",
+ "ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "ext-zlib": "*",
+ "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
+ },
+ "suggest": {
+ "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Schultze",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "time": "2019-07-01T23:21:34+00:00"
+ },
{
"name": "myclabs/deep-copy",
"version": "1.9.5",
@@ -825,6 +1014,96 @@
],
"time": "2020-04-03T14:40:04+00:00"
},
+ {
+ "name": "psr/http-message",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "time": "2016-08-06T14:39:51+00:00"
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "time": "2019-03-08T08:55:37+00:00"
+ },
{
"name": "sebastian/code-unit",
"version": "1.0.0",
@@ -1561,6 +1840,224 @@
],
"time": "2020-02-27T09:26:54+00:00"
},
+ {
+ "name": "symfony/polyfill-intl-idn",
+ "version": "v1.15.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-idn.git",
+ "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
+ "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/polyfill-mbstring": "^1.3",
+ "symfony/polyfill-php72": "^1.10"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.15-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Idn\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Laurent Bassin",
+ "email": "laurent@bassin.info"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "idn",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-03-09T19:04:49+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.15.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
+ "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.15-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-03-09T19:04:49+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php72",
+ "version": "v1.15.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php72.git",
+ "reference": "37b0976c78b94856543260ce09b460a7bc852747"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747",
+ "reference": "37b0976c78b94856543260ce09b460a7bc852747",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.15-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php72\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-02-27T09:26:54+00:00"
+ },
{
"name": "symfony/yaml",
"version": "v5.0.7",