[COMPOSER] Added predis/predis and updated packages
This commit is contained in:
356
vendor/enqueue/dsn/Dsn.php
vendored
Normal file
356
vendor/enqueue/dsn/Dsn.php
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Enqueue\Dsn;
|
||||
|
||||
class Dsn
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $scheme;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $schemeProtocol;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $schemeExtensions;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $password;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $port;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $queryString;
|
||||
|
||||
/**
|
||||
* @var QueryBag
|
||||
*/
|
||||
private $queryBag;
|
||||
|
||||
public function __construct(
|
||||
string $scheme,
|
||||
string $schemeProtocol,
|
||||
array $schemeExtensions,
|
||||
?string $user,
|
||||
?string $password,
|
||||
?string $host,
|
||||
?int $port,
|
||||
?string $path,
|
||||
?string $queryString,
|
||||
array $query
|
||||
) {
|
||||
$this->scheme = $scheme;
|
||||
$this->schemeProtocol = $schemeProtocol;
|
||||
$this->schemeExtensions = $schemeExtensions;
|
||||
$this->user = $user;
|
||||
$this->password = $password;
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->path = $path;
|
||||
$this->queryString = $queryString;
|
||||
$this->queryBag = new QueryBag($query);
|
||||
}
|
||||
|
||||
public function getScheme(): string
|
||||
{
|
||||
return $this->scheme;
|
||||
}
|
||||
|
||||
public function getSchemeProtocol(): string
|
||||
{
|
||||
return $this->schemeProtocol;
|
||||
}
|
||||
|
||||
public function getSchemeExtensions(): array
|
||||
{
|
||||
return $this->schemeExtensions;
|
||||
}
|
||||
|
||||
public function hasSchemeExtension(string $extension): bool
|
||||
{
|
||||
return in_array($extension, $this->schemeExtensions, true);
|
||||
}
|
||||
|
||||
public function getUser(): ?string
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function getPassword(): ?string
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function getHost(): ?string
|
||||
{
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
public function getPort(): ?int
|
||||
{
|
||||
return $this->port;
|
||||
}
|
||||
|
||||
public function getPath(): ?string
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
public function getQueryString(): ?string
|
||||
{
|
||||
return $this->queryString;
|
||||
}
|
||||
|
||||
public function getQueryBag(): QueryBag
|
||||
{
|
||||
return $this->queryBag;
|
||||
}
|
||||
|
||||
public function getQuery(): array
|
||||
{
|
||||
return $this->queryBag->toArray();
|
||||
}
|
||||
|
||||
public function getString(string $name, string $default = null): ?string
|
||||
{
|
||||
return $this->queryBag->getString($name, $default);
|
||||
}
|
||||
|
||||
public function getDecimal(string $name, int $default = null): ?int
|
||||
{
|
||||
return $this->queryBag->getDecimal($name, $default);
|
||||
}
|
||||
|
||||
public function getOctal(string $name, int $default = null): ?int
|
||||
{
|
||||
return $this->queryBag->getOctal($name, $default);
|
||||
}
|
||||
|
||||
public function getFloat(string $name, float $default = null): ?float
|
||||
{
|
||||
return $this->queryBag->getFloat($name, $default);
|
||||
}
|
||||
|
||||
public function getBool(string $name, bool $default = null): ?bool
|
||||
{
|
||||
return $this->queryBag->getBool($name, $default);
|
||||
}
|
||||
|
||||
public function getArray(string $name, array $default = []): QueryBag
|
||||
{
|
||||
return $this->queryBag->getArray($name, $default);
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'scheme' => $this->scheme,
|
||||
'schemeProtocol' => $this->schemeProtocol,
|
||||
'schemeExtensions' => $this->schemeExtensions,
|
||||
'user' => $this->user,
|
||||
'password' => $this->password,
|
||||
'host' => $this->host,
|
||||
'port' => $this->port,
|
||||
'path' => $this->path,
|
||||
'queryString' => $this->queryString,
|
||||
'query' => $this->queryBag->toArray(),
|
||||
];
|
||||
}
|
||||
|
||||
public static function parseFirst(string $dsn): ?self
|
||||
{
|
||||
return self::parse($dsn)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dsn
|
||||
*
|
||||
* @return Dsn[]
|
||||
*/
|
||||
public static function parse(string $dsn): array
|
||||
{
|
||||
if (false === strpos($dsn, ':')) {
|
||||
throw new \LogicException(sprintf('The DSN is invalid. It does not have scheme separator ":".'));
|
||||
}
|
||||
|
||||
list($scheme, $dsnWithoutScheme) = explode(':', $dsn, 2);
|
||||
|
||||
$scheme = strtolower($scheme);
|
||||
if (false == preg_match('/^[a-z\d+-.]*$/', $scheme)) {
|
||||
throw new \LogicException('The DSN is invalid. Scheme contains illegal symbols.');
|
||||
}
|
||||
|
||||
$schemeParts = explode('+', $scheme);
|
||||
$schemeProtocol = $schemeParts[0];
|
||||
|
||||
unset($schemeParts[0]);
|
||||
$schemeExtensions = array_values($schemeParts);
|
||||
|
||||
$user = parse_url($dsn, PHP_URL_USER) ?: null;
|
||||
if (is_string($user)) {
|
||||
$user = rawurldecode($user);
|
||||
}
|
||||
|
||||
$password = parse_url($dsn, PHP_URL_PASS) ?: null;
|
||||
if (is_string($password)) {
|
||||
$password = rawurldecode($password);
|
||||
}
|
||||
|
||||
$path = parse_url($dsn, PHP_URL_PATH) ?: null;
|
||||
if ($path) {
|
||||
$path = rawurldecode($path);
|
||||
}
|
||||
|
||||
$query = [];
|
||||
$queryString = parse_url($dsn, PHP_URL_QUERY) ?: null;
|
||||
if (is_string($queryString)) {
|
||||
$query = self::httpParseQuery($queryString, '&', PHP_QUERY_RFC3986);
|
||||
}
|
||||
$hostsPorts = '';
|
||||
if (0 === strpos($dsnWithoutScheme, '//')) {
|
||||
$dsnWithoutScheme = substr($dsnWithoutScheme, 2);
|
||||
$dsnWithoutUserPassword = explode('@', $dsnWithoutScheme, 2);
|
||||
$dsnWithoutUserPassword = 2 === count($dsnWithoutUserPassword) ?
|
||||
$dsnWithoutUserPassword[1] :
|
||||
$dsnWithoutUserPassword[0]
|
||||
;
|
||||
|
||||
list($hostsPorts) = explode('#', $dsnWithoutUserPassword, 2);
|
||||
list($hostsPorts) = explode('?', $hostsPorts, 2);
|
||||
list($hostsPorts) = explode('/', $hostsPorts, 2);
|
||||
}
|
||||
|
||||
if (empty($hostsPorts)) {
|
||||
return [
|
||||
new self(
|
||||
$scheme,
|
||||
$schemeProtocol,
|
||||
$schemeExtensions,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$path,
|
||||
$queryString,
|
||||
$query
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
$dsns = [];
|
||||
$hostParts = explode(',', $hostsPorts);
|
||||
foreach ($hostParts as $key => $hostPart) {
|
||||
unset($hostParts[$key]);
|
||||
|
||||
$parts = explode(':', $hostPart, 2);
|
||||
$host = $parts[0];
|
||||
|
||||
$port = null;
|
||||
if (isset($parts[1])) {
|
||||
$port = (int) $parts[1];
|
||||
}
|
||||
|
||||
$dsns[] = new self(
|
||||
$scheme,
|
||||
$schemeProtocol,
|
||||
$schemeExtensions,
|
||||
$user,
|
||||
$password,
|
||||
$host,
|
||||
$port,
|
||||
$path,
|
||||
$queryString,
|
||||
$query
|
||||
);
|
||||
}
|
||||
|
||||
return $dsns;
|
||||
}
|
||||
|
||||
/**
|
||||
* based on http://php.net/manual/en/function.parse-str.php#119484 with some slight modifications.
|
||||
*/
|
||||
private static function httpParseQuery(string $queryString, string $argSeparator = '&', int $decType = PHP_QUERY_RFC1738): array
|
||||
{
|
||||
$result = [];
|
||||
$parts = explode($argSeparator, $queryString);
|
||||
|
||||
foreach ($parts as $part) {
|
||||
list($paramName, $paramValue) = explode('=', $part, 2);
|
||||
|
||||
switch ($decType) {
|
||||
case PHP_QUERY_RFC3986:
|
||||
$paramName = rawurldecode($paramName);
|
||||
$paramValue = rawurldecode($paramValue);
|
||||
break;
|
||||
case PHP_QUERY_RFC1738:
|
||||
default:
|
||||
$paramName = urldecode($paramName);
|
||||
$paramValue = urldecode($paramValue);
|
||||
break;
|
||||
}
|
||||
|
||||
if (preg_match_all('/\[([^\]]*)\]/m', $paramName, $matches)) {
|
||||
$paramName = substr($paramName, 0, strpos($paramName, '['));
|
||||
$keys = array_merge([$paramName], $matches[1]);
|
||||
} else {
|
||||
$keys = [$paramName];
|
||||
}
|
||||
|
||||
$target = &$result;
|
||||
|
||||
foreach ($keys as $index) {
|
||||
if ('' === $index) {
|
||||
if (is_array($target)) {
|
||||
$intKeys = array_filter(array_keys($target), 'is_int');
|
||||
$index = count($intKeys) ? max($intKeys) + 1 : 0;
|
||||
} else {
|
||||
$target = [$target];
|
||||
$index = 1;
|
||||
}
|
||||
} elseif (isset($target[$index]) && !is_array($target[$index])) {
|
||||
$target[$index] = [$target[$index]];
|
||||
}
|
||||
|
||||
$target = &$target[$index];
|
||||
}
|
||||
|
||||
if (is_array($target)) {
|
||||
$target[] = $paramValue;
|
||||
} else {
|
||||
$target = $paramValue;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
11
vendor/enqueue/dsn/InvalidQueryParameterTypeException.php
vendored
Normal file
11
vendor/enqueue/dsn/InvalidQueryParameterTypeException.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Enqueue\Dsn;
|
||||
|
||||
final class InvalidQueryParameterTypeException extends \LogicException
|
||||
{
|
||||
public static function create(string $name, string $expectedType): self
|
||||
{
|
||||
return new static(sprintf('The query parameter "%s" has invalid type. It must be "%s"', $name, $expectedType));
|
||||
}
|
||||
}
|
20
vendor/enqueue/dsn/LICENSE
vendored
Normal file
20
vendor/enqueue/dsn/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2018 Kotliar Maksym
|
||||
|
||||
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.
|
103
vendor/enqueue/dsn/QueryBag.php
vendored
Normal file
103
vendor/enqueue/dsn/QueryBag.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Enqueue\Dsn;
|
||||
|
||||
class QueryBag
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $query;
|
||||
|
||||
public function __construct(array $query)
|
||||
{
|
||||
$this->query = $query;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
public function getString(string $name, string $default = null): ?string
|
||||
{
|
||||
return array_key_exists($name, $this->query) ? $this->query[$name] : $default;
|
||||
}
|
||||
|
||||
public function getDecimal(string $name, int $default = null): ?int
|
||||
{
|
||||
$value = $this->getString($name);
|
||||
if (null === $value) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (false == preg_match('/^[\+\-]?[0-9]*$/', $value)) {
|
||||
throw InvalidQueryParameterTypeException::create($name, 'decimal');
|
||||
}
|
||||
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
public function getOctal(string $name, int $default = null): ?int
|
||||
{
|
||||
$value = $this->getString($name);
|
||||
if (null === $value) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (false == preg_match('/^0[\+\-]?[0-7]*$/', $value)) {
|
||||
throw InvalidQueryParameterTypeException::create($name, 'octal');
|
||||
}
|
||||
|
||||
return intval($value, 8);
|
||||
}
|
||||
|
||||
public function getFloat(string $name, float $default = null): ?float
|
||||
{
|
||||
$value = $this->getString($name);
|
||||
if (null === $value) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (false == is_numeric($value)) {
|
||||
throw InvalidQueryParameterTypeException::create($name, 'float');
|
||||
}
|
||||
|
||||
return (float) $value;
|
||||
}
|
||||
|
||||
public function getBool(string $name, bool $default = null): ?bool
|
||||
{
|
||||
$value = $this->getString($name);
|
||||
if (null === $value) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (in_array($value, ['', '0', 'false'], true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (in_array($value, ['1', 'true'], true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw InvalidQueryParameterTypeException::create($name, 'bool');
|
||||
}
|
||||
|
||||
public function getArray(string $name, array $default = []): self
|
||||
{
|
||||
if (false == array_key_exists($name, $this->query)) {
|
||||
return new self($default);
|
||||
}
|
||||
|
||||
$value = $this->query[$name];
|
||||
|
||||
if (is_array($value)) {
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
throw InvalidQueryParameterTypeException::create($name, 'array');
|
||||
}
|
||||
}
|
29
vendor/enqueue/dsn/README.md
vendored
Normal file
29
vendor/enqueue/dsn/README.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<h2 align="center">Supporting Enqueue</h2>
|
||||
|
||||
Enqueue is an MIT-licensed open source project with its ongoing development made possible entirely by the support of community and our customers. If you'd like to join them, please consider:
|
||||
|
||||
- [Become a sponsor](https://www.patreon.com/makasim)
|
||||
- [Become our client](http://forma-pro.com/)
|
||||
|
||||
---
|
||||
|
||||
# Enqueue. Parse DSN class
|
||||
|
||||
## Resources
|
||||
|
||||
* [Site](https://enqueue.forma-pro.com/)
|
||||
* [Documentation](https://github.com/php-enqueue/enqueue-dev/blob/master/docs/dsn.md)
|
||||
* [Questions](https://gitter.im/php-enqueue/Lobby)
|
||||
* [Issue Tracker](https://github.com/php-enqueue/enqueue-dev/issues)
|
||||
|
||||
## Developed by Forma-Pro
|
||||
|
||||
Forma-Pro is a full stack development company which interests also spread to open source development.
|
||||
Being a team of strong professionals we have an aim an ability to help community by developing cutting edge solutions in the areas of e-commerce, docker & microservice oriented architecture where we have accumulated a huge many-years experience.
|
||||
Our main specialization is Symfony framework based solution, but we are always looking to the technologies that allow us to do our job the best way. We are committed to creating solutions that revolutionize the way how things are developed in aspects of architecture & scalability.
|
||||
|
||||
If you have any questions and inquires about our open source development, this product particularly or any other matter feel free to contact at opensource@forma-pro.com
|
||||
|
||||
## License
|
||||
|
||||
It is released under the [MIT License](LICENSE).
|
33
vendor/enqueue/dsn/composer.json
vendored
Normal file
33
vendor/enqueue/dsn/composer.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "enqueue/dsn",
|
||||
"type": "library",
|
||||
"description": "Parse DSN",
|
||||
"keywords": ["dsn", "parse"],
|
||||
"homepage": "https://enqueue.forma-pro.com/",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~5.4.0"
|
||||
},
|
||||
"support": {
|
||||
"email": "opensource@forma-pro.com",
|
||||
"issues": "https://github.com/php-enqueue/enqueue-dev/issues",
|
||||
"forum": "https://gitter.im/php-enqueue/Lobby",
|
||||
"source": "https://github.com/php-enqueue/enqueue-dev",
|
||||
"docs": "https://github.com/php-enqueue/enqueue-dev/blob/master/docs/index.md"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Enqueue\\Dsn\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.9.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
116
vendor/enqueue/stomp/BufferedStompClient.php
vendored
Normal file
116
vendor/enqueue/stomp/BufferedStompClient.php
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Enqueue\Stomp;
|
||||
|
||||
use Stomp\Client;
|
||||
use Stomp\Transport\Frame;
|
||||
|
||||
class BufferedStompClient extends Client
|
||||
{
|
||||
/**
|
||||
* [
|
||||
* 'subscriptionId' => Frame[],
|
||||
* ].
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $buffer;
|
||||
|
||||
/**
|
||||
* @var int int
|
||||
*/
|
||||
private $bufferSize;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $currentBufferSize;
|
||||
|
||||
/**
|
||||
* @param \Stomp\Network\Connection|string $broker
|
||||
* @param int $bufferSize
|
||||
*/
|
||||
public function __construct($broker, $bufferSize = 1000)
|
||||
{
|
||||
parent::__construct($broker);
|
||||
|
||||
$this->bufferSize = $bufferSize;
|
||||
$this->buffer = [];
|
||||
$this->currentBufferSize = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getBufferSize()
|
||||
{
|
||||
return $this->bufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timeout is in milliseconds.
|
||||
*/
|
||||
public function readMessageFrame(string $subscriptionId, int $timeout): ?Frame
|
||||
{
|
||||
// pop up frame from the buffer
|
||||
if (isset($this->buffer[$subscriptionId]) && ($frame = array_shift($this->buffer[$subscriptionId]))) {
|
||||
--$this->currentBufferSize;
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
// do nothing when buffer is full
|
||||
if ($this->currentBufferSize >= $this->bufferSize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$startTime = microtime(true);
|
||||
$remainingTimeout = $timeout * 1000;
|
||||
|
||||
while (true) {
|
||||
$this->getConnection()->setReadTimeout(0, $remainingTimeout);
|
||||
|
||||
// there is nothing to read
|
||||
if (false === $frame = $this->readFrame()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ('MESSAGE' !== $frame->getCommand()) {
|
||||
throw new \LogicException(sprintf('Unexpected frame was received: "%s"', $frame->getCommand()));
|
||||
}
|
||||
|
||||
$headers = $frame->getHeaders();
|
||||
|
||||
if (false == isset($headers['subscription'])) {
|
||||
throw new \LogicException('Got message frame with missing subscription header');
|
||||
}
|
||||
|
||||
// frame belongs to another subscription
|
||||
if ($headers['subscription'] !== $subscriptionId) {
|
||||
$this->buffer[$headers['subscription']][] = $frame;
|
||||
++$this->currentBufferSize;
|
||||
|
||||
$remainingTimeout -= (microtime(true) - $startTime) * 1000000;
|
||||
|
||||
if ($remainingTimeout <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function disconnect($sync = false)
|
||||
{
|
||||
parent::disconnect($sync);
|
||||
|
||||
$this->buffer = [];
|
||||
$this->currentBufferSize = 0;
|
||||
}
|
||||
}
|
20
vendor/enqueue/stomp/LICENSE
vendored
Normal file
20
vendor/enqueue/stomp/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Kotliar Maksym
|
||||
|
||||
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.
|
36
vendor/enqueue/stomp/README.md
vendored
Normal file
36
vendor/enqueue/stomp/README.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<h2 align="center">Supporting Enqueue</h2>
|
||||
|
||||
Enqueue is an MIT-licensed open source project with its ongoing development made possible entirely by the support of community and our customers. If you'd like to join them, please consider:
|
||||
|
||||
- [Become a sponsor](https://www.patreon.com/makasim)
|
||||
- [Become our client](http://forma-pro.com/)
|
||||
|
||||
---
|
||||
|
||||
# STOMP Transport
|
||||
|
||||
[](https://gitter.im/php-enqueue/Lobby)
|
||||
[](https://travis-ci.org/php-enqueue/stomp)
|
||||
[](https://packagist.org/packages/enqueue/stomp)
|
||||
[](https://packagist.org/packages/enqueue/stomp)
|
||||
|
||||
This is an implementation of Queue Interop specification. It allows you to send and consume message via STOMP protocol.
|
||||
|
||||
## Resources
|
||||
|
||||
* [Site](https://enqueue.forma-pro.com/)
|
||||
* [Documentation](https://php-enqueue.github.io/transport/stomp/)
|
||||
* [Questions](https://gitter.im/php-enqueue/Lobby)
|
||||
* [Issue Tracker](https://github.com/php-enqueue/enqueue-dev/issues)
|
||||
|
||||
## Developed by Forma-Pro
|
||||
|
||||
Forma-Pro is a full stack development company which interests also spread to open source development.
|
||||
Being a team of strong professionals we have an aim an ability to help community by developing cutting edge solutions in the areas of e-commerce, docker & microservice oriented architecture where we have accumulated a huge many-years experience.
|
||||
Our main specialization is Symfony framework based solution, but we are always looking to the technologies that allow us to do our job the best way. We are committed to creating solutions that revolutionize the way how things are developed in aspects of architecture & scalability.
|
||||
|
||||
If you have any questions and inquires about our open source development, this product particularly or any other matter feel free to contact at opensource@forma-pro.com
|
||||
|
||||
## License
|
||||
|
||||
It is released under the [MIT License](LICENSE).
|
150
vendor/enqueue/stomp/StompConnectionFactory.php
vendored
Normal file
150
vendor/enqueue/stomp/StompConnectionFactory.php
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Enqueue\Stomp;
|
||||
|
||||
use Enqueue\Dsn\Dsn;
|
||||
use Interop\Queue\ConnectionFactory;
|
||||
use Interop\Queue\Context;
|
||||
use Stomp\Network\Connection;
|
||||
|
||||
class StompConnectionFactory implements ConnectionFactory
|
||||
{
|
||||
const SCHEME_EXT_ACTIVEMQ = 'activemq';
|
||||
const SCHEME_EXT_RABBITMQ = 'rabbitmq';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @var BufferedStompClient
|
||||
*/
|
||||
private $stomp;
|
||||
|
||||
/**
|
||||
* $config = [
|
||||
* 'host' => null,
|
||||
* 'port' => null,
|
||||
* 'login' => null,
|
||||
* 'password' => null,
|
||||
* 'vhost' => null,
|
||||
* 'buffer_size' => 1000,
|
||||
* 'connection_timeout' => 1,
|
||||
* 'sync' => false,
|
||||
* 'lazy' => true,
|
||||
* 'ssl_on' => false,
|
||||
* ].
|
||||
*
|
||||
* or
|
||||
*
|
||||
* stomp:
|
||||
* stomp:?buffer_size=100
|
||||
*
|
||||
* @param array|string|null $config
|
||||
*/
|
||||
public function __construct($config = 'stomp:')
|
||||
{
|
||||
if (empty($config) || 'stomp:' === $config) {
|
||||
$config = [];
|
||||
} elseif (is_string($config)) {
|
||||
$config = $this->parseDsn($config);
|
||||
} elseif (is_array($config)) {
|
||||
if (array_key_exists('dsn', $config)) {
|
||||
$config = array_replace($config, $this->parseDsn($config['dsn']));
|
||||
|
||||
unset($config['dsn']);
|
||||
}
|
||||
} else {
|
||||
throw new \LogicException('The config must be either an array of options, a DSN string or null');
|
||||
}
|
||||
|
||||
$this->config = array_replace($this->defaultConfig(), $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StompContext
|
||||
*/
|
||||
public function createContext(): Context
|
||||
{
|
||||
$useExchangePrefix = self::SCHEME_EXT_RABBITMQ === $this->config['target'] ? true : false;
|
||||
|
||||
if ($this->config['lazy']) {
|
||||
return new StompContext(function () {
|
||||
return $this->establishConnection();
|
||||
}, $useExchangePrefix);
|
||||
}
|
||||
|
||||
return new StompContext($this->establishConnection(), $useExchangePrefix);
|
||||
}
|
||||
|
||||
private function establishConnection(): BufferedStompClient
|
||||
{
|
||||
if (false == $this->stomp) {
|
||||
$config = $this->config;
|
||||
|
||||
$scheme = (true === $config['ssl_on']) ? 'ssl' : 'tcp';
|
||||
$uri = $scheme.'://'.$config['host'].':'.$config['port'];
|
||||
$connection = new Connection($uri, $config['connection_timeout']);
|
||||
|
||||
$this->stomp = new BufferedStompClient($connection, $config['buffer_size']);
|
||||
$this->stomp->setLogin($config['login'], $config['password']);
|
||||
$this->stomp->setVhostname($config['vhost']);
|
||||
$this->stomp->setSync($config['sync']);
|
||||
|
||||
$this->stomp->connect();
|
||||
}
|
||||
|
||||
return $this->stomp;
|
||||
}
|
||||
|
||||
private function parseDsn(string $dsn): array
|
||||
{
|
||||
$dsn = Dsn::parseFirst($dsn);
|
||||
|
||||
if ('stomp' !== $dsn->getSchemeProtocol()) {
|
||||
throw new \LogicException(sprintf('The given DSN is not supported. Must start with "stomp:".'));
|
||||
}
|
||||
|
||||
$schemeExtension = current($dsn->getSchemeExtensions());
|
||||
if (false === $schemeExtension) {
|
||||
$schemeExtension = self::SCHEME_EXT_RABBITMQ;
|
||||
}
|
||||
if (self::SCHEME_EXT_ACTIVEMQ !== $schemeExtension && self::SCHEME_EXT_RABBITMQ !== $schemeExtension) {
|
||||
throw new \LogicException(sprintf('The given DSN is not supported. The scheme extension "%s" provided is invalid. It must be one of "%s" or "%s".', $schemeExtension, self::SCHEME_EXT_ACTIVEMQ, self::SCHEME_EXT_RABBITMQ));
|
||||
}
|
||||
|
||||
return array_filter(array_replace($dsn->getQuery(), [
|
||||
'target' => $schemeExtension,
|
||||
'host' => $dsn->getHost(),
|
||||
'port' => $dsn->getPort(),
|
||||
'login' => $dsn->getUser(),
|
||||
'password' => $dsn->getPassword(),
|
||||
'vhost' => null !== $dsn->getPath() ? ltrim($dsn->getPath(), '/') : null,
|
||||
'buffer_size' => $dsn->getDecimal('buffer_size'),
|
||||
'connection_timeout' => $dsn->getDecimal('connection_timeout'),
|
||||
'sync' => $dsn->getBool('sync'),
|
||||
'lazy' => $dsn->getBool('lazy'),
|
||||
'ssl_on' => $dsn->getBool('ssl_on'),
|
||||
]), function ($value) { return null !== $value; });
|
||||
}
|
||||
|
||||
private function defaultConfig(): array
|
||||
{
|
||||
return [
|
||||
'target' => self::SCHEME_EXT_RABBITMQ,
|
||||
'host' => 'localhost',
|
||||
'port' => 61613,
|
||||
'login' => 'guest',
|
||||
'password' => 'guest',
|
||||
'vhost' => '/',
|
||||
'buffer_size' => 1000,
|
||||
'connection_timeout' => 1,
|
||||
'sync' => false,
|
||||
'lazy' => true,
|
||||
'ssl_on' => false,
|
||||
];
|
||||
}
|
||||
}
|
210
vendor/enqueue/stomp/StompConsumer.php
vendored
Normal file
210
vendor/enqueue/stomp/StompConsumer.php
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Enqueue\Stomp;
|
||||
|
||||
use Interop\Queue\Consumer;
|
||||
use Interop\Queue\Exception\InvalidMessageException;
|
||||
use Interop\Queue\Message;
|
||||
use Interop\Queue\Queue;
|
||||
use Stomp\Client;
|
||||
use Stomp\Transport\Frame;
|
||||
|
||||
class StompConsumer implements Consumer
|
||||
{
|
||||
const ACK_AUTO = 'auto';
|
||||
const ACK_CLIENT = 'client';
|
||||
const ACK_CLIENT_INDIVIDUAL = 'client-individual';
|
||||
|
||||
/**
|
||||
* @var StompDestination
|
||||
*/
|
||||
private $queue;
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $stomp;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isSubscribed;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $ackMode;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $prefetchCount;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $subscriptionId;
|
||||
|
||||
public function __construct(BufferedStompClient $stomp, StompDestination $queue)
|
||||
{
|
||||
$this->stomp = $stomp;
|
||||
$this->queue = $queue;
|
||||
$this->isSubscribed = false;
|
||||
$this->ackMode = self::ACK_CLIENT_INDIVIDUAL;
|
||||
$this->prefetchCount = 1;
|
||||
$this->subscriptionId = StompDestination::TYPE_TEMP_QUEUE == $queue->getType() ?
|
||||
$queue->getQueueName() :
|
||||
uniqid('', true)
|
||||
;
|
||||
}
|
||||
|
||||
public function setAckMode(string $mode): void
|
||||
{
|
||||
if (false === in_array($mode, [self::ACK_AUTO, self::ACK_CLIENT, self::ACK_CLIENT_INDIVIDUAL], true)) {
|
||||
throw new \LogicException(sprintf('Ack mode is not valid: "%s"', $mode));
|
||||
}
|
||||
|
||||
$this->ackMode = $mode;
|
||||
}
|
||||
|
||||
public function getAckMode(): string
|
||||
{
|
||||
return $this->ackMode;
|
||||
}
|
||||
|
||||
public function getPrefetchCount(): int
|
||||
{
|
||||
return $this->prefetchCount;
|
||||
}
|
||||
|
||||
public function setPrefetchCount(int $prefetchCount): void
|
||||
{
|
||||
$this->prefetchCount = $prefetchCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StompDestination
|
||||
*/
|
||||
public function getQueue(): Queue
|
||||
{
|
||||
return $this->queue;
|
||||
}
|
||||
|
||||
public function receive(int $timeout = 0): ?Message
|
||||
{
|
||||
$this->subscribe();
|
||||
|
||||
if (0 === $timeout) {
|
||||
while (true) {
|
||||
if ($message = $this->stomp->readMessageFrame($this->subscriptionId, 100)) {
|
||||
return $this->convertMessage($message);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($message = $this->stomp->readMessageFrame($this->subscriptionId, $timeout)) {
|
||||
return $this->convertMessage($message);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function receiveNoWait(): ?Message
|
||||
{
|
||||
$this->subscribe();
|
||||
|
||||
if ($message = $this->stomp->readMessageFrame($this->subscriptionId, 0)) {
|
||||
return $this->convertMessage($message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StompMessage $message
|
||||
*/
|
||||
public function acknowledge(Message $message): void
|
||||
{
|
||||
InvalidMessageException::assertMessageInstanceOf($message, StompMessage::class);
|
||||
|
||||
$this->stomp->sendFrame(
|
||||
$this->stomp->getProtocol()->getAckFrame($message->getFrame())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StompMessage $message
|
||||
*/
|
||||
public function reject(Message $message, bool $requeue = false): void
|
||||
{
|
||||
InvalidMessageException::assertMessageInstanceOf($message, StompMessage::class);
|
||||
|
||||
$nackFrame = $this->stomp->getProtocol()->getNackFrame($message->getFrame());
|
||||
|
||||
// rabbitmq STOMP protocol extension
|
||||
$nackFrame->addHeaders([
|
||||
'requeue' => $requeue ? 'true' : 'false',
|
||||
]);
|
||||
|
||||
$this->stomp->sendFrame($nackFrame);
|
||||
}
|
||||
|
||||
private function subscribe(): void
|
||||
{
|
||||
if (StompDestination::TYPE_TEMP_QUEUE == $this->queue->getType()) {
|
||||
$this->isSubscribed = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (false == $this->isSubscribed) {
|
||||
$this->isSubscribed = true;
|
||||
|
||||
$frame = $this->stomp->getProtocol()->getSubscribeFrame(
|
||||
$this->queue->getQueueName(),
|
||||
$this->subscriptionId,
|
||||
$this->ackMode
|
||||
);
|
||||
|
||||
// rabbitmq STOMP protocol extension
|
||||
$headers = $this->queue->getHeaders();
|
||||
$headers['prefetch-count'] = $this->prefetchCount;
|
||||
$headers = StompHeadersEncoder::encode($headers);
|
||||
|
||||
foreach ($headers as $key => $value) {
|
||||
$frame[$key] = $value;
|
||||
}
|
||||
|
||||
$this->stomp->sendFrame($frame);
|
||||
}
|
||||
}
|
||||
|
||||
private function convertMessage(Frame $frame): StompMessage
|
||||
{
|
||||
if ('MESSAGE' !== $frame->getCommand()) {
|
||||
throw new \LogicException(sprintf('Frame is not MESSAGE frame but: "%s"', $frame->getCommand()));
|
||||
}
|
||||
|
||||
list($headers, $properties) = StompHeadersEncoder::decode($frame->getHeaders());
|
||||
|
||||
$redelivered = isset($headers['redelivered']) && 'true' === $headers['redelivered'];
|
||||
|
||||
unset(
|
||||
$headers['redelivered'],
|
||||
$headers['destination'],
|
||||
$headers['message-id'],
|
||||
$headers['ack'],
|
||||
$headers['receipt'],
|
||||
$headers['subscription'],
|
||||
$headers['content-length']
|
||||
);
|
||||
|
||||
$message = new StompMessage((string) $frame->getBody(), $properties, $headers);
|
||||
$message->setRedelivered($redelivered);
|
||||
$message->setFrame($frame);
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
213
vendor/enqueue/stomp/StompContext.php
vendored
Normal file
213
vendor/enqueue/stomp/StompContext.php
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Enqueue\Stomp;
|
||||
|
||||
use Interop\Queue\Consumer;
|
||||
use Interop\Queue\Context;
|
||||
use Interop\Queue\Destination;
|
||||
use Interop\Queue\Exception\InvalidDestinationException;
|
||||
use Interop\Queue\Exception\PurgeQueueNotSupportedException;
|
||||
use Interop\Queue\Exception\SubscriptionConsumerNotSupportedException;
|
||||
use Interop\Queue\Message;
|
||||
use Interop\Queue\Producer;
|
||||
use Interop\Queue\Queue;
|
||||
use Interop\Queue\SubscriptionConsumer;
|
||||
use Interop\Queue\Topic;
|
||||
|
||||
class StompContext implements Context
|
||||
{
|
||||
/**
|
||||
* @var BufferedStompClient
|
||||
*/
|
||||
private $stomp;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $useExchangePrefix;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
private $stompFactory;
|
||||
|
||||
/**
|
||||
* @param BufferedStompClient|callable $stomp
|
||||
* @param bool $useExchangePrefix
|
||||
*/
|
||||
public function __construct($stomp, $useExchangePrefix = true)
|
||||
{
|
||||
if ($stomp instanceof BufferedStompClient) {
|
||||
$this->stomp = $stomp;
|
||||
} elseif (is_callable($stomp)) {
|
||||
$this->stompFactory = $stomp;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('The stomp argument must be either BufferedStompClient or callable that return BufferedStompClient.');
|
||||
}
|
||||
|
||||
$this->useExchangePrefix = $useExchangePrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StompMessage
|
||||
*/
|
||||
public function createMessage(string $body = '', array $properties = [], array $headers = []): Message
|
||||
{
|
||||
return new StompMessage($body, $properties, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StompDestination
|
||||
*/
|
||||
public function createQueue(string $name): Queue
|
||||
{
|
||||
if (0 !== strpos($name, '/')) {
|
||||
$destination = new StompDestination();
|
||||
$destination->setType(StompDestination::TYPE_QUEUE);
|
||||
$destination->setStompName($name);
|
||||
|
||||
return $destination;
|
||||
}
|
||||
|
||||
return $this->createDestination($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StompDestination
|
||||
*/
|
||||
public function createTemporaryQueue(): Queue
|
||||
{
|
||||
$queue = $this->createQueue(uniqid('', true));
|
||||
$queue->setType(StompDestination::TYPE_TEMP_QUEUE);
|
||||
|
||||
return $queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StompDestination
|
||||
*/
|
||||
public function createTopic(string $name): Topic
|
||||
{
|
||||
if (0 !== strpos($name, '/')) {
|
||||
$destination = new StompDestination();
|
||||
$destination->setType($this->useExchangePrefix ? StompDestination::TYPE_EXCHANGE : StompDestination::TYPE_TOPIC);
|
||||
$destination->setStompName($name);
|
||||
|
||||
return $destination;
|
||||
}
|
||||
|
||||
return $this->createDestination($name);
|
||||
}
|
||||
|
||||
public function createDestination(string $destination): StompDestination
|
||||
{
|
||||
$types = [
|
||||
StompDestination::TYPE_TOPIC,
|
||||
StompDestination::TYPE_EXCHANGE,
|
||||
StompDestination::TYPE_QUEUE,
|
||||
StompDestination::TYPE_AMQ_QUEUE,
|
||||
StompDestination::TYPE_TEMP_QUEUE,
|
||||
StompDestination::TYPE_REPLY_QUEUE,
|
||||
];
|
||||
|
||||
$dest = $destination;
|
||||
$type = null;
|
||||
$name = null;
|
||||
$routingKey = null;
|
||||
|
||||
foreach ($types as $_type) {
|
||||
$typePrefix = '/'.$_type.'/';
|
||||
if (0 === strpos($dest, $typePrefix)) {
|
||||
$type = $_type;
|
||||
$dest = substr($dest, strlen($typePrefix));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $type) {
|
||||
throw new \LogicException(sprintf('Destination name is invalid, cant find type: "%s"', $destination));
|
||||
}
|
||||
|
||||
$pieces = explode('/', $dest);
|
||||
|
||||
if (count($pieces) > 2) {
|
||||
throw new \LogicException(sprintf('Destination name is invalid, found extra / char: "%s"', $destination));
|
||||
}
|
||||
|
||||
if (empty($pieces[0])) {
|
||||
throw new \LogicException(sprintf('Destination name is invalid, name is empty: "%s"', $destination));
|
||||
}
|
||||
|
||||
$name = $pieces[0];
|
||||
|
||||
if (isset($pieces[1])) {
|
||||
if (empty($pieces[1])) {
|
||||
throw new \LogicException(sprintf('Destination name is invalid, routing key is empty: "%s"', $destination));
|
||||
}
|
||||
|
||||
$routingKey = $pieces[1];
|
||||
}
|
||||
|
||||
$destination = new StompDestination();
|
||||
$destination->setType($type);
|
||||
$destination->setStompName($name);
|
||||
$destination->setRoutingKey($routingKey);
|
||||
|
||||
return $destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StompDestination $destination
|
||||
*
|
||||
* @return StompConsumer
|
||||
*/
|
||||
public function createConsumer(Destination $destination): Consumer
|
||||
{
|
||||
InvalidDestinationException::assertDestinationInstanceOf($destination, StompDestination::class);
|
||||
|
||||
return new StompConsumer($this->getStomp(), $destination);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StompProducer
|
||||
*/
|
||||
public function createProducer(): Producer
|
||||
{
|
||||
return new StompProducer($this->getStomp());
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
$this->getStomp()->disconnect();
|
||||
}
|
||||
|
||||
public function createSubscriptionConsumer(): SubscriptionConsumer
|
||||
{
|
||||
throw SubscriptionConsumerNotSupportedException::providerDoestNotSupportIt();
|
||||
}
|
||||
|
||||
public function purgeQueue(Queue $queue): void
|
||||
{
|
||||
throw PurgeQueueNotSupportedException::providerDoestNotSupportIt();
|
||||
}
|
||||
|
||||
public function getStomp(): BufferedStompClient
|
||||
{
|
||||
if (false == $this->stomp) {
|
||||
$stomp = call_user_func($this->stompFactory);
|
||||
if (false == $stomp instanceof BufferedStompClient) {
|
||||
throw new \LogicException(sprintf(
|
||||
'The factory must return instance of BufferedStompClient. It returns %s',
|
||||
is_object($stomp) ? get_class($stomp) : gettype($stomp)
|
||||
));
|
||||
}
|
||||
|
||||
$this->stomp = $stomp;
|
||||
}
|
||||
|
||||
return $this->stomp;
|
||||
}
|
||||
}
|
164
vendor/enqueue/stomp/StompDestination.php
vendored
Normal file
164
vendor/enqueue/stomp/StompDestination.php
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Enqueue\Stomp;
|
||||
|
||||
use Interop\Queue\Queue;
|
||||
use Interop\Queue\Topic;
|
||||
|
||||
class StompDestination implements Topic, Queue
|
||||
{
|
||||
const TYPE_TOPIC = 'topic';
|
||||
const TYPE_EXCHANGE = 'exchange';
|
||||
const TYPE_QUEUE = 'queue';
|
||||
const TYPE_AMQ_QUEUE = 'amq/queue';
|
||||
const TYPE_TEMP_QUEUE = 'temp-queue';
|
||||
const TYPE_REPLY_QUEUE = 'reply-queue';
|
||||
|
||||
const HEADER_DURABLE = 'durable';
|
||||
const HEADER_AUTO_DELETE = 'auto-delete';
|
||||
const HEADER_EXCLUSIVE = 'exclusive';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $routingKey;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $headers;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->headers = [
|
||||
self::HEADER_DURABLE => false,
|
||||
self::HEADER_AUTO_DELETE => true,
|
||||
self::HEADER_EXCLUSIVE => false,
|
||||
];
|
||||
}
|
||||
|
||||
public function getStompName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setStompName(string $name): void
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getQueueName(): string
|
||||
{
|
||||
if (empty($this->getStompName())) {
|
||||
throw new \LogicException('Destination name is not set');
|
||||
}
|
||||
|
||||
$name = '/'.$this->getType().'/'.$this->getStompName();
|
||||
|
||||
if ($this->getRoutingKey()) {
|
||||
$name .= '/'.$this->getRoutingKey();
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
public function getTopicName(): string
|
||||
{
|
||||
return $this->getQueueName();
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType(string $type): void
|
||||
{
|
||||
$types = [
|
||||
self::TYPE_TOPIC,
|
||||
self::TYPE_EXCHANGE,
|
||||
self::TYPE_QUEUE,
|
||||
self::TYPE_AMQ_QUEUE,
|
||||
self::TYPE_TEMP_QUEUE,
|
||||
self::TYPE_REPLY_QUEUE,
|
||||
];
|
||||
|
||||
if (false == in_array($type, $types, true)) {
|
||||
throw new \LogicException(sprintf('Invalid destination type: "%s"', $type));
|
||||
}
|
||||
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function getRoutingKey(): ?string
|
||||
{
|
||||
return $this->routingKey;
|
||||
}
|
||||
|
||||
public function setRoutingKey(string $routingKey = null): void
|
||||
{
|
||||
$this->routingKey = $routingKey;
|
||||
}
|
||||
|
||||
public function isDurable(): bool
|
||||
{
|
||||
return $this->getHeader(self::HEADER_DURABLE, false);
|
||||
}
|
||||
|
||||
public function setDurable(bool $durable): void
|
||||
{
|
||||
$this->setHeader(self::HEADER_DURABLE, $durable);
|
||||
}
|
||||
|
||||
public function isAutoDelete(): bool
|
||||
{
|
||||
return $this->getHeader(self::HEADER_AUTO_DELETE, false);
|
||||
}
|
||||
|
||||
public function setAutoDelete(bool $autoDelete): void
|
||||
{
|
||||
$this->setHeader(self::HEADER_AUTO_DELETE, $autoDelete);
|
||||
}
|
||||
|
||||
public function isExclusive(): bool
|
||||
{
|
||||
return $this->getHeader(self::HEADER_EXCLUSIVE, false);
|
||||
}
|
||||
|
||||
public function setExclusive(bool $exclusive): void
|
||||
{
|
||||
$this->setHeader(self::HEADER_EXCLUSIVE, $exclusive);
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers): void
|
||||
{
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
public function getHeaders(): array
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
public function getHeader(string $name, $default = null)
|
||||
{
|
||||
return array_key_exists($name, $this->headers) ? $this->headers[$name] : $default;
|
||||
}
|
||||
|
||||
public function setHeader(string $name, $value): void
|
||||
{
|
||||
$this->headers[$name] = $value;
|
||||
}
|
||||
}
|
136
vendor/enqueue/stomp/StompHeadersEncoder.php
vendored
Normal file
136
vendor/enqueue/stomp/StompHeadersEncoder.php
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Enqueue\Stomp;
|
||||
|
||||
class StompHeadersEncoder
|
||||
{
|
||||
const PROPERTY_PREFIX = '_property_';
|
||||
const TYPE_PREFIX = '_type_';
|
||||
const TYPE_STRING = 's';
|
||||
const TYPE_INT = 'i';
|
||||
const TYPE_FLOAT = 'f';
|
||||
const TYPE_BOOL = 'b';
|
||||
const TYPE_NULL = 'n';
|
||||
|
||||
public static function encode(array $headers = [], array $properties = []): array
|
||||
{
|
||||
$encodedHeaders = self::doEncode($headers);
|
||||
|
||||
foreach (self::doEncode($properties) as $key => $value) {
|
||||
$encodedHeaders[self::PROPERTY_PREFIX.$key] = $value;
|
||||
}
|
||||
|
||||
return $encodedHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array [[headers], [properties]].
|
||||
*/
|
||||
public static function decode(array $headers = []): array
|
||||
{
|
||||
$encodedHeaders = [];
|
||||
$encodedProperties = [];
|
||||
$prefixLength = strlen(self::PROPERTY_PREFIX);
|
||||
|
||||
// separate headers/properties
|
||||
foreach ($headers as $key => $value) {
|
||||
if (0 === strpos($key, self::PROPERTY_PREFIX)) {
|
||||
$encodedProperties[substr($key, $prefixLength)] = $value;
|
||||
} else {
|
||||
$encodedHeaders[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$decodedHeaders = self::doDecode($encodedHeaders);
|
||||
$decodedProperties = self::doDecode($encodedProperties);
|
||||
|
||||
return [$decodedHeaders, $decodedProperties];
|
||||
}
|
||||
|
||||
private static function doEncode(array $headers = []): array
|
||||
{
|
||||
$encoded = [];
|
||||
|
||||
foreach ($headers as $key => $value) {
|
||||
switch ($type = gettype($value)) {
|
||||
case 'string':
|
||||
$encoded[$key] = (string) $value;
|
||||
$encoded[self::TYPE_PREFIX.$key] = self::TYPE_STRING;
|
||||
|
||||
break;
|
||||
case 'integer':
|
||||
$encoded[$key] = (string) $value;
|
||||
$encoded[self::TYPE_PREFIX.$key] = self::TYPE_INT;
|
||||
|
||||
break;
|
||||
case 'double':
|
||||
$encoded[$key] = (string) $value;
|
||||
$encoded[self::TYPE_PREFIX.$key] = self::TYPE_FLOAT;
|
||||
|
||||
break;
|
||||
case 'NULL':
|
||||
$encoded[$key] = '';
|
||||
$encoded[self::TYPE_PREFIX.$key] = self::TYPE_NULL;
|
||||
|
||||
break;
|
||||
case 'boolean':
|
||||
$encoded[$key] = $value ? 'true' : 'false';
|
||||
$encoded[self::TYPE_PREFIX.$key] = self::TYPE_BOOL;
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new \LogicException(sprintf('Value type is not valid: "%s"', $type));
|
||||
}
|
||||
}
|
||||
|
||||
return $encoded;
|
||||
}
|
||||
|
||||
private static function doDecode(array $headers = []): array
|
||||
{
|
||||
$decoded = [];
|
||||
|
||||
foreach ($headers as $key => $value) {
|
||||
// skip type header
|
||||
if (0 === strpos($key, self::TYPE_PREFIX)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// copy value as is if here is no type header
|
||||
if (false == array_key_exists(self::TYPE_PREFIX.$key, $headers)) {
|
||||
$decoded[$key] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($headers[self::TYPE_PREFIX.$key]) {
|
||||
case self::TYPE_STRING:
|
||||
$decoded[$key] = (string) $value;
|
||||
|
||||
break;
|
||||
case self::TYPE_INT:
|
||||
$decoded[$key] = (int) $value;
|
||||
|
||||
break;
|
||||
case self::TYPE_FLOAT:
|
||||
$decoded[$key] = (float) $value;
|
||||
|
||||
break;
|
||||
case self::TYPE_NULL:
|
||||
$decoded[$key] = null;
|
||||
|
||||
break;
|
||||
case self::TYPE_BOOL:
|
||||
$decoded[$key] = 'true' === $value;
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new \LogicException(sprintf('Type is invalid: "%s"', $value));
|
||||
}
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
}
|
174
vendor/enqueue/stomp/StompMessage.php
vendored
Normal file
174
vendor/enqueue/stomp/StompMessage.php
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Enqueue\Stomp;
|
||||
|
||||
use Interop\Queue\Message;
|
||||
use Stomp\Transport\Frame;
|
||||
|
||||
class StompMessage implements Message
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $body;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $properties;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $headers;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $redelivered;
|
||||
|
||||
/**
|
||||
* @var Frame
|
||||
*/
|
||||
private $frame;
|
||||
|
||||
public function __construct(string $body = '', array $properties = [], array $headers = [])
|
||||
{
|
||||
$this->body = $body;
|
||||
$this->properties = $properties;
|
||||
$this->headers = $headers;
|
||||
$this->redelivered = false;
|
||||
}
|
||||
|
||||
public function setBody(string $body): void
|
||||
{
|
||||
$this->body = $body;
|
||||
}
|
||||
|
||||
public function getBody(): string
|
||||
{
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
public function setProperties(array $properties): void
|
||||
{
|
||||
$this->properties = $properties;
|
||||
}
|
||||
|
||||
public function getProperties(): array
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
public function setProperty(string $name, $value): void
|
||||
{
|
||||
if (null === $value) {
|
||||
unset($this->properties[$name]);
|
||||
} else {
|
||||
$this->properties[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function getProperty(string $name, $default = null)
|
||||
{
|
||||
return array_key_exists($name, $this->properties) ? $this->properties[$name] : $default;
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers): void
|
||||
{
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
public function getHeaders(): array
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
public function setHeader(string $name, $value): void
|
||||
{
|
||||
if (null === $value) {
|
||||
unset($this->headers[$name]);
|
||||
} else {
|
||||
$this->headers[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function getHeader(string $name, $default = null)
|
||||
{
|
||||
return array_key_exists($name, $this->headers) ? $this->headers[$name] : $default;
|
||||
}
|
||||
|
||||
public function isPersistent(): bool
|
||||
{
|
||||
return $this->getHeader('persistent', false);
|
||||
}
|
||||
|
||||
public function setPersistent(bool $persistent): void
|
||||
{
|
||||
$this->setHeader('persistent', $persistent);
|
||||
}
|
||||
|
||||
public function isRedelivered(): bool
|
||||
{
|
||||
return $this->redelivered;
|
||||
}
|
||||
|
||||
public function setRedelivered(bool $redelivered): void
|
||||
{
|
||||
$this->redelivered = $redelivered;
|
||||
}
|
||||
|
||||
public function setCorrelationId(string $correlationId = null): void
|
||||
{
|
||||
$this->setHeader('correlation_id', (string) $correlationId);
|
||||
}
|
||||
|
||||
public function getCorrelationId(): ?string
|
||||
{
|
||||
return $this->getHeader('correlation_id');
|
||||
}
|
||||
|
||||
public function setMessageId(string $messageId = null): void
|
||||
{
|
||||
$this->setHeader('message_id', (string) $messageId);
|
||||
}
|
||||
|
||||
public function getMessageId(): ?string
|
||||
{
|
||||
return $this->getHeader('message_id');
|
||||
}
|
||||
|
||||
public function getTimestamp(): ?int
|
||||
{
|
||||
$value = $this->getHeader('timestamp');
|
||||
|
||||
return null === $value ? null : (int) $value;
|
||||
}
|
||||
|
||||
public function setTimestamp(int $timestamp = null): void
|
||||
{
|
||||
$this->setHeader('timestamp', $timestamp);
|
||||
}
|
||||
|
||||
public function getFrame(): ?Frame
|
||||
{
|
||||
return $this->frame;
|
||||
}
|
||||
|
||||
public function setFrame(Frame $frame = null): void
|
||||
{
|
||||
$this->frame = $frame;
|
||||
}
|
||||
|
||||
public function setReplyTo(string $replyTo = null): void
|
||||
{
|
||||
$this->setHeader('reply-to', $replyTo);
|
||||
}
|
||||
|
||||
public function getReplyTo(): ?string
|
||||
{
|
||||
return $this->getHeader('reply-to');
|
||||
}
|
||||
}
|
89
vendor/enqueue/stomp/StompProducer.php
vendored
Normal file
89
vendor/enqueue/stomp/StompProducer.php
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Enqueue\Stomp;
|
||||
|
||||
use Interop\Queue\Destination;
|
||||
use Interop\Queue\Exception\InvalidDestinationException;
|
||||
use Interop\Queue\Exception\InvalidMessageException;
|
||||
use Interop\Queue\Exception\PriorityNotSupportedException;
|
||||
use Interop\Queue\Message;
|
||||
use Interop\Queue\Producer;
|
||||
use Stomp\Client;
|
||||
use Stomp\Transport\Message as StompLibMessage;
|
||||
|
||||
class StompProducer implements Producer
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $stomp;
|
||||
|
||||
/**
|
||||
* @param Client $stomp
|
||||
*/
|
||||
public function __construct(Client $stomp)
|
||||
{
|
||||
$this->stomp = $stomp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StompDestination $destination
|
||||
* @param StompMessage $message
|
||||
*/
|
||||
public function send(Destination $destination, Message $message): void
|
||||
{
|
||||
InvalidDestinationException::assertDestinationInstanceOf($destination, StompDestination::class);
|
||||
InvalidMessageException::assertMessageInstanceOf($message, StompMessage::class);
|
||||
|
||||
$headers = array_merge($message->getHeaders(), $destination->getHeaders());
|
||||
$headers = StompHeadersEncoder::encode($headers, $message->getProperties());
|
||||
|
||||
$stompMessage = new StompLibMessage($message->getBody(), $headers);
|
||||
|
||||
$this->stomp->send($destination->getQueueName(), $stompMessage);
|
||||
}
|
||||
|
||||
public function setDeliveryDelay(int $deliveryDelay = null): Producer
|
||||
{
|
||||
if (null === $deliveryDelay) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \LogicException('Not implemented');
|
||||
}
|
||||
|
||||
public function getDeliveryDelay(): ?int
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setPriority(int $priority = null): Producer
|
||||
{
|
||||
if (null === $priority) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw PriorityNotSupportedException::providerDoestNotSupportIt();
|
||||
}
|
||||
|
||||
public function getPriority(): ?int
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setTimeToLive(int $timeToLive = null): Producer
|
||||
{
|
||||
if (null === $timeToLive) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \LogicException('Not implemented');
|
||||
}
|
||||
|
||||
public function getTimeToLive(): ?int
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
42
vendor/enqueue/stomp/composer.json
vendored
Normal file
42
vendor/enqueue/stomp/composer.json
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "enqueue/stomp",
|
||||
"type": "library",
|
||||
"description": "Message Queue Stomp Transport",
|
||||
"keywords": ["messaging", "queue", "stomp"],
|
||||
"homepage": "https://enqueue.forma-pro.com/",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"enqueue/dsn": "^0.9",
|
||||
"stomp-php/stomp-php": "^4",
|
||||
"queue-interop/queue-interop": "^0.7|^0.8",
|
||||
"php-http/guzzle6-adapter": "^1.1",
|
||||
"php-http/client-common": "^1.7@dev",
|
||||
"richardfullmer/rabbitmq-management-api": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~5.4.0",
|
||||
"enqueue/test": "0.9.x-dev",
|
||||
"enqueue/null": "0.9.x-dev",
|
||||
"queue-interop/queue-spec": "^0.6"
|
||||
},
|
||||
"support": {
|
||||
"email": "opensource@forma-pro.com",
|
||||
"issues": "https://github.com/php-enqueue/enqueue-dev/issues",
|
||||
"forum": "https://gitter.im/php-enqueue/Lobby",
|
||||
"source": "https://github.com/php-enqueue/enqueue-dev",
|
||||
"docs": "https://github.com/php-enqueue/enqueue-dev/blob/master/docs/index.md"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Enqueue\\Stomp\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.9.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user