Version v0.13.0-dev
This commit is contained in:
parent
04c233f4ad
commit
4b0f3dc9ed
File diff suppressed because it is too large
Load Diff
|
@ -2,24 +2,6 @@
|
|||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit412d4c2afc15769a0fac36e82d8e412c::getLoader();
|
||||
return ComposerAutoloaderInit6063f1b04a2dad456eda2cdae82a650e::getLoader();
|
||||
|
|
|
@ -1,5 +1,19 @@
|
|||
# Changelog
|
||||
|
||||
## 1.9.0 (2024-04-10)
|
||||
|
||||
* Feature / Fix: Forward compatibility with Promise v3.
|
||||
(#56 by @SimonFrings)
|
||||
|
||||
* Feature: Full PHP 8.3 compatibility.
|
||||
(#54 by @yadaiio)
|
||||
|
||||
* Minor documentation improvements.
|
||||
(#53 and #55 by @yadaiio)
|
||||
|
||||
* Update test suite to use new reactphp/async package instead of clue/reactphp-block.
|
||||
(#50 and #57 by @dinooo13 and @SimonFrings)
|
||||
|
||||
## 1.8.0 (2022-09-01)
|
||||
|
||||
* Feature: Full support for PHP 8.1 and PHP 8.2.
|
||||
|
@ -120,7 +134,7 @@
|
|||
|
||||
```php
|
||||
$promise = $proxy->connect('imap.example.com:143');
|
||||
$promise->then(null, function (Exeption $e) {
|
||||
$promise->then(null, function (Exception $e) {
|
||||
if ($e->getCode() === SOCKET_EACCES) {
|
||||
echo 'Failed to authenticate with proxy!';
|
||||
}
|
||||
|
|
|
@ -170,6 +170,8 @@ $proxy->connect('tcp://smtp.googlemail.com:587')->then(function (React\Socket\Co
|
|||
$connection->on('data', function ($chunk) use ($connection) {
|
||||
echo $chunk;
|
||||
});
|
||||
}, function (Exception $e) {
|
||||
echo 'Error: ' . $e->getMessage() . PHP_EOL;
|
||||
});
|
||||
```
|
||||
|
||||
|
@ -189,6 +191,8 @@ $connector->connect('tcp://smtp.googlemail.com:587')->then(function (React\Socke
|
|||
$connection->on('data', function ($chunk) use ($connection) {
|
||||
echo $chunk;
|
||||
});
|
||||
}, function (Exception $e) {
|
||||
echo 'Error: ' . $e->getMessage() . PHP_EOL;
|
||||
});
|
||||
```
|
||||
|
||||
|
@ -215,6 +219,8 @@ $connector->connect('tls://smtp.googlemail.com:465')->then(function (React\Socke
|
|||
$connection->on('data', function ($chunk) use ($connection) {
|
||||
echo $chunk;
|
||||
});
|
||||
}, function (Exception $e) {
|
||||
echo 'Error: ' . $e->getMessage() . PHP_EOL;
|
||||
});
|
||||
```
|
||||
|
||||
|
@ -247,7 +253,7 @@ $browser->get('https://example.com/')->then(function (Psr\Http\Message\ResponseI
|
|||
```
|
||||
|
||||
See also [ReactPHP's HTTP client](https://github.com/reactphp/http#client-usage)
|
||||
and any of the [examples](examples) for more details.
|
||||
and any of the [examples](examples/) for more details.
|
||||
|
||||
#### Connection timeout
|
||||
|
||||
|
@ -275,6 +281,8 @@ $connector = new React\Socket\Connector(array(
|
|||
|
||||
$connector->connect('tcp://google.com:80')->then(function ($connection) {
|
||||
// connection succeeded within 3.0 seconds
|
||||
}, function (Exception $e) {
|
||||
echo 'Error: ' . $e->getMessage() . PHP_EOL;
|
||||
});
|
||||
```
|
||||
|
||||
|
@ -412,6 +420,8 @@ $proxy = new Clue\React\HttpProxy\ProxyConnector('http+unix:///tmp/proxy.sock');
|
|||
|
||||
$proxy->connect('tcp://google.com:80')->then(function (React\Socket\ConnectionInterface $connection) {
|
||||
// connected…
|
||||
}, function (Exception $e) {
|
||||
echo 'Error: ' . $e->getMessage() . PHP_EOL;
|
||||
});
|
||||
```
|
||||
|
||||
|
@ -441,7 +451,7 @@ This project follows [SemVer](https://semver.org/).
|
|||
This will install the latest supported version:
|
||||
|
||||
```bash
|
||||
composer require clue/http-proxy-react:^1.8
|
||||
composer require clue/http-proxy-react:^1.9
|
||||
```
|
||||
|
||||
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
|
||||
|
|
|
@ -17,15 +17,20 @@
|
|||
"ringcentral/psr7": "^1.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"clue/block-react": "^1.5",
|
||||
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8",
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36",
|
||||
"react/async": "^4 || ^3 || ^2",
|
||||
"react/event-loop": "^1.2",
|
||||
"react/http": "^1.5"
|
||||
"react/http": "^1.5",
|
||||
"react/promise-timer": "^1.10"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Clue\\React\\HttpProxy\\": "src/" }
|
||||
"psr-4": {
|
||||
"Clue\\React\\HttpProxy\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": { "Clue\\Tests\\React\\HttpProxy\\": "tests/" }
|
||||
"psr-4": {
|
||||
"Clue\\Tests\\React\\HttpProxy\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,6 +159,8 @@ class ProxyConnector implements ConnectorInterface
|
|||
// either close active connection or cancel pending connection attempt
|
||||
$connecting->then(function (ConnectionInterface $stream) {
|
||||
$stream->close();
|
||||
}, function () {
|
||||
// ignore to avoid reporting unhandled rejection
|
||||
});
|
||||
$connecting->cancel();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
github: clue
|
||||
custom: https://clue.engineering/support
|
|
@ -1,2 +0,0 @@
|
|||
/vendor
|
||||
/composer.lock
|
|
@ -1,8 +0,0 @@
|
|||
language: php
|
||||
php:
|
||||
- 5.4
|
||||
- 5.3
|
||||
before_script:
|
||||
- composer install --dev --prefer-source --no-interaction
|
||||
script:
|
||||
- phpunit --coverage-text
|
|
@ -1,5 +1,18 @@
|
|||
# Changelog
|
||||
|
||||
## 0.3.2 (2024-08-07)
|
||||
|
||||
* Feature: Improve PHP 8.4+ support by avoiding implicitly nullable types.
|
||||
(#19 by @clue)
|
||||
|
||||
* Update project structure, homepage and examples.
|
||||
Add `.gitattributes` to exclude dev files from exports.
|
||||
(#16, #20, #21 and #22 by @clue)
|
||||
|
||||
* Update test suite to use GitHub actions for continuous integration (CI),
|
||||
run tests on all PHP versions up to PHP 8.3 and ensure 100% code coverage.
|
||||
(#15 by @SimonFrings and #17 and #18 by @clue)
|
||||
|
||||
## 0.3.1 (2017-06-06)
|
||||
|
||||
* Fix: Fix server-side parsing of legacy inline protocol when multiple requests are processed at once
|
||||
|
@ -9,19 +22,25 @@
|
|||
|
||||
* Feature: Add dedicated and faster `RequestParser` that also support the old
|
||||
inline request protocol.
|
||||
|
||||
* Feature: Message serialization can now be handled directly by the Serializer
|
||||
again without having to construct the appropriate model first.
|
||||
|
||||
* BC break: The `Factory` now has two distinct methods to create parsers:
|
||||
* `createResponseParser()` for a client-side library
|
||||
* `createRequestParser()` for a server-side library / testing framework
|
||||
|
||||
* BC break: Simplified parser API, now `pushIncoming()` returns an array of all
|
||||
parsed message models.
|
||||
|
||||
* BC break: The signature for getting a serialized message from a model was
|
||||
changed and now requires a Serializer passed:
|
||||
|
||||
```php
|
||||
ModelInterface::getMessageSerialized($serializer)
|
||||
```
|
||||
* Many, many performance improvements
|
||||
ModelInterface::getMessageSerialized($serializer)
|
||||
```
|
||||
|
||||
* Many, many performance improvements
|
||||
|
||||
## 0.2.0 (2014-01-21)
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2013 Christian Lück
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -1,20 +1,25 @@
|
|||
# clue/redis-protocol [![Build Status](https://travis-ci.org/clue/php-redis-protocol.png?branch=master)](https://travis-ci.org/clue/php-redis-protocol)
|
||||
# clue/redis-protocol
|
||||
|
||||
A streaming redis protocol parser and serializer written in PHP
|
||||
[![CI status](https://github.com/clue/redis-protocol/actions/workflows/ci.yml/badge.svg)](https://github.com/clue/redis-protocol/actions)
|
||||
[![code coverage](https://img.shields.io/badge/code%20coverage-100%25-success)](#tests)
|
||||
[![installs on Packagist](https://img.shields.io/packagist/dt/clue/redis-protocol?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/clue/redis-protocol)
|
||||
|
||||
This parser and serializer implementation allows you to parse redis protocol
|
||||
A streaming Redis protocol (RESP) parser and serializer written in pure PHP.
|
||||
|
||||
This parser and serializer implementation allows you to parse Redis protocol
|
||||
messages into native PHP values and vice-versa. This is usually needed by a
|
||||
redis client implementation which also handles the connection socket.
|
||||
Redis client implementation which also handles the connection socket.
|
||||
|
||||
To re-iterate: This is *not* a redis client implementation. This is a protocol
|
||||
implementation that is usually used by a redis client implementation. If you're
|
||||
To re-iterate: This is *not* a Redis client implementation. This is a protocol
|
||||
implementation that is usually used by a Redis client implementation. If you're
|
||||
looking for an easy way to build your own client implementation, then this is
|
||||
for you. If you merely want to connect to a redis server and issue some
|
||||
for you. If you merely want to connect to a Redis server and issue some
|
||||
commands, you're probably better off using one of the existing client
|
||||
implementations.
|
||||
|
||||
**Table of contents**
|
||||
|
||||
* [Support us](#support-us)
|
||||
* [Quickstart example](#quickstart-example)
|
||||
* [Usage](#usage)
|
||||
* [Factory](#factory)
|
||||
|
@ -22,14 +27,27 @@ implementations.
|
|||
* [Model](#model)
|
||||
* [Serializer](#serializer)
|
||||
* [Install](#install)
|
||||
* [Tests](#tests)
|
||||
* [License](#license)
|
||||
|
||||
## Support us
|
||||
|
||||
We invest a lot of time developing, maintaining and updating our awesome
|
||||
open-source projects. You can help us sustain this high-quality of our work by
|
||||
[becoming a sponsor on GitHub](https://github.com/sponsors/clue). Sponsors get
|
||||
numerous benefits in return, see our [sponsoring page](https://github.com/sponsors/clue)
|
||||
for details.
|
||||
|
||||
Let's take these projects to the next level together! 🚀
|
||||
|
||||
## Quickstart example
|
||||
|
||||
```php
|
||||
use Clue\Redis\Protocol;
|
||||
<?php
|
||||
|
||||
$factory = new Protocol\Factory();
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
$factory = new Clue\Redis\Protocol\Factory();
|
||||
$parser = $factory->createResponseParser();
|
||||
$serializer = $factory->createSerializer();
|
||||
|
||||
|
@ -47,6 +65,8 @@ var_dump($reply1->getValueNative()); // string(2) "OK"
|
|||
var_dump($reply2->getValueNative()); // string(5) "value"
|
||||
```
|
||||
|
||||
See also the [examples](examples/).
|
||||
|
||||
## Usage
|
||||
|
||||
### Factory
|
||||
|
@ -59,15 +79,15 @@ your use-case).
|
|||
|
||||
### Parser
|
||||
|
||||
The library includes a streaming redis protocol parser. As such, it can safely
|
||||
parse redis protocol messages and work with an incomplete data stream. For this,
|
||||
The library includes a streaming Redis protocol parser. As such, it can safely
|
||||
parse Redis protocol messages and work with an incomplete data stream. For this,
|
||||
each included parser implements a single method
|
||||
`ParserInterface::pushIncoming($chunk)`.
|
||||
|
||||
* The `ResponseParser` is what most redis client implementation would want to
|
||||
use in order to parse incoming response messages from a redis server instance.
|
||||
* The `RequestParser` can be used to test messages coming from a redis client or
|
||||
even to implement a redis server.
|
||||
* The `ResponseParser` is what most Redis client implementation would want to
|
||||
use in order to parse incoming response messages from a Redis server instance.
|
||||
* The `RequestParser` can be used to test messages coming from a Redis client or
|
||||
even to implement a Redis server.
|
||||
* The `MessageBuffer` decorates either of the available parsers and merely
|
||||
offers some helper methods in order to work with single messages:
|
||||
* `hasIncomingModel()` to check if there's a complete message in the pipeline
|
||||
|
@ -118,17 +138,44 @@ assert($model implement Model\MultiBulkReply);
|
|||
## Install
|
||||
|
||||
It's very unlikely you'll want to use this protocol parser standalone.
|
||||
It should be added as a dependency to your redis client implementation instead.
|
||||
The recommended way to install this library is [through Composer](https://getcomposer.org).
|
||||
It should be added as a dependency to your Redis client implementation instead.
|
||||
The recommended way to install this library is [through Composer](https://getcomposer.org/).
|
||||
[New to Composer?](https://getcomposer.org/doc/00-intro.md)
|
||||
|
||||
This will install the latest supported version:
|
||||
|
||||
```bash
|
||||
$ composer require clue/redis-protocol:^0.3.1
|
||||
composer require clue/redis-protocol:^0.3.2
|
||||
```
|
||||
|
||||
More details and upgrade guides can be found in the [CHANGELOG](CHANGELOG.md).
|
||||
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
|
||||
|
||||
This project aims to run on any platform and thus does not require any PHP
|
||||
extensions and supports running on legacy PHP 5.3 through current PHP 8+.
|
||||
It's *highly recommended to use the latest supported PHP version* for this project.
|
||||
|
||||
## Tests
|
||||
|
||||
To run the test suite, you first need to clone this repo and then install all
|
||||
dependencies [through Composer](https://getcomposer.org/):
|
||||
|
||||
```bash
|
||||
composer install
|
||||
```
|
||||
|
||||
To run the test suite, go to the project root and run:
|
||||
|
||||
```bash
|
||||
vendor/bin/phpunit
|
||||
```
|
||||
|
||||
The test suite is set up to always ensure 100% code coverage across all
|
||||
supported environments. If you have the Xdebug extension installed, you can also
|
||||
generate a code coverage report locally like this:
|
||||
|
||||
```bash
|
||||
XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
|
@ -136,4 +183,7 @@ Its parser and serializer originally used to be based on
|
|||
[jpd/redisent](https://github.com/jdp/redisent), which is released under the ISC
|
||||
license, copyright (c) 2009-2012 Justin Poliey <justin@getglue.com>.
|
||||
|
||||
Other than that, this library is MIT licensed.
|
||||
Other than that, this project is released under the permissive [MIT license](LICENSE).
|
||||
|
||||
> Did you know that I offer custom development services and issuing invoices for
|
||||
sponsorships of releases and for contributions? Contact me (@clue) for details.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "clue/redis-protocol",
|
||||
"description": "A streaming redis wire protocol parser and serializer implementation in PHP",
|
||||
"keywords": ["streaming", "redis", "protocol", "parser", "serializer"],
|
||||
"homepage": "https://github.com/clue/php-redis-protocol",
|
||||
"description": "A streaming Redis protocol (RESP) parser and serializer written in pure PHP.",
|
||||
"keywords": ["streaming", "redis", "protocol", "resp", "parser", "serializer"],
|
||||
"homepage": "https://github.com/clue/redis-protocol",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
|
@ -13,7 +13,17 @@
|
|||
"require": {
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Clue\\Redis\\Protocol": "src" }
|
||||
"psr-4": {
|
||||
"Clue\\Redis\\Protocol\\": "src/"
|
||||
}
|
||||
} ,
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Clue\\Tests\\Redis\\Protocol\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Clue\Redis\Protocol;
|
||||
|
||||
$factory = new Protocol\Factory();
|
||||
$parser = $factory->createResponseParser();
|
||||
$serializer = $factory->createSerializer();
|
||||
|
||||
$fp = fsockopen('tcp://localhost', 6379);
|
||||
fwrite($fp, $serializer->getRequestMessage('SET', array('name', 'value')));
|
||||
fwrite($fp, $serializer->getRequestMessage('GET', array('name')));
|
||||
|
||||
// the commands are pipelined, so this may parse multiple responses
|
||||
$models = $parser->pushIncoming(fread($fp, 4096));
|
||||
|
||||
$reply1 = array_shift($models);
|
||||
$reply2 = array_shift($models);
|
||||
|
||||
var_dump($reply1->getValueNative()); // string(2) "OK"
|
||||
var_dump($reply2->getValueNative()); // string(5) "value"
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\ProtocolBuffer;
|
||||
use Clue\Redis\Protocol\Factory;
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$factory = new Factory();
|
||||
$parser = $factory->createResponseParser();
|
||||
$serializer = $factory->createSerializer();
|
||||
|
||||
$n = isset($argv[1]) ? (int)$argv[1] : 10000; // number of dummy messages to parse
|
||||
$cs = 4096; // pretend we can only read 7 bytes at once. more like 4096/8192 usually
|
||||
|
||||
echo 'benchmarking ' . $n . ' messages (chunksize of ' . $cs .' bytes)' . PHP_EOL;
|
||||
|
||||
$time = microtime(true);
|
||||
|
||||
$stream = '';
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$stream .= $serializer->getRequestMessage('set', array('var' . $i, 'value' . $i));
|
||||
}
|
||||
|
||||
echo round(microtime(true) - $time, 3) . 's for serialization' . PHP_EOL;
|
||||
$time = microtime(true);
|
||||
|
||||
for ($i = 0, $l = strlen($stream); $i < $l; $i += $cs) {
|
||||
$parser->pushIncoming(substr($stream, $i, $cs));
|
||||
}
|
||||
|
||||
echo round(microtime(true) - $time, 3) . 's for parsing' . PHP_EOL;
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit bootstrap="tests/bootstrap.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Redis Protocol Test Suite">
|
||||
<directory>./tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./src/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Model;
|
||||
|
||||
use Clue\Redis\Protocol\Model\ModelInterface;
|
||||
use Clue\Redis\Protocol\Serializer\SerializerInterface;
|
||||
|
||||
class BulkReply implements ModelInterface
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Model;
|
||||
|
||||
use Exception;
|
||||
use Clue\Redis\Protocol\Serializer\SerializerInterface;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -14,7 +14,7 @@ class ErrorReply extends Exception implements ModelInterface
|
|||
/**
|
||||
* create error status reply (single line error message)
|
||||
*
|
||||
* @param string|ErrorReplyException $message
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
public function __construct($message, $code = 0, $previous = null)
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Model;
|
||||
|
||||
use Clue\Redis\Protocol\Model\ModelInterface;
|
||||
use Clue\Redis\Protocol\Serializer\SerializerInterface;
|
||||
|
||||
class IntegerReply implements ModelInterface
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Model;
|
||||
|
||||
use Clue\Redis\Protocol\Serializer\SerializerInterface;
|
||||
use InvalidArgumentException;
|
||||
use UnexpectedValueException;
|
||||
use Clue\Redis\Protocol\Serializer\SerializerInterface;
|
||||
|
||||
class MultiBulkReply implements ModelInterface
|
||||
{
|
||||
|
@ -19,8 +19,11 @@ class MultiBulkReply implements ModelInterface
|
|||
* @param array|null $data
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(array $data = null)
|
||||
public function __construct($data = null)
|
||||
{
|
||||
if ($data !== null && !is_array($data)) { // manual type check to support legacy PHP < 7.1
|
||||
throw new InvalidArgumentException('Argument #1 ($data) expected array|null');
|
||||
}
|
||||
$this->data = $data;
|
||||
}
|
||||
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Model;
|
||||
|
||||
use Clue\Redis\Protocol\Model\ModelInterface;
|
||||
use Clue\Redis\Protocol\Model\BulkReply;
|
||||
use Clue\Redis\Protocol\Model\MultiBulkReply;
|
||||
use Clue\Redis\Protocol\Serializer\SerializerInterface;
|
||||
|
||||
class Request implements ModelInterface
|
|
@ -14,7 +14,7 @@ class StatusReply implements ModelInterface
|
|||
/**
|
||||
* create status reply (single line message)
|
||||
*
|
||||
* @param string|Status $message
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
public function __construct($message)
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Parser;
|
||||
|
||||
use Clue\Redis\Protocol\Model\ModelInterface;
|
||||
use Clue\Redis\Protocol\Parser\ParserException;
|
||||
|
||||
interface ParserInterface
|
||||
{
|
||||
/**
|
||||
|
@ -20,8 +17,8 @@ interface ParserInterface
|
|||
* message model will be returned once the parser has sufficient data.
|
||||
*
|
||||
* @param string $dataChunk
|
||||
* @return ModelInterface[] 0+ message models
|
||||
* @throws ParserException if the message can not be parsed
|
||||
* @return \Clue\Redis\Protocol\Model\ModelInterface[] 0+ message models
|
||||
* @throws \Clue\Redis\Protocol\Parser\ParserException if the message can not be parsed
|
||||
* @see self::popIncomingModel()
|
||||
*/
|
||||
public function pushIncoming($dataChunk);
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Parser;
|
||||
|
||||
use Clue\Redis\Protocol\Parser\ParserException;
|
||||
use Clue\Redis\Protocol\Model\Request;
|
||||
|
||||
class RequestParser implements ParserInterface
|
|
@ -2,14 +2,12 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Parser;
|
||||
|
||||
use Clue\Redis\Protocol\Parser\ParserInterface;
|
||||
use Clue\Redis\Protocol\Model\ModelInterface;
|
||||
use Clue\Redis\Protocol\Model\BulkReply;
|
||||
use Clue\Redis\Protocol\Model\ErrorReply;
|
||||
use Clue\Redis\Protocol\Model\IntegerReply;
|
||||
use Clue\Redis\Protocol\Model\MultiBulkReply;
|
||||
use Clue\Redis\Protocol\Model\StatusReply;
|
||||
use Clue\Redis\Protocol\Parser\ParserException;
|
||||
|
||||
/**
|
||||
* Simple recursive redis wire protocol parser
|
||||
|
@ -143,7 +141,6 @@ class ResponseParser implements ParserInterface
|
|||
break;
|
||||
default:
|
||||
throw new ParserException('Invalid message can not be parsed: "' . $reply . '"');
|
||||
break;
|
||||
}
|
||||
/* Party on */
|
||||
return $response;
|
|
@ -2,14 +2,13 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Serializer;
|
||||
|
||||
use Clue\Redis\Protocol\Model\StatusReply;
|
||||
use InvalidArgumentException;
|
||||
use Exception;
|
||||
use Clue\Redis\Protocol\Model\BulkReply;
|
||||
use Clue\Redis\Protocol\Model\IntegerReply;
|
||||
use Clue\Redis\Protocol\Model\ErrorReply;
|
||||
use Clue\Redis\Protocol\Model\MultiBulkReply;
|
||||
use Clue\Redis\Protocol\Model\ModelInterface;
|
||||
use Clue\Redis\Protocol\Model\MultiBulkReply;
|
||||
use Clue\Redis\Protocol\Model\Request;
|
||||
|
||||
class RecursiveSerializer implements SerializerInterface
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Clue\Redis\Protocol\Serializer;
|
||||
|
||||
use Clue\Redis\Protocol\Model\ErrorReplyException;
|
||||
use Clue\Redis\Protocol\Model\ModelInterface;
|
||||
use Clue\Redis\Protocol\Model\MultiBulkReply;
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Factory;
|
||||
|
||||
class FactoryTest extends TestCase
|
||||
{
|
||||
private $factory;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->factory = new Factory();
|
||||
}
|
||||
|
||||
public function testCreateResponseParser()
|
||||
{
|
||||
$parser = $this->factory->createResponseParser();
|
||||
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Parser\ParserInterface', $parser);
|
||||
}
|
||||
|
||||
public function testCreateRequestParser()
|
||||
{
|
||||
$parser = $this->factory->createRequestParser();
|
||||
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Parser\ParserInterface', $parser);
|
||||
}
|
||||
|
||||
public function testCreateSerializer()
|
||||
{
|
||||
$serializer = $this->factory->createSerializer();
|
||||
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Serializer\SerializerInterface', $serializer);
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Serializer\RecursiveSerializer;
|
||||
|
||||
abstract class AbstractModelTest extends TestCase
|
||||
{
|
||||
protected $serializer;
|
||||
|
||||
abstract protected function createModel($value);
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->serializer = new RecursiveSerializer();
|
||||
}
|
||||
|
||||
public function testConstructor()
|
||||
{
|
||||
$model = $this->createModel(null);
|
||||
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\ModelInterface', $model);
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Model\BulkReply;
|
||||
|
||||
class BulkReplyTest extends AbstractModelTest
|
||||
{
|
||||
protected function createModel($value)
|
||||
{
|
||||
return new BulkReply($value);
|
||||
}
|
||||
|
||||
public function testStringReply()
|
||||
{
|
||||
$model = $this->createModel('test');
|
||||
|
||||
$this->assertEquals('test', $model->getValueNative());
|
||||
$this->assertEquals("$4\r\ntest\r\n", $model->getMessageSerialized($this->serializer));
|
||||
}
|
||||
|
||||
public function testEmptyStringReply()
|
||||
{
|
||||
$model = $this->createModel('');
|
||||
|
||||
$this->assertEquals('', $model->getValueNative());
|
||||
$this->assertEquals("$0\r\n\r\n", $model->getMessageSerialized($this->serializer));
|
||||
}
|
||||
|
||||
public function testIntegerCast()
|
||||
{
|
||||
$model = $this->createModel(123);
|
||||
|
||||
$this->assertEquals('123', $model->getValueNative());
|
||||
$this->assertEquals("$3\r\n123\r\n", $model->getMessageSerialized($this->serializer));
|
||||
}
|
||||
|
||||
public function testNullBulkReply()
|
||||
{
|
||||
$model = $this->createModel(null);
|
||||
|
||||
$this->assertEquals(null, $model->getValueNative());
|
||||
$this->assertEquals("$-1\r\n", $model->getMessageSerialized($this->serializer));
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Model\ErrorReply;
|
||||
|
||||
class ErrorReplyTest extends AbstractModelTest
|
||||
{
|
||||
protected function createModel($value)
|
||||
{
|
||||
return new ErrorReply($value);
|
||||
}
|
||||
|
||||
public function testError()
|
||||
{
|
||||
$model = $this->createModel('ERR error');
|
||||
|
||||
$this->assertEquals('ERR error', $model->getValueNative());
|
||||
$this->assertEquals("-ERR error\r\n", $model->getMessageSerialized($this->serializer));
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Model\IntegerReply;
|
||||
|
||||
class IntegerReplyTest extends AbstractModelTest
|
||||
{
|
||||
protected function createModel($value)
|
||||
{
|
||||
return new IntegerReply($value);
|
||||
}
|
||||
|
||||
public function testIntegerReply()
|
||||
{
|
||||
$model = $this->createModel(0);
|
||||
$this->assertEquals(0, $model->getValueNative());
|
||||
$this->assertEquals(":0\r\n", $model->getMessageSerialized($this->serializer));
|
||||
}
|
||||
|
||||
public function testFloatCasted()
|
||||
{
|
||||
$model = $this->createModel(-12.99);
|
||||
$this->assertEquals(-12, $model->getValueNative());
|
||||
$this->assertEquals(":-12\r\n", $model->getMessageSerialized($this->serializer));
|
||||
|
||||
$model = $this->createModel(14.99);
|
||||
$this->assertEquals(14, $model->getValueNative());
|
||||
$this->assertEquals(":14\r\n", $model->getMessageSerialized($this->serializer));
|
||||
}
|
||||
|
||||
public function testBooleanCasted()
|
||||
{
|
||||
$model = $this->createModel(true);
|
||||
$this->assertEquals(1, $model->getValueNative());
|
||||
$this->assertEquals(":1\r\n", $model->getMessageSerialized($this->serializer));
|
||||
|
||||
$model = $this->createModel(false);
|
||||
$this->assertEquals(0, $model->getValueNative());
|
||||
$this->assertEquals(":0\r\n", $model->getMessageSerialized($this->serializer));
|
||||
}
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Model\MultiBulkReply;
|
||||
use Clue\Redis\Protocol\Model\BulkReply;
|
||||
use Clue\Redis\Protocol\Model\IntegerReply;
|
||||
|
||||
class MultiBulkReplyTest extends AbstractModelTest
|
||||
{
|
||||
protected function createModel($value)
|
||||
{
|
||||
return new MultiBulkReply($value);
|
||||
}
|
||||
|
||||
public function testEmptyArray()
|
||||
{
|
||||
$model = $this->createModel(array());
|
||||
|
||||
$this->assertEquals(array(), $model->getValueNative());
|
||||
$this->assertEquals("*0\r\n", $model->getMessageSerialized($this->serializer));
|
||||
|
||||
$this->assertFalse($model->isRequest());
|
||||
}
|
||||
|
||||
public function testNullMultiBulkReply()
|
||||
{
|
||||
$model = $this->createModel(null);
|
||||
|
||||
$this->assertEquals(null, $model->getValueNative());
|
||||
$this->assertEquals("*-1\r\n", $model->getMessageSerialized($this->serializer));
|
||||
|
||||
$this->assertFalse($model->isRequest());
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MultiBulkReply $model
|
||||
* @depends testNullMultiBulkReply
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testNullMultiBulkReplyIsNotARequest(MultiBulkReply $model)
|
||||
{
|
||||
$model->getRequestModel();
|
||||
}
|
||||
|
||||
public function testSingleBulkEnclosed()
|
||||
{
|
||||
$model = $this->createModel(array(new BulkReply('test')));
|
||||
|
||||
$this->assertEquals(array('test'), $model->getValueNative());
|
||||
$this->assertEquals("*1\r\n$4\r\ntest\r\n", $model->getMessageSerialized($this->serializer));
|
||||
|
||||
$this->assertTrue($model->isRequest());
|
||||
|
||||
// this can be represented by a request
|
||||
$request = $model->getRequestModel();
|
||||
$this->assertEquals($model->getValueNative(), $request->getValueNative());
|
||||
|
||||
// representing the request as a reply should return our original instance
|
||||
$reply = $request->getReplyModel();
|
||||
$this->assertEquals($model, $reply);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testSingleBulkEnclosed
|
||||
*/
|
||||
public function testStringEnclosedEqualsSingleBulk(MultiBulkReply $expected)
|
||||
{
|
||||
$model = $this->createModel(array('test'));
|
||||
|
||||
$this->assertEquals($expected->getValueNative(), $model->getValueNative());
|
||||
$this->assertEquals($expected->getMessageSerialized($this->serializer), $model->getMessageSerialized($this->serializer));
|
||||
|
||||
$this->assertTrue($model->isRequest());
|
||||
}
|
||||
|
||||
public function testMixedReply()
|
||||
{
|
||||
$model = $this->createModel(array(new BulkReply('test'), new IntegerReply(123)));
|
||||
|
||||
$this->assertEquals(array('test', 123), $model->getValueNative());
|
||||
$this->assertEquals("*2\r\n$4\r\ntest\r\n:123\r\n", $model->getMessageSerialized($this->serializer));
|
||||
|
||||
$this->assertFalse($model->isRequest());
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MultiBulkReply $model
|
||||
* @depends testMixedReply
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testMixedReplyIsNotARequest(MultiBulkReply $model)
|
||||
{
|
||||
$model->getRequestModel();
|
||||
}
|
||||
|
||||
public function testMultiStrings()
|
||||
{
|
||||
$model = $this->createModel(array('SET', 'a', 'b'));
|
||||
|
||||
$this->assertEquals(array('SET', 'a', 'b'), $model->getValueNative());
|
||||
|
||||
$this->assertTrue($model->isRequest());
|
||||
|
||||
$request = $model->getRequestModel();
|
||||
|
||||
// this can be represented by a request
|
||||
$request = $model->getRequestModel();
|
||||
$this->assertEquals($model->getValueNative(), $request->getValueNative());
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Model\Request;
|
||||
|
||||
class RequestTest extends AbstractModelTest
|
||||
{
|
||||
protected function createModel($value)
|
||||
{
|
||||
return new Request('QUIT');
|
||||
}
|
||||
|
||||
public function testPing()
|
||||
{
|
||||
$model = new Request('PING');
|
||||
|
||||
$this->assertEquals('PING', $model->getCommand());
|
||||
$this->assertEquals(array(), $model->getArgs());
|
||||
$this->assertEquals(array('PING'), $model->getValueNative());
|
||||
$this->assertEquals("*1\r\n$4\r\nPING\r\n", $model->getMessageSerialized($this->serializer));
|
||||
|
||||
$reply = $model->getReplyModel();
|
||||
$this->assertEquals($model->getValueNative(), $reply->getValueNative());
|
||||
}
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
$model = new Request('GET', array('a'));
|
||||
|
||||
$this->assertEquals('GET', $model->getCommand());
|
||||
$this->assertEquals(array('a'), $model->getArgs());
|
||||
$this->assertEquals(array('GET', 'a'), $model->getValueNative());
|
||||
$this->assertEquals("*2\r\n$3\r\nGET\r\n$1\r\na\r\n", $model->getMessageSerialized($this->serializer));
|
||||
|
||||
$reply = $model->getReplyModel();
|
||||
$this->assertEquals($model->getValueNative(), $reply->getValueNative());
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Model\StatusReply;
|
||||
|
||||
class StatusReplyTest extends AbstractModelTest
|
||||
{
|
||||
protected function createModel($value)
|
||||
{
|
||||
return new StatusReply($value);
|
||||
}
|
||||
|
||||
public function testStatusOk()
|
||||
{
|
||||
$model = $this->createModel('OK');
|
||||
|
||||
$this->assertEquals('OK', $model->getValueNative());
|
||||
$this->assertEquals("+OK\r\n", $model->getMessageSerialized($this->serializer));
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Parser\ParserInterface;
|
||||
use Clue\Redis\Protocol\Parser\MessageBuffer;
|
||||
|
||||
abstract class AbstractParserTest extends TestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var ParserInterface
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
abstract protected function createParser();
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->parser = $this->createParser();
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Parser\ParserInterface', $this->parser);
|
||||
}
|
||||
|
||||
public function testParsingMessageOne()
|
||||
{
|
||||
// getRequestMessage('test')
|
||||
$message = $expected = "*1\r\n$4\r\ntest\r\n";
|
||||
|
||||
$models = $this->parser->pushIncoming($message);
|
||||
$this->assertCount(1, $models);
|
||||
|
||||
$model = reset($models);
|
||||
$this->assertEquals(array('test'), $model->getValueNative());
|
||||
}
|
||||
|
||||
public function testParsingMessageTwoPartial()
|
||||
{
|
||||
// getRequestMessage('test', array('second'))
|
||||
$message = "*2\r\n$4\r\ntest\r\n$6\r\nsecond\r\n";
|
||||
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming(substr($message, 0, 1)));
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming(substr($message, 1, 1)));
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming(substr($message, 2, 1)));
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming(substr($message, 3, 10)));
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming(substr($message, 13)));
|
||||
|
||||
$model = reset($models);
|
||||
|
||||
$this->assertEquals(array('test', 'second'), $model->getValueNative());
|
||||
}
|
||||
|
||||
public function testMessageBuffer()
|
||||
{
|
||||
$buffer = new MessageBuffer($this->parser);
|
||||
|
||||
$this->assertFalse($buffer->hasIncomingModel());
|
||||
|
||||
$data = "*1\r\n$4\r\ntest\r\n";
|
||||
$this->assertCount(1, $models = $buffer->pushIncoming($data));
|
||||
$this->assertTrue($buffer->hasIncomingModel());
|
||||
|
||||
$expected = reset($models);
|
||||
$this->assertSame($expected, $buffer->popIncomingModel());
|
||||
$this->assertFalse($buffer->hasIncomingModel());
|
||||
|
||||
$this->setExpectedException('UnderflowException');
|
||||
$buffer->popIncomingModel();
|
||||
}
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Parser\RequestParser;
|
||||
|
||||
class RequestParserTest extends AbstractParserTest
|
||||
{
|
||||
protected function createParser()
|
||||
{
|
||||
return new RequestParser();
|
||||
}
|
||||
|
||||
public function testSimplePingRequest()
|
||||
{
|
||||
$message = "*1\r\n$4\r\nping\r\n";
|
||||
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$request = reset($models);
|
||||
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\Request', $request);
|
||||
$this->assertEquals('ping', $request->getCommand());
|
||||
$this->assertEquals(array(), $request->getArgs());
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Request $expected
|
||||
* @depends testSimplePingRequest
|
||||
*/
|
||||
public function testInlinePingRequest($expected)
|
||||
{
|
||||
$message = "ping\r\n";
|
||||
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$request = reset($models);
|
||||
|
||||
$this->assertEquals($expected, $request);
|
||||
}
|
||||
|
||||
public function testInlineWhitespaceIsIgnored()
|
||||
{
|
||||
$message = " set name value \r\n";
|
||||
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$request = reset($models);
|
||||
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\Request', $request);
|
||||
$this->assertEquals('set', $request->getCommand());
|
||||
$this->assertEquals(array('name', 'value'), $request->getArgs());
|
||||
}
|
||||
|
||||
public function testIncompleteSuccessive()
|
||||
{
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming("*1\r\n"));
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming("$4\r\n"));
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming("test"));
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming("\r\n"));
|
||||
}
|
||||
|
||||
public function testNullMultiBulkRequestIsIgnored()
|
||||
{
|
||||
$message = "*-1\r\n";
|
||||
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming($message));
|
||||
}
|
||||
|
||||
public function testEmptyMultiBulkRequestIsIgnored()
|
||||
{
|
||||
$message = "*0\r\n";
|
||||
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming($message));
|
||||
}
|
||||
|
||||
public function testEmptyInlineIsIgnored()
|
||||
{
|
||||
$message = "\r\n";
|
||||
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming($message));
|
||||
}
|
||||
|
||||
public function testInlineParsesMultipleRequestsAtOnce()
|
||||
{
|
||||
$message = "hello\r\n\world\r\ntest\r\n";
|
||||
|
||||
$this->assertCount(3, $models = $this->parser->pushIncoming($message));
|
||||
}
|
||||
|
||||
|
||||
public function testEmptyInlineAroundInlineIsIgnored()
|
||||
{
|
||||
$message = "\r\n\r\n" . "ping\r\n\r\n";
|
||||
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$request = reset($models);
|
||||
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\Request', $request);
|
||||
$this->assertEquals('ping', $request->getCommand());
|
||||
$this->assertEquals(array(), $request->getArgs());
|
||||
}
|
||||
|
||||
public function testWhitespaceInlineIsIgnored()
|
||||
{
|
||||
$message = " \r\n";
|
||||
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming($message));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Clue\Redis\Protocol\Parser\ParserException
|
||||
*/
|
||||
public function testInvalidMultiBulkMustContainBulk()
|
||||
{
|
||||
$message = "*1\r\n:123\r\n";
|
||||
|
||||
$this->parser->pushIncoming($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Clue\Redis\Protocol\Parser\ParserException
|
||||
*/
|
||||
public function testInvalidBulkLength()
|
||||
{
|
||||
$message = "*1\r\n$-1\r\n";
|
||||
|
||||
$this->parser->pushIncoming($message);
|
||||
}
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Parser\ResponseParser;
|
||||
|
||||
class RecursiveParserTest extends AbstractParserTest
|
||||
{
|
||||
protected function createParser()
|
||||
{
|
||||
return new ResponseParser();
|
||||
}
|
||||
|
||||
public function testPartialIncompleteBulkReply()
|
||||
{
|
||||
$this->assertEquals(array(), $this->parser->pushIncoming("$20\r\nincompl"));
|
||||
}
|
||||
|
||||
public function testParsingStatusReplies()
|
||||
{
|
||||
// C: PING
|
||||
$message = "+PONG\r\n";
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals('PONG', $data);
|
||||
|
||||
// C: SET key value
|
||||
$message = "+OK\r\n";
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals('OK', $data);
|
||||
}
|
||||
|
||||
public function testParsingErrorReply()
|
||||
{
|
||||
$message = "-WRONGTYPE Operation against a key holding the wrong kind of value\r\n";
|
||||
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
$exception = reset($models);
|
||||
|
||||
$this->assertInstanceOf('Exception', $exception);
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\ErrorReply', $exception);
|
||||
$this->assertEquals('WRONGTYPE Operation against a key holding the wrong kind of value', $exception->getMessage());
|
||||
}
|
||||
|
||||
public function testParsingIntegerReply()
|
||||
{
|
||||
// C: INCR mykey
|
||||
$message = ":1\r\n";
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals(1, $data);
|
||||
}
|
||||
|
||||
public function testParsingBulkReply()
|
||||
{
|
||||
// C: GET mykey
|
||||
$message = "$6\r\nfoobar\r\n";
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals("foobar", $data);
|
||||
}
|
||||
|
||||
public function testParsingNullBulkReply()
|
||||
{
|
||||
// C: GET nonexistingkey
|
||||
$message = "$-1\r\n";
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals(null, $data);
|
||||
}
|
||||
|
||||
public function testParsingEmptyMultiBulkReply()
|
||||
{
|
||||
// C: LRANGE nokey 0 1
|
||||
$message = "*0\r\n";
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals(array(), $data);
|
||||
}
|
||||
|
||||
public function testParsingNullMultiBulkReply()
|
||||
{
|
||||
// C: BLPOP key 1
|
||||
$message = "*-1\r\n";
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals(null, $data);
|
||||
}
|
||||
|
||||
public function testParsingMultiBulkReplyWithMixedElements()
|
||||
{
|
||||
$message = "*5\r\n:1\r\n:2\r\n:3\r\n:4\r\n$6\r\nfoobar\r\n";
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals(array(1, 2, 3, 4, 'foobar'), $data);
|
||||
}
|
||||
|
||||
public function testParsingMultiBulkReplyWithIncompletePush()
|
||||
{
|
||||
$this->assertCount(0, $this->parser->pushIncoming("*5\r\n:1\r\n:2\r"));
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming("\n:3\r\n:4\r\n$6\r\nfoobar\r\n"));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals(array(1, 2, 3, 4, 'foobar'), $data);
|
||||
}
|
||||
|
||||
public function testParsingMultiBulkReplyWithNullElement()
|
||||
{
|
||||
$message = "*3\r\n$3\r\nfoo\r\n$-1\r\n$3\r\nbar\r\n";
|
||||
$this->assertCount(1, $models = $this->parser->pushIncoming($message));
|
||||
|
||||
$data = reset($models)->getValueNative();
|
||||
$this->assertEquals(array('foo', null, 'bar'), $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Clue\Redis\Protocol\Parser\ParserException
|
||||
*/
|
||||
public function testParseError()
|
||||
{
|
||||
$this->parser->pushIncoming("invalid string\r\n");
|
||||
}
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Serializer\SerializerInterface;
|
||||
use Clue\Redis\Protocol\Model\Status;
|
||||
use Clue\Redis\Protocol\Model\ErrorReplyException;
|
||||
//use Exception;
|
||||
|
||||
abstract class AbstractSerializerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @return SerializerInterface
|
||||
*/
|
||||
abstract protected function createSerializer();
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->serializer = $this->createSerializer();
|
||||
}
|
||||
|
||||
public function testIntegerReply()
|
||||
{
|
||||
$model = $this->serializer->createReplyModel(0);
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\IntegerReply', $model);
|
||||
$this->assertEquals(0, $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage(0));
|
||||
}
|
||||
|
||||
public function testFloatCastIntegerReply()
|
||||
{
|
||||
$model = $this->serializer->createReplyModel(-12.99);
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\IntegerReply', $model);
|
||||
$this->assertEquals(-12, $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage(-12.99));
|
||||
|
||||
$model = $this->serializer->createReplyModel(14.99);
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\IntegerReply', $model);
|
||||
$this->assertEquals(14, $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage(14.99));
|
||||
}
|
||||
|
||||
public function testBooleanCastIntegerReply()
|
||||
{
|
||||
$model = $this->serializer->createReplyModel(true);
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\IntegerReply', $model);
|
||||
$this->assertEquals(1, $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage(true));
|
||||
|
||||
$model = $this->serializer->createReplyModel(false);
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\IntegerReply', $model);
|
||||
$this->assertEquals(0, $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage(false));
|
||||
}
|
||||
|
||||
public function testStringReply()
|
||||
{
|
||||
$model = $this->serializer->createReplyModel('test');
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\BulkReply', $model);
|
||||
$this->assertEquals('test', $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage('test'));
|
||||
}
|
||||
|
||||
public function testNullCastNullBulkReply()
|
||||
{
|
||||
$model = $this->serializer->createReplyModel(null);
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\BulkReply', $model);
|
||||
$this->assertEquals(null, $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage(null));
|
||||
}
|
||||
|
||||
public function testEmptyArrayMultiBulkReply()
|
||||
{
|
||||
$model = $this->serializer->createReplyModel(array());
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\MultiBulkReply', $model);
|
||||
$this->assertEquals(array(), $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage(array()));
|
||||
}
|
||||
|
||||
public function testArrayMultiBulkReply()
|
||||
{
|
||||
$model = $this->serializer->createReplyModel(array('test', 123));
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\MultiBulkReply', $model);
|
||||
$this->assertEquals(array('test', 123), $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage(array('test', 123)));
|
||||
}
|
||||
|
||||
public function testErrorReply()
|
||||
{
|
||||
$model = $this->serializer->createReplyModel(new Exception('ERR failure'));
|
||||
$this->assertInstanceOf('Clue\Redis\Protocol\Model\ErrorReply', $model);
|
||||
$this->assertEquals('ERR failure', $model->getValueNative());
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $this->serializer->getReplyMessage(new Exception('ERR failure')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidArgument()
|
||||
{
|
||||
$this->serializer->createReplyModel((object)array());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidReplyData()
|
||||
{
|
||||
$this->serializer->getReplyMessage((object)array());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $data
|
||||
* @dataProvider provideRequestMessage
|
||||
*/
|
||||
public function testRequestMessage($command, $args)
|
||||
{
|
||||
// the model is already unit-tested, so just compare against its message
|
||||
$model = $this->serializer->createRequestModel($command, $args);
|
||||
|
||||
$message = $this->serializer->getRequestMessage($command, $args);
|
||||
|
||||
$this->assertEquals($model->getMessageSerialized($this->serializer), $message);
|
||||
}
|
||||
|
||||
public function provideRequestMessage()
|
||||
{
|
||||
return array(
|
||||
array('PING', array()),
|
||||
array('GET', array('a')),
|
||||
array('SET', array('a', 'b')),
|
||||
array('SET', array('empty', ''))
|
||||
);
|
||||
}
|
||||
|
||||
// public function testBenchCreateRequest()
|
||||
// {
|
||||
// for ($i = 0; $i < 100000; ++$i) {
|
||||
// $this->serializer->createReplyModel(array('a', 'b', 'c'));
|
||||
// }
|
||||
// }
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Clue\Redis\Protocol\Serializer\RecursiveSerializer;
|
||||
|
||||
class RecursiveSerializerTest extends AbstractSerializerTest
|
||||
{
|
||||
protected function createSerializer()
|
||||
{
|
||||
return new RecursiveSerializer();
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
<?php
|
||||
|
||||
(include_once __DIR__ . '/../vendor/autoload.php') OR die(PHP_EOL . 'ERROR: composer autoloader not found, run "composer install" or see README for instructions' . PHP_EOL);
|
||||
|
||||
class TestCase extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
}
|
|
@ -1,5 +1,24 @@
|
|||
# Changelog
|
||||
|
||||
## 2.8.0 (2025-01-03)
|
||||
|
||||
This is a compatibility release that contains backported features from the `3.x` branch.
|
||||
Once v3 is released, it will be the way forward for this project.
|
||||
|
||||
* Feature: Improve PHP 8.4+ support by avoiding implicitly nullable types.
|
||||
(#165 and #170 by @clue)
|
||||
|
||||
## 2.7.0 (2024-01-05)
|
||||
|
||||
This is a compatibility release that contains backported features from the `3.x` branch.
|
||||
Once v3 is released, it will be the way forward for this project.
|
||||
|
||||
* Feature: Forward compatibility with Promise v3.
|
||||
(#152 by @clue)
|
||||
|
||||
* Feature: Full PHP 8.3 compatibility and update test suite.
|
||||
(#151 by @clue)
|
||||
|
||||
## 2.6.0 (2022-05-09)
|
||||
|
||||
* Feature: Support PHP 8.1 release.
|
||||
|
|
|
@ -610,7 +610,7 @@ This project follows [SemVer](https://semver.org/).
|
|||
This will install the latest supported version:
|
||||
|
||||
```bash
|
||||
$ composer require clue/redis-react:^2.6
|
||||
$ composer require clue/redis-react:^2.8
|
||||
```
|
||||
|
||||
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
|
||||
|
|
|
@ -12,21 +12,25 @@
|
|||
],
|
||||
"require": {
|
||||
"php": ">=5.3",
|
||||
"clue/redis-protocol": "0.3.*",
|
||||
"clue/redis-protocol": "^0.3.2",
|
||||
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
|
||||
"react/event-loop": "^1.2",
|
||||
"react/promise": "^2.0 || ^1.1",
|
||||
"react/promise-timer": "^1.8",
|
||||
"react/socket": "^1.9"
|
||||
"react/promise": "^3.2 || ^2.0 || ^1.1",
|
||||
"react/promise-timer": "^1.11",
|
||||
"react/socket": "^1.16"
|
||||
},
|
||||
"require-dev": {
|
||||
"clue/block-react": "^1.1",
|
||||
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35"
|
||||
"clue/block-react": "^1.5",
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Clue\\React\\Redis\\": "src/" }
|
||||
"psr-4": {
|
||||
"Clue\\React\\Redis\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": { "Clue\\Tests\\React\\Redis\\": "tests/" }
|
||||
"psr-4": {
|
||||
"Clue\\Tests\\React\\Redis\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,20 @@ class Factory
|
|||
/**
|
||||
* @param ?LoopInterface $loop
|
||||
* @param ?ConnectorInterface $connector
|
||||
* @param ?ProtocolFactory $protocol
|
||||
* @param ?ProtocolFactory $protocol (internal, should not usually be passed)
|
||||
*/
|
||||
public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null, ProtocolFactory $protocol = null)
|
||||
public function __construct($loop = null, $connector = null, $protocol = null)
|
||||
{
|
||||
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
|
||||
throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
|
||||
}
|
||||
if ($connector !== null && !$connector instanceof ConnectorInterface) { // manual type check to support legacy PHP < 7.1
|
||||
throw new \InvalidArgumentException('Argument #2 ($connector) expected null|React\Socket\ConnectorInterface');
|
||||
}
|
||||
if ($protocol !== null && !$protocol instanceof ProtocolFactory) { // manual type check to support legacy PHP < 7.1
|
||||
throw new \InvalidArgumentException('Argument #3 ($protocol) expected null|Clue\Redis\Protocol\Factory');
|
||||
}
|
||||
|
||||
$this->loop = $loop ?: Loop::get();
|
||||
$this->connector = $connector ?: new Connector(array(), $this->loop);
|
||||
$this->protocol = $protocol ?: new ProtocolFactory();
|
||||
|
@ -84,6 +94,8 @@ class Factory
|
|||
// either close successful connection or cancel pending connection attempt
|
||||
$connecting->then(function (ConnectionInterface $connection) {
|
||||
$connection->close();
|
||||
}, function () {
|
||||
// ignore to avoid reporting unhandled rejection
|
||||
});
|
||||
$connecting->cancel();
|
||||
});
|
||||
|
|
|
@ -168,6 +168,8 @@ class LazyClient extends EventEmitter implements Client
|
|||
if ($this->promise !== null) {
|
||||
$this->promise->then(function (Client $redis) {
|
||||
$redis->close();
|
||||
}, function () {
|
||||
// ignore to avoid reporting unhandled rejection
|
||||
});
|
||||
if ($this->promise !== null) {
|
||||
$this->promise->cancel();
|
||||
|
|
|
@ -28,8 +28,17 @@ class StreamingClient extends EventEmitter implements Client
|
|||
private $subscribed = 0;
|
||||
private $psubscribed = 0;
|
||||
|
||||
public function __construct(DuplexStreamInterface $stream, ParserInterface $parser = null, SerializerInterface $serializer = null)
|
||||
/**
|
||||
* @param DuplexStreamInterface $stream
|
||||
* @param ?ParserInterface $parser
|
||||
* @param ?SerializerInterface $serializer
|
||||
*/
|
||||
public function __construct(DuplexStreamInterface $stream, $parser = null, $serializer = null)
|
||||
{
|
||||
// manual type checks to support legacy PHP < 7.1
|
||||
assert($parser === null || $parser instanceof ParserInterface);
|
||||
assert($serializer === null || $serializer instanceof SerializerInterface);
|
||||
|
||||
if ($parser === null || $serializer === null) {
|
||||
$factory = new ProtocolFactory();
|
||||
if ($parser === null) {
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
# Changelog
|
||||
|
||||
## 1.4.0 (2024-01-30)
|
||||
|
||||
* Feature: Full PHP 8.3 compatibility.
|
||||
(#38 by @yadaiio and #36 by @clue)
|
||||
|
||||
* Improve documentation and examples.
|
||||
(#37 by @yadaiio, #34 by @SimonFrings and #33 by @PaulRotmann)
|
||||
|
||||
* Improve test suite and use GitHub actions for continuous integration (CI).
|
||||
(#32 by @SimonFrings)
|
||||
|
||||
## 1.3.0 (2020-11-06)
|
||||
|
||||
* Improve test suite and add `.gitattributes` to exclude dev files from export.
|
||||
|
@ -8,7 +19,7 @@
|
|||
|
||||
## 1.2.0 (2018-07-09)
|
||||
|
||||
* Feature: Forward compatiblity with EventLoop v0.5 and upcoming v1.0.
|
||||
* Feature: Forward compatibility with EventLoop v0.5 and upcoming v1.0.
|
||||
(#28 by @clue)
|
||||
|
||||
* Improve test suite by updating Travis config to test against legacy PHP 5.3 through PHP 7.2.
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
# clue/reactphp-term [![Build Status](https://travis-ci.org/clue/reactphp-term.svg?branch=master)](https://travis-ci.org/clue/reactphp-term)
|
||||
# clue/reactphp-term
|
||||
|
||||
[![CI status](https://github.com/clue/reactphp-term/actions/workflows/ci.yml/badge.svg)](https://github.com/clue/reactphp-term/actions)
|
||||
[![installs on Packagist](https://img.shields.io/packagist/dt/clue/term-react?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/clue/term-react)
|
||||
|
||||
Streaming terminal emulator, built on top of [ReactPHP](https://reactphp.org/).
|
||||
|
||||
|
@ -33,7 +36,7 @@ It wraps a given `ReadableStreamInterface` and exposes its plain data through
|
|||
the same interface.
|
||||
|
||||
```php
|
||||
$stdin = new ReadableResourceStream(STDIN, $loop);
|
||||
$stdin = new React\Stream\ReadableResourceStream(STDIN);
|
||||
|
||||
$stream = new ControlCodeParser($stdin);
|
||||
|
||||
|
@ -112,37 +115,36 @@ $stream->on('c0', function ($code) {
|
|||
|
||||
## Install
|
||||
|
||||
The recommended way to install this library is [through Composer](https://getcomposer.org).
|
||||
The recommended way to install this library is [through Composer](https://getcomposer.org/).
|
||||
[New to Composer?](https://getcomposer.org/doc/00-intro.md)
|
||||
|
||||
This project follows [SemVer](https://semver.org/).
|
||||
This will install the latest supported version:
|
||||
|
||||
```bash
|
||||
$ composer require clue/term-react:^1.3
|
||||
|
||||
composer require clue/term-react:^1.4
|
||||
```
|
||||
|
||||
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
|
||||
|
||||
This project aims to run on any platform and thus does not require any PHP
|
||||
extensions and supports running on legacy PHP 5.3 through current PHP 7+ and
|
||||
extensions and supports running on legacy PHP 5.3 through current PHP 8+ and
|
||||
HHVM.
|
||||
It's *highly recommended to use PHP 7+* for this project.
|
||||
It's *highly recommended to use the latest supported PHP version* for this project.
|
||||
|
||||
## Tests
|
||||
|
||||
To run the test suite, you first need to clone this repo and then install all
|
||||
dependencies [through Composer](https://getcomposer.org):
|
||||
dependencies [through Composer](https://getcomposer.org/):
|
||||
|
||||
```bash
|
||||
$ composer install
|
||||
composer install
|
||||
```
|
||||
|
||||
To run the test suite, go to the project root and run:
|
||||
|
||||
```bash
|
||||
$ php vendor/bin/phpunit
|
||||
vendor/bin/phpunit
|
||||
```
|
||||
|
||||
## License
|
||||
|
|
|
@ -10,18 +10,22 @@
|
|||
"email": "christian@clue.engineering"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": { "Clue\\React\\Term\\": "src/" }
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": { "Clue\\Tests\\React\\Term\\": "tests/" }
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3",
|
||||
"react/stream": "^1.0 || ^0.7"
|
||||
"react/stream": "^1.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8",
|
||||
"react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3"
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36",
|
||||
"react/event-loop": "^1.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Clue\\React\\Term\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Clue\\Tests\\React\\Term\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ class ControlCodeParser extends EventEmitter implements ReadableStreamInterface
|
|||
* C1 types in 8 bit are currently not supported, as they require special
|
||||
* care with regards to whether UTF-8 mode is enabled. So far this has
|
||||
* turned out to be a non-issue because most terminal emulators *accept*
|
||||
* boths formats, but usually *send* in 7 bit mode exclusively.
|
||||
* both formats, but usually *send* in 7 bit mode exclusively.
|
||||
*/
|
||||
private $types = array(
|
||||
'[' => 'csi',
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
# Changelog
|
||||
|
||||
## 1.3.0 (2023-12-06)
|
||||
|
||||
* Feature: Full PHP 8.3 compatibility.
|
||||
(#29 by @yadaiio and #27 by @clue)
|
||||
|
||||
* Minor documentation improvements.
|
||||
(#25 by @PaulRotmann, #26 by @SimonFrings and #28 by @yadaiio)
|
||||
|
||||
* Improve test suite, use GitHub actions for continuous integration (CI).
|
||||
(#24 by @SimonFrings)
|
||||
|
||||
## 1.2.0 (2020-11-06)
|
||||
|
||||
* Improve test suite and add `.gitattributes` to exclude dev files from export.
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
# clue/reactphp-utf8 [![Build Status](https://travis-ci.org/clue/reactphp-utf8.svg?branch=master)](https://travis-ci.org/clue/reactphp-utf8)
|
||||
# clue/reactphp-utf8
|
||||
|
||||
[![CI status](https://github.com/clue/reactphp-utf8/actions/workflows/ci.yml/badge.svg)](https://github.com/clue/reactphp-utf8/actions)
|
||||
[![installs on Packagist](https://img.shields.io/packagist/dt/clue/utf8-react?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/clue/utf8-react)
|
||||
|
||||
Streaming UTF-8 parser, built on top of [ReactPHP](https://reactphp.org/).
|
||||
|
||||
|
@ -32,7 +35,11 @@ It wraps a given `ReadableStreamInterface` and exposes its data through the same
|
|||
interface.
|
||||
|
||||
```php
|
||||
$stdin = new ReadableResourceStream(STDIN, $loop);
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
$stdin = new ReadableResourceStream(STDIN);
|
||||
|
||||
$stream = new Sequencer($stdin);
|
||||
|
||||
|
@ -49,7 +56,7 @@ This class reassembles these sequences by buffering incomplete ones.
|
|||
Also, if you're merely consuming a stream and you're not in control of producing and
|
||||
ensuring valid UTF-8 data, it may as well include invalid UTF-8 byte sequences.
|
||||
This class replaces any invalid bytes in the sequence with a `?`.
|
||||
This replacement character can be given as a second paramter to the constructor:
|
||||
This replacement character can be given as a second parameter to the constructor:
|
||||
|
||||
```php
|
||||
$stream = new Sequencer($stdin, 'X');
|
||||
|
@ -64,36 +71,36 @@ This binary data will be left as-is, unless you filter this at a later stage.
|
|||
|
||||
## Install
|
||||
|
||||
The recommended way to install this library is [through Composer](https://getcomposer.org).
|
||||
The recommended way to install this library is [through Composer](https://getcomposer.org/).
|
||||
[New to Composer?](https://getcomposer.org/doc/00-intro.md)
|
||||
|
||||
This project follows [SemVer](https://semver.org/).
|
||||
This will install the latest supported version:
|
||||
|
||||
```bash
|
||||
$ composer require clue/utf8-react:^1.2
|
||||
composer require clue/utf8-react:^1.3
|
||||
```
|
||||
|
||||
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
|
||||
|
||||
This project aims to run on any platform and thus does not require any PHP
|
||||
extensions and supports running on legacy PHP 5.3 through current PHP 7+ and
|
||||
extensions and supports running on legacy PHP 5.3 through current PHP 8+ and
|
||||
HHVM.
|
||||
It's *highly recommended to use PHP 7+* for this project.
|
||||
It's *highly recommended to use the latest supported PHP version* for this project.
|
||||
|
||||
## Tests
|
||||
|
||||
To run the test suite, you first need to clone this repo and then install all
|
||||
dependencies [through Composer](https://getcomposer.org):
|
||||
dependencies [through Composer](https://getcomposer.org/):
|
||||
|
||||
```bash
|
||||
$ composer install
|
||||
composer install
|
||||
```
|
||||
|
||||
To run the test suite, go to the project root and run:
|
||||
|
||||
```bash
|
||||
$ php vendor/bin/phpunit
|
||||
vendor/bin/phpunit
|
||||
```
|
||||
|
||||
## License
|
||||
|
|
|
@ -10,18 +10,22 @@
|
|||
"email": "christian@clue.engineering"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": { "Clue\\React\\Utf8\\": "src/" }
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": { "Clue\\Tests\\React\\Utf8\\": "tests/" }
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3",
|
||||
"react/stream": "^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4 || ^0.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.3 ||^5.7 || ^4.8",
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36",
|
||||
"react/stream": "^1.0 || ^0.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Clue\\React\\Utf8\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Clue\\Tests\\React\\Utf8\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ namespace Clue\React\Utf8;
|
|||
|
||||
use Evenement\EventEmitter;
|
||||
use React\Stream\ReadableStreamInterface;
|
||||
use React\Stream\WritableStreamInterface;
|
||||
use React\Stream\Util;
|
||||
use React\Stream\WritableStreamInterface;
|
||||
|
||||
/**
|
||||
* forwards only complete UTF-8 sequences
|
||||
|
|
|
@ -42,37 +42,35 @@ namespace Composer\Autoload;
|
|||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var string|null */
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array<string, list<string>>
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
|
@ -80,7 +78,8 @@ class ClassLoader
|
|||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
|
@ -88,29 +87,29 @@ class ClassLoader
|
|||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var string|null */
|
||||
/** @var ?string */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var array<string, self>
|
||||
* @var self[]
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param string|null $vendorDir
|
||||
* @param ?string $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
|
@ -122,7 +121,8 @@ class ClassLoader
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
|
@ -130,7 +130,8 @@ class ClassLoader
|
|||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
|
@ -138,7 +139,8 @@ class ClassLoader
|
|||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
|
@ -146,7 +148,8 @@ class ClassLoader
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string> Array of classname => path
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
|
@ -154,7 +157,8 @@ class ClassLoader
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
@ -171,25 +175,24 @@ class ClassLoader
|
|||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$paths,
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
$paths
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -198,19 +201,19 @@ class ClassLoader
|
|||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$paths,
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
$paths
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -219,9 +222,9 @@ class ClassLoader
|
|||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
|
@ -229,18 +232,17 @@ class ClassLoader
|
|||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$paths,
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
$paths
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
|
@ -250,18 +252,18 @@ class ClassLoader
|
|||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$paths,
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
$paths
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -270,8 +272,8 @@ class ClassLoader
|
|||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 base directories
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
@ -288,8 +290,8 @@ class ClassLoader
|
|||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
|
@ -423,8 +425,7 @@ class ClassLoader
|
|||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -475,9 +476,9 @@ class ClassLoader
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
*
|
||||
* @return array<string, self>
|
||||
* @return self[]
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
|
@ -554,26 +555,18 @@ class ClassLoader
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}
|
||||
|
|
|
@ -21,14 +21,12 @@ use Composer\Semver\VersionParser;
|
|||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
|
@ -39,7 +37,7 @@ class InstalledVersions
|
|||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
|
@ -98,7 +96,7 @@ class InstalledVersions
|
|||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +117,7 @@ class InstalledVersions
|
|||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints((string) $constraint);
|
||||
$constraint = $parser->parseConstraints($constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
|
@ -243,7 +241,7 @@ class InstalledVersions
|
|||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
|
@ -257,7 +255,7 @@ class InstalledVersions
|
|||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
|
@ -280,7 +278,7 @@ class InstalledVersions
|
|||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
|
@ -303,7 +301,7 @@ class InstalledVersions
|
|||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
|
@ -313,7 +311,7 @@ class InstalledVersions
|
|||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
|
@ -322,6 +320,7 @@ class InstalledVersions
|
|||
}
|
||||
|
||||
$installed = array();
|
||||
$copiedLocalDir = false;
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
|
@ -330,9 +329,11 @@ class InstalledVersions
|
|||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
self::$installedByVendor[$vendorDir] = $required;
|
||||
$installed[] = $required;
|
||||
if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $required;
|
||||
$copiedLocalDir = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +351,7 @@ class InstalledVersions
|
|||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array()) {
|
||||
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
|
||||
'972fda704d680a3a53c68e34e193cb22' => $vendorDir . '/react/promise-timer/src/functions_include.php',
|
||||
'ebf8799635f67b5d7248946fe2154f4a' => $vendorDir . '/ringcentral/psr7/src/functions_include.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'45b89995831374eefdfc4161161938f6' => $vendorDir . '/jfcherng/php-color-output/src/helpers.php',
|
||||
'ebf8799635f67b5d7248946fe2154f4a' => $vendorDir . '/ringcentral/psr7/src/functions_include.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
@ -11,6 +11,5 @@ return array(
|
|||
'Less' => array($vendorDir . '/wikimedia/less.php/lib'),
|
||||
'JShrink' => array($vendorDir . '/tedivm/jshrink/src'),
|
||||
'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'),
|
||||
'Clue\\Redis\\Protocol' => array($vendorDir . '/clue/redis-protocol/src'),
|
||||
'AssetLoader' => array($baseDir . '/'),
|
||||
);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
@ -44,10 +44,11 @@ return array(
|
|||
'Fig\\Http\\Message\\' => array($vendorDir . '/fig/http-message-util/src'),
|
||||
'Evenement\\' => array($vendorDir . '/evenement/evenement/src'),
|
||||
'Dompdf\\' => array($vendorDir . '/dompdf/dompdf/src'),
|
||||
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/lib/Doctrine/Deprecations'),
|
||||
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'),
|
||||
'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/lib/Doctrine/Common/Collections'),
|
||||
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
|
||||
'ConnectionManager\\Extra\\' => array($vendorDir . '/clue/connection-manager-extra/src'),
|
||||
'Clue\\Redis\\Protocol\\' => array($vendorDir . '/clue/redis-protocol/src'),
|
||||
'Clue\\React\\Utf8\\' => array($vendorDir . '/clue/utf8-react/src'),
|
||||
'Clue\\React\\Term\\' => array($vendorDir . '/clue/term-react/src'),
|
||||
'Clue\\React\\Stdio\\' => array($vendorDir . '/clue/stdio-react/src'),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit412d4c2afc15769a0fac36e82d8e412c
|
||||
class ComposerAutoloaderInit6063f1b04a2dad456eda2cdae82a650e
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
|
@ -24,31 +24,61 @@ class ComposerAutoloaderInit412d4c2afc15769a0fac36e82d8e412c
|
|||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit412d4c2afc15769a0fac36e82d8e412c', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit412d4c2afc15769a0fac36e82d8e412c', 'loadClassLoader'));
|
||||
spl_autoload_register(array('ComposerAutoloaderInit6063f1b04a2dad456eda2cdae82a650e', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit6063f1b04a2dad456eda2cdae82a650e', 'loadClassLoader'));
|
||||
|
||||
$includePaths = require __DIR__ . '/include_paths.php';
|
||||
$includePaths[] = get_include_path();
|
||||
set_include_path(implode(PATH_SEPARATOR, $includePaths));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c::getInitializer($loader));
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit6063f1b04a2dad456eda2cdae82a650e::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit6063f1b04a2dad456eda2cdae82a650e::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire6063f1b04a2dad456eda2cdae82a650e($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileIdentifier
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
function composerRequire6063f1b04a2dad456eda2cdae82a650e($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c
|
||||
class ComposerStaticInit6063f1b04a2dad456eda2cdae82a650e
|
||||
{
|
||||
public static $files = array (
|
||||
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
|
||||
'972fda704d680a3a53c68e34e193cb22' => __DIR__ . '/..' . '/react/promise-timer/src/functions_include.php',
|
||||
'ebf8799635f67b5d7248946fe2154f4a' => __DIR__ . '/..' . '/ringcentral/psr7/src/functions_include.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'45b89995831374eefdfc4161161938f6' => __DIR__ . '/..' . '/jfcherng/php-color-output/src/helpers.php',
|
||||
'ebf8799635f67b5d7248946fe2154f4a' => __DIR__ . '/..' . '/ringcentral/psr7/src/functions_include.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
|
@ -102,6 +102,7 @@ class ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c
|
|||
array (
|
||||
'Cron\\' => 5,
|
||||
'ConnectionManager\\Extra\\' => 24,
|
||||
'Clue\\Redis\\Protocol\\' => 20,
|
||||
'Clue\\React\\Utf8\\' => 16,
|
||||
'Clue\\React\\Term\\' => 16,
|
||||
'Clue\\React\\Stdio\\' => 17,
|
||||
|
@ -275,7 +276,7 @@ class ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c
|
|||
),
|
||||
'Doctrine\\Deprecations\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/doctrine/deprecations/lib/Doctrine/Deprecations',
|
||||
0 => __DIR__ . '/..' . '/doctrine/deprecations/src',
|
||||
),
|
||||
'Doctrine\\Common\\Collections\\' =>
|
||||
array (
|
||||
|
@ -289,6 +290,10 @@ class ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c
|
|||
array (
|
||||
0 => __DIR__ . '/..' . '/clue/connection-manager-extra/src',
|
||||
),
|
||||
'Clue\\Redis\\Protocol\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/clue/redis-protocol/src',
|
||||
),
|
||||
'Clue\\React\\Utf8\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/clue/utf8-react/src',
|
||||
|
@ -363,13 +368,6 @@ class ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c
|
|||
0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library',
|
||||
),
|
||||
),
|
||||
'C' =>
|
||||
array (
|
||||
'Clue\\Redis\\Protocol' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/clue/redis-protocol/src',
|
||||
),
|
||||
),
|
||||
'A' =>
|
||||
array (
|
||||
'AssetLoader' =>
|
||||
|
@ -395,10 +393,10 @@ class ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c
|
|||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c::$prefixesPsr0;
|
||||
$loader->classMap = ComposerStaticInit412d4c2afc15769a0fac36e82d8e412c::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit6063f1b04a2dad456eda2cdae82a650e::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit6063f1b04a2dad456eda2cdae82a650e::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInit6063f1b04a2dad456eda2cdae82a650e::$prefixesPsr0;
|
||||
$loader->classMap = ComposerStaticInit6063f1b04a2dad456eda2cdae82a650e::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// include_paths.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,301 +1,301 @@
|
|||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'icinga/icinga-php-thirdparty',
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => 'f70b33a8ab9ec60c6491b2467935c32b9f390116',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '04c233f4add8d6fcebc00186826c7b709bc26e19',
|
||||
'name' => 'icinga/icinga-php-thirdparty',
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'brick/math' => array(
|
||||
'pretty_version' => '0.9.3',
|
||||
'version' => '0.9.3.0',
|
||||
'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../brick/math',
|
||||
'aliases' => array(),
|
||||
'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/block-react' => array(
|
||||
'pretty_version' => 'v1.5.0',
|
||||
'version' => '1.5.0.0',
|
||||
'reference' => '718b0571a94aa693c6fffc72182e87257ac900f3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/block-react',
|
||||
'aliases' => array(),
|
||||
'reference' => '718b0571a94aa693c6fffc72182e87257ac900f3',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/connection-manager-extra' => array(
|
||||
'pretty_version' => 'v1.3.0',
|
||||
'version' => '1.3.0.0',
|
||||
'reference' => '6ddf7da4cd75bf5aa54be13eea7be9aad9e97ada',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/connection-manager-extra',
|
||||
'aliases' => array(),
|
||||
'reference' => '6ddf7da4cd75bf5aa54be13eea7be9aad9e97ada',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/http-proxy-react' => array(
|
||||
'pretty_version' => 'v1.8.0',
|
||||
'version' => '1.8.0.0',
|
||||
'reference' => '09366dd3e13b36b90f8e47a6acaf5a2c96b79fb5',
|
||||
'pretty_version' => 'v1.9.0',
|
||||
'version' => '1.9.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/http-proxy-react',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f3b02835273036a9370ac1c144b55df8e2b98430',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/mq-react' => array(
|
||||
'pretty_version' => 'v1.6.0',
|
||||
'version' => '1.6.0.0',
|
||||
'reference' => 'cab0147723017bc2deb3f248c607ad8e3c87e509',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/mq-react',
|
||||
'aliases' => array(),
|
||||
'reference' => 'cab0147723017bc2deb3f248c607ad8e3c87e509',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/redis-protocol' => array(
|
||||
'pretty_version' => 'v0.3.1',
|
||||
'version' => '0.3.1.0',
|
||||
'reference' => '271b8009887209d930f613ad3b9518f94bd6b51c',
|
||||
'pretty_version' => 'v0.3.2',
|
||||
'version' => '0.3.2.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/redis-protocol',
|
||||
'aliases' => array(),
|
||||
'reference' => '6f565332f5531b7722d1e9c445314b91862f6d6c',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/redis-react' => array(
|
||||
'pretty_version' => 'v2.6.0',
|
||||
'version' => '2.6.0.0',
|
||||
'reference' => 'f911455f9d7a77dd6f39c22548ddff521544b291',
|
||||
'pretty_version' => 'v2.8.0',
|
||||
'version' => '2.8.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/redis-react',
|
||||
'aliases' => array(),
|
||||
'reference' => '84569198dfd5564977d2ae6a32de4beb5a24bdca',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/soap-react' => array(
|
||||
'pretty_version' => 'v2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'reference' => 'db2e0ba9b0380ac6c4a34df3f1021d2191d45d45',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/soap-react',
|
||||
'aliases' => array(),
|
||||
'reference' => 'db2e0ba9b0380ac6c4a34df3f1021d2191d45d45',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/socket-raw' => array(
|
||||
'pretty_version' => 'v1.6.0',
|
||||
'version' => '1.6.0.0',
|
||||
'reference' => '91e9f619f6769f931454a9882c21ffd7623d06cb',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/socket-raw',
|
||||
'aliases' => array(),
|
||||
'reference' => '91e9f619f6769f931454a9882c21ffd7623d06cb',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/socks-react' => array(
|
||||
'pretty_version' => 'v1.4.0',
|
||||
'version' => '1.4.0.0',
|
||||
'reference' => 'eb3bd2ca5f43fea4b3bc4ef055179e0e6714730d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/socks-react',
|
||||
'aliases' => array(),
|
||||
'reference' => 'eb3bd2ca5f43fea4b3bc4ef055179e0e6714730d',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/stdio-react' => array(
|
||||
'pretty_version' => 'v2.6.0',
|
||||
'version' => '2.6.0.0',
|
||||
'reference' => 'dfa6c378aabdff718202d4e2453f752c38ea3399',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/stdio-react',
|
||||
'aliases' => array(),
|
||||
'reference' => 'dfa6c378aabdff718202d4e2453f752c38ea3399',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/term-react' => array(
|
||||
'pretty_version' => 'v1.3.0',
|
||||
'version' => '1.3.0.0',
|
||||
'reference' => 'eb6eb063eda04a714ef89f066586a2c49588f7ca',
|
||||
'pretty_version' => 'v1.4.0',
|
||||
'version' => '1.4.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/term-react',
|
||||
'aliases' => array(),
|
||||
'reference' => '00f297dc597eaee2ebf98af8f27cca5d21d60fa3',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'clue/utf8-react' => array(
|
||||
'pretty_version' => 'v1.2.0',
|
||||
'version' => '1.2.0.0',
|
||||
'reference' => '8bc3f8c874cdf642c8f10f9ae93aadb8cd63da96',
|
||||
'pretty_version' => 'v1.3.0',
|
||||
'version' => '1.3.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../clue/utf8-react',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd5cd04d39cb5457aa5df830b7c4b301d2694217e',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'components/jquery' => array(
|
||||
'pretty_version' => '3.6.0',
|
||||
'version' => '3.6.0.0',
|
||||
'reference' => '6cf38ee1fd04b6adf8e7dda161283aa35be818c3',
|
||||
'type' => 'component',
|
||||
'install_path' => __DIR__ . '/../components/jquery',
|
||||
'aliases' => array(),
|
||||
'reference' => '6cf38ee1fd04b6adf8e7dda161283aa35be818c3',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'cweagans/composer-patches' => array(
|
||||
'pretty_version' => '1.7.3',
|
||||
'version' => '1.7.3.0',
|
||||
'reference' => 'e190d4466fe2b103a55467dfa83fc2fecfcaf2db',
|
||||
'type' => 'composer-plugin',
|
||||
'install_path' => __DIR__ . '/../cweagans/composer-patches',
|
||||
'aliases' => array(),
|
||||
'reference' => 'e190d4466fe2b103a55467dfa83fc2fecfcaf2db',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'doctrine/collections' => array(
|
||||
'pretty_version' => '1.8.0',
|
||||
'version' => '1.8.0.0',
|
||||
'reference' => '2b44dd4cbca8b5744327de78bafef5945c7e7b5e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../doctrine/collections',
|
||||
'aliases' => array(),
|
||||
'reference' => '2b44dd4cbca8b5744327de78bafef5945c7e7b5e',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'doctrine/deprecations' => array(
|
||||
'pretty_version' => '1.1.2',
|
||||
'version' => '1.1.2.0',
|
||||
'reference' => '4f2d4f2836e7ec4e7a8625e75c6aa916004db931',
|
||||
'pretty_version' => '1.1.4',
|
||||
'version' => '1.1.4.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../doctrine/deprecations',
|
||||
'aliases' => array(),
|
||||
'reference' => '31610dbb31faa98e6b5447b62340826f54fbc4e9',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'dompdf/dompdf' => array(
|
||||
'pretty_version' => 'v2.0.3',
|
||||
'version' => '2.0.3.0',
|
||||
'reference' => 'e8d2d5e37e8b0b30f0732a011295ab80680d7e85',
|
||||
'pretty_version' => 'v2.0.8',
|
||||
'version' => '2.0.8.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../dompdf/dompdf',
|
||||
'aliases' => array(),
|
||||
'reference' => 'c20247574601700e1f7c8dab39310fca1964dc52',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'dragonmantank/cron-expression' => array(
|
||||
'pretty_version' => 'v3.3.3',
|
||||
'version' => '3.3.3.0',
|
||||
'reference' => 'adfb1f505deb6384dc8b39804c5065dd3c8c8c0a',
|
||||
'pretty_version' => 'v3.4.0',
|
||||
'version' => '3.4.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../dragonmantank/cron-expression',
|
||||
'aliases' => array(),
|
||||
'reference' => '8c784d071debd117328803d86b2097615b457500',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'erusev/parsedown' => array(
|
||||
'pretty_version' => '1.7.4',
|
||||
'version' => '1.7.4.0',
|
||||
'reference' => 'cb17b6477dfff935958ba01325f2e8a2bfa6dab3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../erusev/parsedown',
|
||||
'aliases' => array(),
|
||||
'reference' => 'cb17b6477dfff935958ba01325f2e8a2bfa6dab3',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'evenement/evenement' => array(
|
||||
'pretty_version' => 'v3.0.2',
|
||||
'version' => '3.0.2.0',
|
||||
'reference' => '0a16b0d71ab13284339abb99d9d2bd813640efbc',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../evenement/evenement',
|
||||
'aliases' => array(),
|
||||
'reference' => '0a16b0d71ab13284339abb99d9d2bd813640efbc',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'ezyang/htmlpurifier' => array(
|
||||
'pretty_version' => 'v4.17.0',
|
||||
'version' => '4.17.0.0',
|
||||
'reference' => 'bbc513d79acf6691fa9cf10f192c90dd2957f18c',
|
||||
'pretty_version' => 'v4.18.0',
|
||||
'version' => '4.18.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../ezyang/htmlpurifier',
|
||||
'aliases' => array(),
|
||||
'reference' => 'cb56001e54359df7ae76dc522d08845dc741621b',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'fig/http-message-util' => array(
|
||||
'pretty_version' => '1.1.5',
|
||||
'version' => '1.1.5.0',
|
||||
'reference' => '9d94dc0154230ac39e5bf89398b324a86f63f765',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../fig/http-message-util',
|
||||
'aliases' => array(),
|
||||
'reference' => '9d94dc0154230ac39e5bf89398b324a86f63f765',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'guzzlehttp/guzzle' => array(
|
||||
'pretty_version' => '7.8.0',
|
||||
'version' => '7.8.0.0',
|
||||
'reference' => '1110f66a6530a40fe7aea0378fe608ee2b2248f9',
|
||||
'pretty_version' => '7.9.2',
|
||||
'version' => '7.9.2.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd281ed313b989f213357e3be1a179f02196ac99b',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'guzzlehttp/promises' => array(
|
||||
'pretty_version' => '2.0.1',
|
||||
'version' => '2.0.1.0',
|
||||
'reference' => '111166291a0f8130081195ac4556a5587d7f1b5d',
|
||||
'pretty_version' => '2.0.4',
|
||||
'version' => '2.0.4.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../guzzlehttp/promises',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f9c436286ab2892c7db7be8c8da4ef61ccf7b455',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'guzzlehttp/psr7' => array(
|
||||
'pretty_version' => '2.6.1',
|
||||
'version' => '2.6.1.0',
|
||||
'reference' => 'be45764272e8873c72dbe3d2edcfdfcc3bc9f727',
|
||||
'pretty_version' => '2.7.0',
|
||||
'version' => '2.7.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../guzzlehttp/psr7',
|
||||
'aliases' => array(),
|
||||
'reference' => 'a70f5c95fb43bc83f07c9c948baa0dc1829bf201',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'icinga/icinga-php-thirdparty' => array(
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => 'f70b33a8ab9ec60c6491b2467935c32b9f390116',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '04c233f4add8d6fcebc00186826c7b709bc26e19',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jfcherng/php-color-output' => array(
|
||||
'pretty_version' => '2.0.2',
|
||||
'version' => '2.0.2.0',
|
||||
'reference' => '2673074597eca9682d2fdfaee39a22418d4cc2f6',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jfcherng/php-color-output',
|
||||
'aliases' => array(),
|
||||
'reference' => '2673074597eca9682d2fdfaee39a22418d4cc2f6',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jfcherng/php-diff' => array(
|
||||
'pretty_version' => '6.10.14',
|
||||
'version' => '6.10.14.0',
|
||||
'reference' => '38b6e816badaa97f75541484d6c3d7c3e5dbca78',
|
||||
'pretty_version' => '6.10.17',
|
||||
'version' => '6.10.17.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jfcherng/php-diff',
|
||||
'aliases' => array(),
|
||||
'reference' => '72f551e6200831dc5a7015d28af285649baee817',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jfcherng/php-mb-string' => array(
|
||||
'pretty_version' => '1.4.8',
|
||||
'version' => '1.4.8.0',
|
||||
'reference' => 'ef8926ff849863bfea234e99ee827947bedd86b0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jfcherng/php-mb-string',
|
||||
'aliases' => array(),
|
||||
'reference' => 'ef8926ff849863bfea234e99ee827947bedd86b0',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jfcherng/php-sequence-matcher' => array(
|
||||
'pretty_version' => '3.2.10',
|
||||
'version' => '3.2.10.0',
|
||||
'reference' => '650164598be2c6ad6891dbd41de4cb5cc21cc91b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jfcherng/php-sequence-matcher',
|
||||
'aliases' => array(),
|
||||
'reference' => '650164598be2c6ad6891dbd41de4cb5cc21cc91b',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'masterminds/html5' => array(
|
||||
'pretty_version' => '2.8.1',
|
||||
'version' => '2.8.1.0',
|
||||
'reference' => 'f47dcf3c70c584de14f21143c55d9939631bc6cf',
|
||||
'pretty_version' => '2.9.0',
|
||||
'version' => '2.9.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../masterminds/html5',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f5ac2c0b0a2eefca70b2ce32a5809992227e75a6',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'mtdowling/cron-expression' => array(
|
||||
|
@ -305,39 +305,39 @@
|
|||
),
|
||||
),
|
||||
'phenx/php-font-lib' => array(
|
||||
'pretty_version' => '0.5.4',
|
||||
'version' => '0.5.4.0',
|
||||
'reference' => 'dd448ad1ce34c63d09baccd05415e361300c35b4',
|
||||
'pretty_version' => '0.5.6',
|
||||
'version' => '0.5.6.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phenx/php-font-lib',
|
||||
'aliases' => array(),
|
||||
'reference' => 'a1681e9793040740a405ac5b189275059e2a9863',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phenx/php-svg-lib' => array(
|
||||
'pretty_version' => '0.5.0',
|
||||
'version' => '0.5.0.0',
|
||||
'reference' => '76876c6cf3080bcb6f249d7d59705108166a6685',
|
||||
'pretty_version' => '0.5.4',
|
||||
'version' => '0.5.4.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phenx/php-svg-lib',
|
||||
'aliases' => array(),
|
||||
'reference' => '46b25da81613a9cf43c83b2a8c2c1bdab27df691',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'predis/predis' => array(
|
||||
'pretty_version' => 'v2.2.2',
|
||||
'version' => '2.2.2.0',
|
||||
'reference' => 'b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1',
|
||||
'pretty_version' => 'v2.3.0',
|
||||
'version' => '2.3.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../predis/predis',
|
||||
'aliases' => array(),
|
||||
'reference' => 'bac46bfdb78cd6e9c7926c697012aae740cb9ec9',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-client' => array(
|
||||
'pretty_version' => '1.0.3',
|
||||
'version' => '1.0.3.0',
|
||||
'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-client',
|
||||
'aliases' => array(),
|
||||
'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-client-implementation' => array(
|
||||
|
@ -347,12 +347,12 @@
|
|||
),
|
||||
),
|
||||
'psr/http-factory' => array(
|
||||
'pretty_version' => '1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
|
||||
'pretty_version' => '1.1.0',
|
||||
'version' => '1.1.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-factory',
|
||||
'aliases' => array(),
|
||||
'reference' => '2b4765fddfe3b508ac62f829e852b1501d3f6e8a',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-factory-implementation' => array(
|
||||
|
@ -364,10 +364,10 @@
|
|||
'psr/http-message' => array(
|
||||
'pretty_version' => '1.1',
|
||||
'version' => '1.1.0.0',
|
||||
'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-message',
|
||||
'aliases' => array(),
|
||||
'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-message-implementation' => array(
|
||||
|
@ -379,136 +379,136 @@
|
|||
'psr/log' => array(
|
||||
'pretty_version' => '1.1.4',
|
||||
'version' => '1.1.4.0',
|
||||
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/log',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'ralouphie/getallheaders' => array(
|
||||
'pretty_version' => '3.0.3',
|
||||
'version' => '3.0.3.0',
|
||||
'reference' => '120b605dfeb996808c31b6477290a714d356e822',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../ralouphie/getallheaders',
|
||||
'aliases' => array(),
|
||||
'reference' => '120b605dfeb996808c31b6477290a714d356e822',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'ramsey/collection' => array(
|
||||
'pretty_version' => '1.1.4',
|
||||
'version' => '1.1.4.0',
|
||||
'reference' => 'ab2237657ad99667a5143e32ba2683c8029563d4',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../ramsey/collection',
|
||||
'aliases' => array(),
|
||||
'reference' => 'ab2237657ad99667a5143e32ba2683c8029563d4',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'ramsey/uuid' => array(
|
||||
'pretty_version' => '4.2.3',
|
||||
'version' => '4.2.3.0',
|
||||
'reference' => 'fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../ramsey/uuid',
|
||||
'aliases' => array(),
|
||||
'reference' => 'fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/cache' => array(
|
||||
'pretty_version' => 'v1.2.0',
|
||||
'version' => '1.2.0.0',
|
||||
'reference' => 'd47c472b64aa5608225f47965a484b75c7817d5b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/cache',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd47c472b64aa5608225f47965a484b75c7817d5b',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/child-process' => array(
|
||||
'pretty_version' => 'v0.6.5',
|
||||
'version' => '0.6.5.0',
|
||||
'reference' => 'e71eb1aa55f057c7a4a0d08d06b0b0a484bead43',
|
||||
'pretty_version' => 'v0.6.6',
|
||||
'version' => '0.6.6.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/child-process',
|
||||
'aliases' => array(),
|
||||
'reference' => '1721e2b93d89b745664353b9cfc8f155ba8a6159',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/datagram' => array(
|
||||
'pretty_version' => 'v1.9.0',
|
||||
'version' => '1.9.0.0',
|
||||
'reference' => '13c259bb2fd04f238eeb85f3783167eedec46e2c',
|
||||
'pretty_version' => 'v1.10.0',
|
||||
'version' => '1.10.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/datagram',
|
||||
'aliases' => array(),
|
||||
'reference' => '9236e1f5a67a6029be17d551e9858c487836c301',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/dns' => array(
|
||||
'pretty_version' => 'v1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'reference' => '3be0fc8f1eb37d6875cd6f0c6c7d0be81435de9f',
|
||||
'pretty_version' => 'v1.13.0',
|
||||
'version' => '1.13.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/dns',
|
||||
'aliases' => array(),
|
||||
'reference' => 'eb8ae001b5a455665c89c1df97f6fb682f8fb0f5',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/event-loop' => array(
|
||||
'pretty_version' => 'v1.5.0',
|
||||
'version' => '1.5.0.0',
|
||||
'reference' => 'bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/event-loop',
|
||||
'aliases' => array(),
|
||||
'reference' => 'bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/http' => array(
|
||||
'pretty_version' => 'v1.9.0',
|
||||
'version' => '1.9.0.0',
|
||||
'reference' => 'bb3154dbaf2dfe3f0467f956a05f614a69d5f1d0',
|
||||
'pretty_version' => 'v1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/http',
|
||||
'aliases' => array(),
|
||||
'reference' => '8db02de41dcca82037367f67a2d4be365b1c4db9',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/promise' => array(
|
||||
'pretty_version' => 'v2.11.0',
|
||||
'version' => '2.11.0.0',
|
||||
'reference' => '1a8460931ea36dc5c76838fec5734d55c88c6831',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/promise',
|
||||
'aliases' => array(),
|
||||
'reference' => '1a8460931ea36dc5c76838fec5734d55c88c6831',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/promise-stream' => array(
|
||||
'pretty_version' => 'v1.6.0',
|
||||
'version' => '1.6.0.0',
|
||||
'reference' => '87d1399a33926fd5ba28a7647346b71482787502',
|
||||
'pretty_version' => 'v1.7.0',
|
||||
'version' => '1.7.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/promise-stream',
|
||||
'aliases' => array(),
|
||||
'reference' => '5c7ec3450f558deb779742e33967d837e2db7871',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/promise-timer' => array(
|
||||
'pretty_version' => 'v1.10.0',
|
||||
'version' => '1.10.0.0',
|
||||
'reference' => '4cb85c1c2125390748e3908120bb82feb99fe766',
|
||||
'pretty_version' => 'v1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/promise-timer',
|
||||
'aliases' => array(),
|
||||
'reference' => '4f70306ed66b8b44768941ca7f142092600fafc1',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/socket' => array(
|
||||
'pretty_version' => 'v1.14.0',
|
||||
'version' => '1.14.0.0',
|
||||
'reference' => '21591111d3ea62e31f2254280ca0656bc2b1bda6',
|
||||
'pretty_version' => 'v1.16.0',
|
||||
'version' => '1.16.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/socket',
|
||||
'aliases' => array(),
|
||||
'reference' => '23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'react/stream' => array(
|
||||
'pretty_version' => 'v1.3.0',
|
||||
'version' => '1.3.0.0',
|
||||
'reference' => '6fbc9672905c7d5a885f2da2fc696f65840f4a66',
|
||||
'pretty_version' => 'v1.4.0',
|
||||
'version' => '1.4.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../react/stream',
|
||||
'aliases' => array(),
|
||||
'reference' => '1e5b0acb8fe55143b5b426817155190eb6f5b18d',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'rhumsaa/uuid' => array(
|
||||
|
@ -520,109 +520,109 @@
|
|||
'ringcentral/psr7' => array(
|
||||
'pretty_version' => '1.3.0',
|
||||
'version' => '1.3.0.0',
|
||||
'reference' => '360faaec4b563958b673fb52bbe94e37f14bc686',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../ringcentral/psr7',
|
||||
'aliases' => array(),
|
||||
'reference' => '360faaec4b563958b673fb52bbe94e37f14bc686',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'sabberworm/php-css-parser' => array(
|
||||
'pretty_version' => '8.4.0',
|
||||
'version' => '8.4.0.0',
|
||||
'reference' => 'e41d2140031d533348b2192a83f02d8dd8a71d30',
|
||||
'pretty_version' => 'v8.7.0',
|
||||
'version' => '8.7.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sabberworm/php-css-parser',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f414ff953002a9b18e3a116f5e462c56f21237cf',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'shardj/zf1-future' => array(
|
||||
'pretty_version' => '1.23.5',
|
||||
'version' => '1.23.5.0',
|
||||
'reference' => '0464ee916ca73142ab733d80c83210d89cba3936',
|
||||
'pretty_version' => '1.24.2',
|
||||
'version' => '1.24.2.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../shardj/zf1-future',
|
||||
'aliases' => array(),
|
||||
'reference' => '68d83e18c01950547ddf26700a8a99abeb98e936',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'simshaun/recurr' => array(
|
||||
'pretty_version' => 'v5.0.2',
|
||||
'version' => '5.0.2.0',
|
||||
'reference' => '1aff62e6e0ee875b3f2487352542605123ee9172',
|
||||
'pretty_version' => 'v5.0.3',
|
||||
'version' => '5.0.3.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../simshaun/recurr',
|
||||
'aliases' => array(),
|
||||
'reference' => '7b136768d64f257065e38a804ee6d2f9af6ba6d1',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/deprecation-contracts' => array(
|
||||
'pretty_version' => 'v2.5.2',
|
||||
'version' => '2.5.2.0',
|
||||
'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
|
||||
'pretty_version' => 'v2.5.4',
|
||||
'version' => '2.5.4.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
||||
'aliases' => array(),
|
||||
'reference' => '605389f2a7e5625f273b53960dc46aeaf9c62918',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-ctype' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => 'ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb',
|
||||
'pretty_version' => 'v1.31.0',
|
||||
'version' => '1.31.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
|
||||
'aliases' => array(),
|
||||
'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '42292d99c55abe617799667f454222c54c60e229',
|
||||
'pretty_version' => 'v1.31.0',
|
||||
'version' => '1.31.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'reference' => '85181ba99b2345b0ef10ce42ecac37612d9fd341',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php80' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '6caa57379c4aec19c0a12a38b59b26487dcfe4b5',
|
||||
'pretty_version' => 'v1.31.0',
|
||||
'version' => '1.31.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||
'aliases' => array(),
|
||||
'reference' => '60328e362d4c2c802a54fcbf04f9d3fb892b4cf8',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php81' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '7581cd600fa9fd681b797d00b02f068e2f13263b',
|
||||
'pretty_version' => 'v1.31.0',
|
||||
'version' => '1.31.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php81',
|
||||
'aliases' => array(),
|
||||
'reference' => '4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'tedivm/jshrink' => array(
|
||||
'pretty_version' => 'v1.7.0',
|
||||
'version' => '1.7.0.0',
|
||||
'reference' => '7a35f5a4651ca2ce77295eb8a3b4e133ba47e19e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../tedivm/jshrink',
|
||||
'aliases' => array(),
|
||||
'reference' => '7a35f5a4651ca2ce77295eb8a3b4e133ba47e19e',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'webmozart/assert' => array(
|
||||
'pretty_version' => '1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../webmozart/assert',
|
||||
'aliases' => array(),
|
||||
'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'wikimedia/less.php' => array(
|
||||
'pretty_version' => 'v3.2.1',
|
||||
'version' => '3.2.1.0',
|
||||
'reference' => '0d5b30ba792bdbf8991a646fc9c30561b38a5559',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../wikimedia/less.php',
|
||||
'aliases' => array(),
|
||||
'reference' => '0d5b30ba792bdbf8991a646fc9c30561b38a5559',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'zendframework/zendframework1' => array(
|
||||
|
|
|
@ -150,6 +150,67 @@ class MyTest extends TestCase
|
|||
}
|
||||
```
|
||||
|
||||
## Displaying deprecations after running a PHPUnit test suite
|
||||
|
||||
It is possible to integrate this library with PHPUnit to display all
|
||||
deprecations triggered during the test suite execution.
|
||||
|
||||
```xml
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
failOnDeprecation="true"
|
||||
>
|
||||
<!-- one attribute to display the deprecations, the other to fail the test suite -->
|
||||
|
||||
<php>
|
||||
<!-- ensures native PHP deprecations are used -->
|
||||
<server name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<!-- ensures the @ operator in @trigger_error is ignored -->
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
```
|
||||
|
||||
Note that you can still trigger Deprecations in your code, provided you use the
|
||||
`#[WithoutErrorHandler]` attribute to disable PHPUnit's error handler for tests
|
||||
that call it. Be wary that this will disable all error handling, meaning it
|
||||
will mask any warnings or errors that would otherwise be caught by PHPUnit.
|
||||
|
||||
At the moment, it is not possible to disable deduplication with an environment
|
||||
variable, but you can use a bootstrap file to achieve that:
|
||||
|
||||
```php
|
||||
// tests/bootstrap.php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
Deprecation::withoutDeduplication();
|
||||
```
|
||||
|
||||
Then, reference that file in your PHPUnit configuration:
|
||||
|
||||
```xml
|
||||
<phpunit …
|
||||
bootstrap="tests/bootstrap.php"
|
||||
…
|
||||
>
|
||||
…
|
||||
</phpunit>
|
||||
```
|
||||
|
||||
## What is a deprecation identifier?
|
||||
|
||||
An identifier for deprecations is just a link to any resource, most often a
|
||||
|
|
|
@ -8,20 +8,18 @@
|
|||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9",
|
||||
"phpstan/phpstan": "1.4.10 || 1.10.15",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"doctrine/coding-standard": "^9 || ^12",
|
||||
"phpstan/phpstan": "1.4.10 || 2.0.3",
|
||||
"phpstan/phpstan-phpunit": "^1.0 || ^2",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"psalm/plugin-phpunit": "0.18.4",
|
||||
"psr/log": "^1 || ^2 || ^3",
|
||||
"vimeo/psalm": "4.30.0 || 5.12.0"
|
||||
"psr/log": "^1 || ^2 || ^3"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations"
|
||||
"Doctrine\\Deprecations\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
|
|
@ -173,9 +173,7 @@ class Deprecation
|
|||
self::delegateTriggerToBackend($message, $backtrace, $link, $package);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array{function: string, line?: int, file?: string, class?: class-string, type?: string, args?: mixed[], object?: object}> $backtrace
|
||||
*/
|
||||
/** @param list<array{function: string, line?: int, file?: string, class?: class-string, type?: string, args?: mixed[], object?: object}> $backtrace */
|
||||
private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package): void
|
||||
{
|
||||
$type = self::$type ?? self::getTypeFromEnv();
|
||||
|
@ -226,19 +224,19 @@ class Deprecation
|
|||
|
||||
public static function enableTrackingDeprecations(): void
|
||||
{
|
||||
self::$type = self::$type ?? 0;
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_TRACK_DEPRECATIONS;
|
||||
}
|
||||
|
||||
public static function enableWithTriggerError(): void
|
||||
{
|
||||
self::$type = self::$type ?? 0;
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_TRIGGER_ERROR;
|
||||
}
|
||||
|
||||
public static function enableWithPsrLogger(LoggerInterface $logger): void
|
||||
{
|
||||
self::$type = self::$type ?? 0;
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_PSR_LOGGER;
|
||||
self::$logger = $logger;
|
||||
}
|
||||
|
@ -289,9 +287,7 @@ class Deprecation
|
|||
return self::$triggeredDeprecations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int-mask-of<self::TYPE_*>
|
||||
*/
|
||||
/** @return int-mask-of<self::TYPE_*> */
|
||||
private static function getTypeFromEnv(): int
|
||||
{
|
||||
switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) {
|
|
@ -26,17 +26,13 @@ trait VerifyDeprecations
|
|||
$this->doctrineNoDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @before
|
||||
*/
|
||||
/** @before */
|
||||
public function enableDeprecationTracking(): void
|
||||
{
|
||||
Deprecation::enableTrackingDeprecations();
|
||||
}
|
||||
|
||||
/**
|
||||
* @after
|
||||
*/
|
||||
/** @after */
|
||||
public function verifyDeprecationsAreTriggered(): void
|
||||
{
|
||||
foreach ($this->doctrineDeprecationsExpectations as $identifier => $expectation) {
|
|
@ -1 +1 @@
|
|||
2.0.3
|
||||
2.0.8
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
"ext-mbstring": "*",
|
||||
"masterminds/html5": "^2.0",
|
||||
"phenx/php-font-lib": ">=0.5.4 <1.0.0",
|
||||
"phenx/php-svg-lib": ">=0.3.3 <1.0.0"
|
||||
"phenx/php-svg-lib": ">=0.5.2 <1.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-json": "*",
|
||||
|
|
|
@ -467,12 +467,17 @@ class GD implements Canvas
|
|||
imagesetthickness($this->get_image(), $width);
|
||||
|
||||
if ($c === IMG_COLOR_STYLED) {
|
||||
imagepolygon($this->get_image(), [
|
||||
$points = [
|
||||
$x1, $y1,
|
||||
$x1 + $w, $y1,
|
||||
$x1 + $w, $y1 + $h,
|
||||
$x1, $y1 + $h
|
||||
], $c);
|
||||
];
|
||||
if (version_compare(PHP_VERSION, "8.1.0", "<")) {
|
||||
imagepolygon($this->get_image(), $points, count($points)/2, $c);
|
||||
} else {
|
||||
imagepolygon($this->get_image(), $points, $c);
|
||||
}
|
||||
} else {
|
||||
imagerectangle($this->get_image(), $x1, $y1, $x1 + $w, $y1 + $h, $c);
|
||||
}
|
||||
|
@ -570,9 +575,17 @@ class GD implements Canvas
|
|||
imagesetthickness($this->get_image(), isset($width) ? $width : 0);
|
||||
|
||||
if ($fill) {
|
||||
imagefilledpolygon($this->get_image(), $points, $c);
|
||||
if (version_compare(PHP_VERSION, "8.1.0", "<")) {
|
||||
imagefilledpolygon($this->get_image(), $points, count($points)/2, $c);
|
||||
} else {
|
||||
imagefilledpolygon($this->get_image(), $points, $c);
|
||||
}
|
||||
} else {
|
||||
imagepolygon($this->get_image(), $points, $c);
|
||||
if (version_compare(PHP_VERSION, "8.1.0", "<")) {
|
||||
imagepolygon($this->get_image(), $points, count($points)/2, $c);
|
||||
} else {
|
||||
imagepolygon($this->get_image(), $points, $c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,14 @@ class Cache
|
|||
*/
|
||||
protected static $tempImages = [];
|
||||
|
||||
/**
|
||||
* Array of image references from an SVG document.
|
||||
* Used to detect circular references across SVG documents.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $svgRefs = [];
|
||||
|
||||
/**
|
||||
* The url to the "broken image" used when images can't be loaded
|
||||
*
|
||||
|
@ -134,20 +142,28 @@ class Cache
|
|||
$parser,
|
||||
function ($parser, $name, $attributes) use ($options, $parsed_url, $full_url) {
|
||||
if (strtolower($name) === "image") {
|
||||
if (!\array_key_exists($full_url, self::$svgRefs)) {
|
||||
self::$svgRefs[$full_url] = [];
|
||||
}
|
||||
$attributes = array_change_key_case($attributes, CASE_LOWER);
|
||||
$urls = [];
|
||||
$urls[] = $attributes["xlink:href"] ?? "";
|
||||
$urls[] = $attributes["href"] ?? "";
|
||||
foreach ($urls as $url) {
|
||||
if (!empty($url)) {
|
||||
$inner_full_url = Helpers::build_url($parsed_url["protocol"], $parsed_url["host"], $parsed_url["path"], $url);
|
||||
if ($inner_full_url === $full_url) {
|
||||
throw new ImageException("SVG self-reference is not allowed", E_WARNING);
|
||||
}
|
||||
[$resolved_url, $type, $message] = self::resolve_url($url, $parsed_url["protocol"], $parsed_url["host"], $parsed_url["path"], $options);
|
||||
if (!empty($message)) {
|
||||
throw new ImageException("This SVG document references a restricted resource. $message", E_WARNING);
|
||||
}
|
||||
if (empty($url)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$inner_full_url = Helpers::build_url($parsed_url["protocol"], $parsed_url["host"], $parsed_url["path"], $url);
|
||||
if (empty($inner_full_url)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
self::detectCircularRef($full_url, $inner_full_url);
|
||||
self::$svgRefs[$full_url][] = $inner_full_url;
|
||||
[$resolved_url, $type, $message] = self::resolve_url($url, $parsed_url["protocol"], $parsed_url["host"], $parsed_url["path"], $options);
|
||||
if (!empty($message)) {
|
||||
throw new ImageException("This SVG document references a restricted resource. $message", E_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +194,19 @@ class Cache
|
|||
return [$resolved_url, $type, $message];
|
||||
}
|
||||
|
||||
static function detectCircularRef(string $src, string $target)
|
||||
{
|
||||
if (!\array_key_exists($target, self::$svgRefs)) {
|
||||
return;
|
||||
}
|
||||
foreach (self::$svgRefs[$target] as $ref) {
|
||||
if ($ref === $src) {
|
||||
throw new ImageException("Circular external SVG image reference detected.", E_WARNING);
|
||||
}
|
||||
self::detectCircularRef($src, $ref);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a temp file for the given original image file.
|
||||
*
|
||||
|
@ -239,6 +268,7 @@ class Cache
|
|||
|
||||
self::$_cache = [];
|
||||
self::$tempImages = [];
|
||||
self::$svgRefs = [];
|
||||
}
|
||||
|
||||
static function detect_type($file, $context = null)
|
||||
|
|
|
@ -83,6 +83,13 @@ class Options
|
|||
"https://" => ["rules" => []]
|
||||
];
|
||||
|
||||
/**
|
||||
* Operational artifact (log files, temporary files) path validation
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
private $artifactPathValidation = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
@ -335,6 +342,8 @@ class Options
|
|||
|
||||
$this->setAllowedProtocols(["file://", "http://", "https://"]);
|
||||
|
||||
$this->setArtifactPathValidation([$this, "validateArtifactPath"]);
|
||||
|
||||
if (null !== $attributes) {
|
||||
$this->set($attributes);
|
||||
}
|
||||
|
@ -361,6 +370,8 @@ class Options
|
|||
$this->setChroot($value);
|
||||
} elseif ($key === 'allowedProtocols') {
|
||||
$this->setAllowedProtocols($value);
|
||||
} elseif ($key === 'artifactPathValidation') {
|
||||
$this->setArtifactPathValidation($value);
|
||||
} elseif ($key === 'logOutputFile' || $key === 'log_output_file') {
|
||||
$this->setLogOutputFile($value);
|
||||
} elseif ($key === 'defaultMediaType' || $key === 'default_media_type') {
|
||||
|
@ -428,6 +439,8 @@ class Options
|
|||
return $this->getChroot();
|
||||
} elseif ($key === 'allowedProtocols') {
|
||||
return $this->getAllowedProtocols();
|
||||
} elseif ($key === 'artifactPathValidation') {
|
||||
return $this->getArtifactPathValidation();
|
||||
} elseif ($key === 'logOutputFile' || $key === 'log_output_file') {
|
||||
return $this->getLogOutputFile();
|
||||
} elseif ($key === 'defaultMediaType' || $key === 'default_media_type') {
|
||||
|
@ -592,6 +605,24 @@ class Options
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getArtifactPathValidation()
|
||||
{
|
||||
return $this->artifactPathValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $validator
|
||||
* @return $this
|
||||
*/
|
||||
public function setArtifactPathValidation($validator)
|
||||
{
|
||||
$this->artifactPathValidation = $validator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
@ -848,7 +879,9 @@ class Options
|
|||
*/
|
||||
public function setFontCache($fontCache)
|
||||
{
|
||||
$this->fontCache = $fontCache;
|
||||
if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($fontCache, "fontCache") === true) {
|
||||
$this->fontCache = $fontCache;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -866,7 +899,9 @@ class Options
|
|||
*/
|
||||
public function setFontDir($fontDir)
|
||||
{
|
||||
$this->fontDir = $fontDir;
|
||||
if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($fontDir, "fontDir") === true) {
|
||||
$this->fontDir = $fontDir;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -1035,7 +1070,9 @@ class Options
|
|||
*/
|
||||
public function setLogOutputFile($logOutputFile)
|
||||
{
|
||||
$this->logOutputFile = $logOutputFile;
|
||||
if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($logOutputFile, "logOutputFile") === true) {
|
||||
$this->logOutputFile = $logOutputFile;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -1053,7 +1090,9 @@ class Options
|
|||
*/
|
||||
public function setTempDir($tempDir)
|
||||
{
|
||||
$this->tempDir = $tempDir;
|
||||
if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($tempDir, "tempDir") === true) {
|
||||
$this->tempDir = $tempDir;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -1071,7 +1110,9 @@ class Options
|
|||
*/
|
||||
public function setRootDir($rootDir)
|
||||
{
|
||||
$this->rootDir = $rootDir;
|
||||
if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($rootDir, "rootDir") === true) {
|
||||
$this->rootDir = $rootDir;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -1105,6 +1146,19 @@ class Options
|
|||
return $this->httpContext;
|
||||
}
|
||||
|
||||
|
||||
public function validateArtifactPath(?string $path, string $option)
|
||||
{
|
||||
if ($path === null) {
|
||||
return true;
|
||||
}
|
||||
$parsed_uri = parse_url($path);
|
||||
if ($parsed_uri === false || (array_key_exists("scheme", $parsed_uri) && strtolower($parsed_uri["scheme"]) === "phar")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validateLocalUri(string $uri)
|
||||
{
|
||||
if ($uri === null || strlen($uri) === 0) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
PHP Cron Expression Parser
|
||||
==========================
|
||||
|
||||
[![Latest Stable Version](https://poser.pugx.org/dragonmantank/cron-expression/v/stable.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Total Downloads](https://poser.pugx.org/dragonmantank/cron-expression/downloads.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Build Status](https://secure.travis-ci.org/dragonmantank/cron-expression.png)](http://travis-ci.org/dragonmantank/cron-expression) [![StyleCI](https://github.styleci.io/repos/103715337/shield?branch=master)](https://github.styleci.io/repos/103715337)
|
||||
[![Latest Stable Version](https://poser.pugx.org/dragonmantank/cron-expression/v/stable.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Total Downloads](https://poser.pugx.org/dragonmantank/cron-expression/downloads.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Tests](https://github.com/dragonmantank/cron-expression/actions/workflows/tests.yml/badge.svg)](https://github.com/dragonmantank/cron-expression/actions/workflows/tests.yml) [![StyleCI](https://github.styleci.io/repos/103715337/shield?branch=master)](https://github.styleci.io/repos/103715337)
|
||||
|
||||
The PHP cron expression parser can parse a CRON expression, determine if it is
|
||||
due to run, calculate the next run date of the expression, and calculate the previous
|
||||
|
@ -55,23 +55,65 @@ CRON Expressions
|
|||
|
||||
A CRON expression is a string representing the schedule for a particular command to execute. The parts of a CRON schedule are as follows:
|
||||
|
||||
* * * * *
|
||||
- - - - -
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | +----- day of week (0 - 7) (Sunday=0 or 7)
|
||||
| | | +---------- month (1 - 12)
|
||||
| | +--------------- day of month (1 - 31)
|
||||
| +-------------------- hour (0 - 23)
|
||||
+------------------------- min (0 - 59)
|
||||
```
|
||||
* * * * *
|
||||
- - - - -
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | +----- day of week (0-7) (Sunday = 0 or 7) (or SUN-SAT)
|
||||
| | | +--------- month (1-12) (or JAN-DEC)
|
||||
| | +------------- day of month (1-31)
|
||||
| +----------------- hour (0-23)
|
||||
+--------------------- minute (0-59)
|
||||
```
|
||||
|
||||
This library also supports a few macros:
|
||||
Each part of expression can also use wildcard, lists, ranges and steps:
|
||||
|
||||
* `@yearly`, `@annually` - Run once a year, midnight, Jan. 1 - `0 0 1 1 *`
|
||||
* `@monthly` - Run once a month, midnight, first of month - `0 0 1 * *`
|
||||
* `@weekly` - Run once a week, midnight on Sun - `0 0 * * 0`
|
||||
* `@daily`, `@midnight` - Run once a day, midnight - `0 0 * * *`
|
||||
* `@hourly` - Run once an hour, first minute - `0 * * * *`
|
||||
- wildcard - match always
|
||||
- `* * * * *` - At every minute.
|
||||
- day of week and day of month also support `?`, an alias to `*`
|
||||
- lists - match list of values, ranges and steps
|
||||
- e.g. `15,30 * * * *` - At minute 15 and 30.
|
||||
- ranges - match values in range
|
||||
- e.g. `1-9 * * * *` - At every minute from 1 through 9.
|
||||
- steps - match every nth value in range
|
||||
- e.g. `*/5 * * * *` - At every 5th minute.
|
||||
- e.g. `0-30/5 * * * *` - At every 5th minute from 0 through 30.
|
||||
- combinations
|
||||
- e.g. `0-14,30-44 * * * *` - At every minute from 0 through 14 and every minute from 30 through 44.
|
||||
|
||||
You can also use macro instead of an expression:
|
||||
|
||||
- `@yearly`, `@annually` - At 00:00 on 1st of January. (same as `0 0 1 1 *`)
|
||||
- `@monthly` - At 00:00 on day-of-month 1. (same as `0 0 1 * *`)
|
||||
- `@weekly` - At 00:00 on Sunday. (same as `0 0 * * 0`)
|
||||
- `@daily`, `@midnight` - At 00:00. (same as `0 0 * * *`)
|
||||
- `@hourly` - At minute 0. (same as `0 * * * *`)
|
||||
|
||||
Day of month extra features:
|
||||
|
||||
- nearest weekday - weekday (Monday-Friday) nearest to the given day
|
||||
- e.g. `* * 15W * *` - At every minute on a weekday nearest to the 15th.
|
||||
- If you were to specify `15W` as the value, the meaning is: "the nearest weekday to the 15th of the month"
|
||||
So if the 15th is a Saturday, the trigger will fire on Friday the 14th.
|
||||
If the 15th is a Sunday, the trigger will fire on Monday the 16th.
|
||||
If the 15th is a Tuesday, then it will fire on Tuesday the 15th.
|
||||
- However, if you specify `1W` as the value for day-of-month,
|
||||
and the 1st is a Saturday, the trigger will fire on Monday the 3rd,
|
||||
as it will not 'jump' over the boundary of a month's days.
|
||||
- last day of the month
|
||||
- e.g. `* * L * *` - At every minute on a last day-of-month.
|
||||
- last weekday of the month
|
||||
- e.g. `* * LW * *` - At every minute on a last weekday.
|
||||
|
||||
Day of week extra features:
|
||||
|
||||
- nth day
|
||||
- e.g. `* * * * 7#4` - At every minute on 4th Sunday.
|
||||
- 1-5
|
||||
- Every day of week repeats 4-5 times a month. To target the last one, use "last day" feature instead.
|
||||
- last day
|
||||
- e.g. `* * * * 7L` - At every minute on the last Sunday.
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
@ -85,3 +127,5 @@ Projects that Use cron-expression
|
|||
* Part of the [Laravel Framework](https://github.com/laravel/framework/)
|
||||
* Available as a [Symfony Bundle - setono/cron-expression-bundle](https://github.com/Setono/CronExpressionBundle)
|
||||
* Framework agnostic, PHP-based job scheduler - [Crunz](https://github.com/crunzphp/crunz)
|
||||
* Framework agnostic job scheduler - with locks, parallelism, per-second scheduling and more - [orisai/scheduler](https://github.com/orisai/scheduler)
|
||||
* Explain expression in English (and other languages) with [orisai/cron-expression-explainer](https://github.com/orisai/cron-expression-explainer)
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"phpunit/phpunit": "^7.0|^8.0|^9.0",
|
||||
"phpstan/phpstan-webmozart-assert": "^1.0",
|
||||
"phpstan/extension-installer": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -38,6 +37,11 @@
|
|||
"phpstan": "./vendor/bin/phpstan analyze",
|
||||
"test": "phpunit"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"ocramius/package-versions": true,
|
||||
|
|
|
@ -12,7 +12,6 @@ use Exception;
|
|||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use RuntimeException;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/**
|
||||
* CRON expression parser that can determine whether or not a CRON expression is
|
||||
|
@ -148,7 +147,7 @@ class CronExpression
|
|||
/**
|
||||
* @deprecated since version 3.0.2, use __construct instead.
|
||||
*/
|
||||
public static function factory(string $expression, FieldFactoryInterface $fieldFactory = null): CronExpression
|
||||
public static function factory(string $expression, ?FieldFactoryInterface $fieldFactory = null): CronExpression
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
return new static($expression, $fieldFactory);
|
||||
|
@ -179,7 +178,7 @@ class CronExpression
|
|||
* @param null|FieldFactoryInterface $fieldFactory Factory to create cron fields
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(string $expression, FieldFactoryInterface $fieldFactory = null)
|
||||
public function __construct(string $expression, ?FieldFactoryInterface $fieldFactory = null)
|
||||
{
|
||||
$shortcut = strtolower($expression);
|
||||
$expression = self::$registeredAliases[$shortcut] ?? $expression;
|
||||
|
@ -200,7 +199,12 @@ class CronExpression
|
|||
public function setExpression(string $value): CronExpression
|
||||
{
|
||||
$split = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY);
|
||||
Assert::isArray($split);
|
||||
|
||||
if (!\is_array($split)) {
|
||||
throw new InvalidArgumentException(
|
||||
$value . ' is not a valid CRON expression'
|
||||
);
|
||||
}
|
||||
|
||||
$notEnoughParts = \count($split) < 5;
|
||||
|
||||
|
@ -334,7 +338,10 @@ class CronExpression
|
|||
$currentTime = new DateTime($currentTime);
|
||||
}
|
||||
|
||||
Assert::isInstanceOf($currentTime, DateTime::class);
|
||||
if (!$currentTime instanceof DateTime) {
|
||||
throw new InvalidArgumentException('invalid current time');
|
||||
}
|
||||
|
||||
$currentTime->setTimezone(new DateTimeZone($timeZone));
|
||||
|
||||
$matches = [];
|
||||
|
@ -420,7 +427,10 @@ class CronExpression
|
|||
$currentTime = new DateTime($currentTime);
|
||||
}
|
||||
|
||||
Assert::isInstanceOf($currentTime, DateTime::class);
|
||||
if (!$currentTime instanceof DateTime) {
|
||||
throw new InvalidArgumentException('invalid current time');
|
||||
}
|
||||
|
||||
$currentTime->setTimezone(new DateTimeZone($timeZone));
|
||||
|
||||
// drop the seconds to 0
|
||||
|
@ -462,7 +472,10 @@ class CronExpression
|
|||
$currentDate = new DateTime('now');
|
||||
}
|
||||
|
||||
Assert::isInstanceOf($currentDate, DateTime::class);
|
||||
if (!$currentDate instanceof DateTime) {
|
||||
throw new InvalidArgumentException('invalid current date');
|
||||
}
|
||||
|
||||
$currentDate->setTimezone(new DateTimeZone($timeZone));
|
||||
// Workaround for setTime causing an offset change: https://bugs.php.net/bug.php?id=81074
|
||||
$currentDate = DateTime::createFromFormat("!Y-m-d H:iO", $currentDate->format("Y-m-d H:iP"), $currentDate->getTimezone());
|
||||
|
|
|
@ -1 +1 @@
|
|||
4.17.0
|
||||
4.18.0
|
|
@ -13,7 +13,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0"
|
||||
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"cerdic/css-tidy": "^1.7 || ^2.0",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
|
||||
* FILE, changes will be overwritten the next time the script is run.
|
||||
*
|
||||
* @version 4.17.0
|
||||
* @version 4.18.0
|
||||
*
|
||||
* @warning
|
||||
* You must *not* include any other HTML Purifier files before this file,
|
||||
|
@ -101,6 +101,7 @@ require 'HTMLPurifier/AttrDef/CSS/Length.php';
|
|||
require 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Ratio.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/URI.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
HTML Purifier 4.17.0 - Standards Compliant HTML Filtering
|
||||
HTML Purifier 4.18.0 - Standards Compliant HTML Filtering
|
||||
Copyright (C) 2006-2008 Edward Z. Yang
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
|
@ -58,12 +58,12 @@ class HTMLPurifier
|
|||
* Version of HTML Purifier.
|
||||
* @type string
|
||||
*/
|
||||
public $version = '4.17.0';
|
||||
public $version = '4.18.0';
|
||||
|
||||
/**
|
||||
* Constant with version of HTML Purifier.
|
||||
*/
|
||||
const VERSION = '4.17.0';
|
||||
const VERSION = '4.18.0';
|
||||
|
||||
/**
|
||||
* Global configuration object.
|
||||
|
|
|
@ -95,6 +95,7 @@ require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php';
|
|||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Ratio.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||
|
|
|
@ -27,6 +27,13 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
|||
$definition = $config->getCSSDefinition();
|
||||
$allow_duplicates = $config->get("CSS.AllowDuplicates");
|
||||
|
||||
$universal_attrdef = new HTMLPurifier_AttrDef_Enum(
|
||||
array(
|
||||
'initial',
|
||||
'inherit',
|
||||
'unset',
|
||||
)
|
||||
);
|
||||
|
||||
// According to the CSS2.1 spec, the places where a
|
||||
// non-delimiting semicolon can appear are in strings
|
||||
|
@ -96,16 +103,13 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
|||
if (!$ok) {
|
||||
continue;
|
||||
}
|
||||
// inefficient call, since the validator will do this again
|
||||
if (strtolower(trim($value)) !== 'inherit') {
|
||||
// inherit works for everything (but only on the base property)
|
||||
$result = $universal_attrdef->validate($value, $config, $context);
|
||||
if ($result === false) {
|
||||
$result = $definition->info[$property]->validate(
|
||||
$value,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
} else {
|
||||
$result = 'inherit';
|
||||
}
|
||||
if ($result === false) {
|
||||
continue;
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Validates a ratio as defined by the CSS spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Ratio extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* @param string $ratio Ratio to validate
|
||||
* @param HTMLPurifier_Config $config Configuration options
|
||||
* @param HTMLPurifier_Context $context Context
|
||||
*
|
||||
* @return string|boolean
|
||||
*
|
||||
* @warning Some contexts do not pass $config, $context. These
|
||||
* variables should not be used without checking HTMLPurifier_Length
|
||||
*/
|
||||
public function validate($ratio, $config, $context)
|
||||
{
|
||||
$ratio = $this->parseCDATA($ratio);
|
||||
|
||||
$parts = explode('/', $ratio, 2);
|
||||
$length = count($parts);
|
||||
|
||||
if ($length < 1 || $length > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$num = new \HTMLPurifier_AttrDef_CSS_Number();
|
||||
|
||||
if ($length === 1) {
|
||||
return $num->validate($parts[0], $config, $context);
|
||||
}
|
||||
|
||||
$num1 = $num->validate($parts[0], $config, $context);
|
||||
$num2 = $num->validate($parts[1], $config, $context);
|
||||
|
||||
if ($num1 === false || $num2 === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $num1 . '/' . $num2;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
|
@ -63,24 +63,18 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
|
|||
// This doesn't match I18N domain names, but we don't have proper IRI support,
|
||||
// so force users to insert Punycode.
|
||||
|
||||
// There is not a good sense in which underscores should be
|
||||
// allowed, since it's technically not! (And if you go as
|
||||
// far to allow everything as specified by the DNS spec...
|
||||
// well, that's literally everything, modulo some space limits
|
||||
// for the components and the overall name (which, by the way,
|
||||
// we are NOT checking!). So we (arbitrarily) decide this:
|
||||
// let's allow underscores wherever we would have allowed
|
||||
// hyphens, if they are enabled. This is a pretty good match
|
||||
// for browser behavior, for example, a large number of browsers
|
||||
// cannot handle foo_.example.com, but foo_bar.example.com is
|
||||
// fairly well supported.
|
||||
// Underscores defined as Unreserved Characters in RFC 3986 are
|
||||
// allowed in a URI. There are cases where we want to consider a
|
||||
// URI containing "_" such as "_dmarc.example.com".
|
||||
// Underscores are not allowed in the default. If you want to
|
||||
// allow it, set Core.AllowHostnameUnderscore to true.
|
||||
$underscore = $config->get('Core.AllowHostnameUnderscore') ? '_' : '';
|
||||
|
||||
// Based off of RFC 1738, but amended so that
|
||||
// as per RFC 3696, the top label need only not be all numeric.
|
||||
// The productions describing this are:
|
||||
$a = '[a-z]'; // alpha
|
||||
$an = '[a-z0-9]'; // alphanum
|
||||
$an = "[a-z0-9$underscore]"; // alphanum
|
||||
$and = "[a-z0-9-$underscore]"; // alphanum | "-"
|
||||
// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
||||
$domainlabel = "$an(?:$and*$an)?";
|
||||
|
|
|
@ -116,8 +116,6 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
|
|||
'auto',
|
||||
'cover',
|
||||
'contain',
|
||||
'initial',
|
||||
'inherit',
|
||||
]
|
||||
),
|
||||
new HTMLPurifier_AttrDef_CSS_Percentage(),
|
||||
|
@ -236,21 +234,20 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
|
|||
[
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0'),
|
||||
new HTMLPurifier_AttrDef_CSS_Percentage(true),
|
||||
new HTMLPurifier_AttrDef_Enum(['auto', 'initial', 'inherit'])
|
||||
new HTMLPurifier_AttrDef_Enum(['auto'])
|
||||
]
|
||||
);
|
||||
$trusted_min_wh = new HTMLPurifier_AttrDef_CSS_Composite(
|
||||
[
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0'),
|
||||
new HTMLPurifier_AttrDef_CSS_Percentage(true),
|
||||
new HTMLPurifier_AttrDef_Enum(['initial', 'inherit'])
|
||||
]
|
||||
);
|
||||
$trusted_max_wh = new HTMLPurifier_AttrDef_CSS_Composite(
|
||||
[
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0'),
|
||||
new HTMLPurifier_AttrDef_CSS_Percentage(true),
|
||||
new HTMLPurifier_AttrDef_Enum(['none', 'initial', 'inherit'])
|
||||
new HTMLPurifier_AttrDef_Enum(['none'])
|
||||
]
|
||||
);
|
||||
$max = $config->get('CSS.MaxImgLength');
|
||||
|
@ -278,12 +275,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
|
|||
new HTMLPurifier_AttrDef_Switch(
|
||||
'img',
|
||||
// For img tags:
|
||||
new HTMLPurifier_AttrDef_CSS_Composite(
|
||||
[
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0', $max),
|
||||
new HTMLPurifier_AttrDef_Enum(['initial', 'inherit'])
|
||||
]
|
||||
),
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0', $max),
|
||||
// For everyone else:
|
||||
$trusted_min_wh
|
||||
);
|
||||
|
@ -297,22 +289,29 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
|
|||
new HTMLPurifier_AttrDef_CSS_Composite(
|
||||
[
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0', $max),
|
||||
new HTMLPurifier_AttrDef_Enum(['none', 'initial', 'inherit'])
|
||||
new HTMLPurifier_AttrDef_Enum(['none'])
|
||||
]
|
||||
),
|
||||
// For everyone else:
|
||||
$trusted_max_wh
|
||||
);
|
||||
|
||||
$this->info['aspect-ratio'] = new HTMLPurifier_AttrDef_CSS_Multiple(
|
||||
new HTMLPurifier_AttrDef_CSS_Composite([
|
||||
new HTMLPurifier_AttrDef_CSS_Ratio(),
|
||||
new HTMLPurifier_AttrDef_Enum(['auto']),
|
||||
])
|
||||
);
|
||||
|
||||
// text-decoration and related shorthands
|
||||
$this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration();
|
||||
|
||||
$this->info['text-decoration-line'] = new HTMLPurifier_AttrDef_Enum(
|
||||
['none', 'underline', 'overline', 'line-through', 'initial', 'inherit']
|
||||
['none', 'underline', 'overline', 'line-through']
|
||||
);
|
||||
|
||||
$this->info['text-decoration-style'] = new HTMLPurifier_AttrDef_Enum(
|
||||
['solid', 'double', 'dotted', 'dashed', 'wavy', 'initial', 'inherit']
|
||||
['solid', 'double', 'dotted', 'dashed', 'wavy']
|
||||
);
|
||||
|
||||
$this->info['text-decoration-color'] = new HTMLPurifier_AttrDef_CSS_Color();
|
||||
|
@ -320,7 +319,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
|
|||
$this->info['text-decoration-thickness'] = new HTMLPurifier_AttrDef_CSS_Composite([
|
||||
new HTMLPurifier_AttrDef_CSS_Length(),
|
||||
new HTMLPurifier_AttrDef_CSS_Percentage(),
|
||||
new HTMLPurifier_AttrDef_Enum(['auto', 'from-font', 'initial', 'inherit'])
|
||||
new HTMLPurifier_AttrDef_Enum(['auto', 'from-font'])
|
||||
]);
|
||||
|
||||
$this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily();
|
||||
|
|
|
@ -190,6 +190,9 @@ class HTMLPurifier_ChildDef_Table extends HTMLPurifier_ChildDef
|
|||
$current_tr_tbody = null;
|
||||
|
||||
foreach($content as $node) {
|
||||
if (!isset($node->name)) {
|
||||
continue;
|
||||
}
|
||||
switch ($node->name) {
|
||||
case 'tbody':
|
||||
$current_tr_tbody = null;
|
||||
|
|
|
@ -21,7 +21,7 @@ class HTMLPurifier_Config
|
|||
* HTML Purifier's version
|
||||
* @type string
|
||||
*/
|
||||
public $version = '4.17.0';
|
||||
public $version = '4.18.0';
|
||||
|
||||
/**
|
||||
* Whether or not to automatically finalize
|
||||
|
|
File diff suppressed because one or more lines are too long
10
vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveBlanks.txt
vendored
Normal file
10
vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveBlanks.txt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
Core.RemoveBlanks
|
||||
TYPE: bool
|
||||
DEFAULT: false
|
||||
VERSION: 4.18
|
||||
--DESCRIPTION--
|
||||
<p>
|
||||
If set to true, blank nodes will be removed. This can be useful for maintaining
|
||||
backwards compatibility when upgrading from previous versions of PHP.
|
||||
</p>
|
||||
--# vim: et sw=4 sts=4
|
|
@ -116,8 +116,8 @@ class HTMLPurifier_EntityParser
|
|||
protected function entityCallback($matches)
|
||||
{
|
||||
$entity = $matches[0];
|
||||
$hex_part = @$matches[1];
|
||||
$dec_part = @$matches[2];
|
||||
$hex_part = isset($matches[1]) ? $matches[1] : null;
|
||||
$dec_part = isset($matches[2]) ? $matches[2] : null;
|
||||
$named_part = empty($matches[3]) ? (empty($matches[4]) ? "" : $matches[4]) : $matches[3];
|
||||
if ($hex_part !== NULL && $hex_part !== "") {
|
||||
return HTMLPurifier_Encoder::unichr(hexdec($hex_part));
|
||||
|
|
|
@ -54,6 +54,11 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
|
|||
*/
|
||||
private $_enum_attrdef;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_Enum
|
||||
*/
|
||||
private $_universal_attrdef;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->_tidy = new csstidy();
|
||||
|
@ -70,6 +75,13 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
|
|||
'focus'
|
||||
)
|
||||
);
|
||||
$this->_universal_attrdef = new HTMLPurifier_AttrDef_Enum(
|
||||
array(
|
||||
'initial',
|
||||
'inherit',
|
||||
'unset',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -307,6 +319,11 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
|
|||
unset($style[$name]);
|
||||
continue;
|
||||
}
|
||||
$uni_ret = $this->_universal_attrdef->validate($value, $config, $context);
|
||||
if ($uni_ret !== false) {
|
||||
$style[$name] = $uni_ret;
|
||||
continue;
|
||||
}
|
||||
$def = $css_definition->info[$name];
|
||||
$ret = $def->validate($value, $config, $context);
|
||||
if ($ret === false) {
|
||||
|
|
|
@ -28,22 +28,28 @@ class HTMLPurifier_HTMLModule_Iframe extends HTMLPurifier_HTMLModule
|
|||
if ($config->get('HTML.SafeIframe')) {
|
||||
$this->safe = true;
|
||||
}
|
||||
$attrs = array(
|
||||
'src' => 'URI#embedded',
|
||||
'width' => 'Length',
|
||||
'height' => 'Length',
|
||||
'name' => 'ID',
|
||||
'scrolling' => 'Enum#yes,no,auto',
|
||||
'frameborder' => 'Enum#0,1',
|
||||
'longdesc' => 'URI',
|
||||
'marginheight' => 'Pixels',
|
||||
'marginwidth' => 'Pixels',
|
||||
);
|
||||
|
||||
if ($config->get('HTML.Trusted')) {
|
||||
$attrs['allowfullscreen'] = 'Bool#allowfullscreen';
|
||||
}
|
||||
|
||||
$this->addElement(
|
||||
'iframe',
|
||||
'Inline',
|
||||
'Flow',
|
||||
'Common',
|
||||
array(
|
||||
'src' => 'URI#embedded',
|
||||
'width' => 'Length',
|
||||
'height' => 'Length',
|
||||
'name' => 'ID',
|
||||
'scrolling' => 'Enum#yes,no,auto',
|
||||
'frameborder' => 'Enum#0,1',
|
||||
'longdesc' => 'URI',
|
||||
'marginheight' => 'Pixels',
|
||||
'marginwidth' => 'Pixels',
|
||||
)
|
||||
$attrs
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -269,20 +269,6 @@ class HTMLPurifier_Lexer
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Special Internet Explorer conditional comments should be removed.
|
||||
* @param string $string HTML string to process.
|
||||
* @return string HTML with conditional comments removed.
|
||||
*/
|
||||
protected static function removeIEConditional($string)
|
||||
{
|
||||
return preg_replace(
|
||||
'#<!--\[if [^>]+\]>.*?<!\[endif\]-->#si', // probably should generalize for all strings
|
||||
'',
|
||||
$string
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for escapeCDATA() that does the work.
|
||||
*
|
||||
|
@ -323,8 +309,6 @@ class HTMLPurifier_Lexer
|
|||
// escape CDATA
|
||||
$html = $this->escapeCDATA($html);
|
||||
|
||||
$html = $this->removeIEConditional($html);
|
||||
|
||||
// extract body from document if applicable
|
||||
if ($config->get('Core.ConvertDocumentToFragment')) {
|
||||
$e = false;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue