mirror of
https://github.com/shlinkio/shlink.git
synced 2026-10-16 22:01:58 -05:00
Merge pull request #2672 from acelaya-forks/mercure-1-support
Add support for Mercure 1.0
This commit is contained in:
19 files changed
+427
-241
No files matched your search
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
* [#2671](https://github.com/shlinkio/shlink/issues/2671) Add support for Mercure 1.0.
|
||||
|
||||
### Changed
|
||||
* *Nothing*
|
||||
|
||||
### Deprecated
|
||||
* *Nothing*
|
||||
|
||||
### Removed
|
||||
* *Nothing*
|
||||
|
||||
### Fixed
|
||||
* *Nothing*
|
||||
|
||||
|
||||
## [5.1.7] - 2026-09-21
|
||||
### Added
|
||||
* *Nothing*
|
||||
|
||||
+2
-2
@@ -42,11 +42,11 @@
|
||||
"pagerfanta/core": "^3.8",
|
||||
"ramsey/uuid": "^4.9",
|
||||
"shlinkio/doctrine-specification": "^2.3",
|
||||
"shlinkio/shlink-common": "^9.0.2",
|
||||
"shlinkio/shlink-common": "dev-main#7e5d108 as 9.1.0",
|
||||
"shlinkio/shlink-config": "^4.1.0",
|
||||
"shlinkio/shlink-event-dispatcher": "^4.4.0",
|
||||
"shlinkio/shlink-importer": "^5.8",
|
||||
"shlinkio/shlink-installer": "^10.1",
|
||||
"shlinkio/shlink-installer": "dev-develop#af7d57d as 10.2.0",
|
||||
"shlinkio/shlink-ip-geolocation": "^5.0.0",
|
||||
"shlinkio/shlink-json": "^1.3",
|
||||
"spiral/roadrunner": "^2025.1",
|
||||
|
||||
@@ -40,6 +40,7 @@ return [
|
||||
Option\Mercure\MercurePublicUrlConfigOption::class,
|
||||
Option\Mercure\MercureInternalUrlConfigOption::class,
|
||||
Option\Mercure\MercureJwtSecretConfigOption::class,
|
||||
Option\Mercure\MercureVersionConfigOption::class,
|
||||
Option\UrlShortener\GeoLiteLicenseKeyConfigOption::class,
|
||||
Option\UrlShortener\RedirectStatusCodeConfigOption::class,
|
||||
Option\UrlShortener\RedirectCacheLifeTimeConfigOption::class,
|
||||
|
||||
@@ -16,6 +16,7 @@ return [
|
||||
'internal_hub_url' => EnvVars::MERCURE_INTERNAL_HUB_URL->loadFromEnv(),
|
||||
'jwt_secret' => EnvVars::MERCURE_JWT_SECRET->loadFromEnv(),
|
||||
'jwt_issuer' => 'Shlink',
|
||||
'version' => EnvVars::MERCURE_VERSION->loadFromEnv(),
|
||||
],
|
||||
|
||||
'dependencies' => [
|
||||
|
||||
@@ -64,6 +64,7 @@ return [
|
||||
EnvVars::MERCURE_PUBLIC_HUB_URL->value => 'http://localhost:8002',
|
||||
EnvVars::MERCURE_INTERNAL_HUB_URL->value => 'http://shlink_mercure_proxy',
|
||||
EnvVars::MERCURE_JWT_SECRET->value => 'mercure_jwt_key_long_enough_to_avoid_error',
|
||||
EnvVars::MERCURE_VERSION->value => 'stable',
|
||||
|
||||
// RabbitMQ
|
||||
EnvVars::RABBITMQ_ENABLED->value => true,
|
||||
|
||||
+16
-1
@@ -30,6 +30,7 @@ services:
|
||||
- shlink_redis
|
||||
- shlink_redis_acl
|
||||
- shlink_mercure
|
||||
- shlink_mercure_0
|
||||
- shlink_mercure_proxy
|
||||
- shlink_rabbitmq
|
||||
- shlink_matomo
|
||||
@@ -58,6 +59,7 @@ services:
|
||||
- shlink_redis
|
||||
- shlink_redis_acl
|
||||
- shlink_mercure
|
||||
- shlink_mercure_0
|
||||
- shlink_mercure_proxy
|
||||
- shlink_rabbitmq
|
||||
- shlink_matomo
|
||||
@@ -87,6 +89,7 @@ services:
|
||||
- shlink_redis
|
||||
- shlink_redis_acl
|
||||
- shlink_mercure
|
||||
- shlink_mercure_0
|
||||
- shlink_mercure_proxy
|
||||
- shlink_rabbitmq
|
||||
- shlink_matomo
|
||||
@@ -175,9 +178,21 @@ services:
|
||||
|
||||
shlink_mercure:
|
||||
container_name: shlink_mercure
|
||||
image: dunglas/mercure:v0.18
|
||||
image: dunglas/mercure:v1
|
||||
ports:
|
||||
- "3080:80"
|
||||
environment:
|
||||
SERVER_NAME: ":80"
|
||||
MERCURE_PUBLISHER_JWT_KEY: mercure_jwt_key_long_enough_to_avoid_error
|
||||
MERCURE_SUBSCRIBER_JWT_KEY: mercure_jwt_key_long_enough_to_avoid_error
|
||||
MERCURE_TRUSTED_ISSUERS: Shlink # Value of the JWT iss claim
|
||||
MERCURE_EXTRA_DIRECTIVES: "cors_origins https://app.shlink.io http://localhost:3000 http://127.0.0.1:3000 http://localhost:3002 http://127.0.0.1:3002 http://localhost:3005 http://127.0.0.1:3005"
|
||||
|
||||
shlink_mercure_0:
|
||||
container_name: shlink_mercure_0
|
||||
image: dunglas/mercure:v0
|
||||
ports:
|
||||
- "3081:80"
|
||||
environment:
|
||||
SERVER_NAME: ":80"
|
||||
MERCURE_PUBLISHER_JWT_KEY: mercure_jwt_key_long_enough_to_avoid_error
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
"jwtExpiration": {
|
||||
"type": "string",
|
||||
"description": "The date (in ISO-8601 format) in which the JWT will expire"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"enum": ["legacy", "stable"],
|
||||
"description": "Indicates the version of the mercure hub that has been configured, so that consumers know how to subscribe"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,8 @@
|
||||
"example": {
|
||||
"mercureHubUrl": "https://example.com/.well-known/mercure",
|
||||
"jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTaGxpbmsiLCJpYXQiOjE1ODY2ODY3MzIsImV4cCI6MTU4Njk0NTkzMiwibWVyY3VyZSI6eyJzdWJzY3JpYmUiOltdfX0.P-519lgU7dFz0bbNlRG1CXyqugGbaHon4kw6fu4QBdQ",
|
||||
"jwtExpiration": "2020-04-15T12:18:52+02:00"
|
||||
"jwtExpiration": "2020-04-15T12:18:52+02:00",
|
||||
"version": "stable"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+230
-80
@@ -522,18 +522,6 @@ code = "mixed-operand"
|
||||
message = "Cannot reliably increment a `mixed` operand."
|
||||
count = 2
|
||||
|
||||
[[issues]]
|
||||
file = "module/CLI/test/RedirectRule/RedirectRuleHandlerTest.php"
|
||||
code = "redundant-comparison"
|
||||
message = "Redundant `<` comparison: left-hand side is always less than right-hand side."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/CLI/test/RedirectRule/RedirectRuleHandlerTest.php"
|
||||
code = "redundant-logical-operation"
|
||||
message = "Redundant `&&` operation: left operand is always truthy and right operand is evaluated."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/CLI/test/Util/CliTestUtils.php"
|
||||
code = "invalid-return-statement"
|
||||
@@ -684,6 +672,66 @@ code = "possibly-static-access-on-interface"
|
||||
message = "Potential static method call on interface `BackedEnum` via `class-string`."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20230211171904.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20230303164233.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20230303164233.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::dropIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240220214031.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Column::getType`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240220214031.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Column::setType`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240220214031.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::modifyColumn`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240224115725.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::createTable`.'
|
||||
count = 2
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240224115725.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::dropTable`.'
|
||||
count = 3
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240224115725.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addColumn`.'
|
||||
count = 9
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240224115725.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addForeignKeyConstraint`.'
|
||||
count = 3
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240224115725.php"
|
||||
code = "deprecated-method"
|
||||
@@ -696,12 +744,72 @@ code = "mixed-assignment"
|
||||
message = "Assigning `mixed` type to a variable may lead to unexpected behavior."
|
||||
count = 2
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240227080629.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::createTable`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240227080629.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::dropTable`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240227080629.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addColumn`.'
|
||||
count = 4
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240227080629.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addForeignKeyConstraint`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240227080629.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addUniqueIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240227080629.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::setPrimaryKey`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240306132518.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::createTable`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240306132518.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::dropTable`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240306132518.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addColumn`.'
|
||||
count = 5
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240306132518.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addForeignKeyConstraint`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240306132518.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addUniqueIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240306132518.php"
|
||||
code = "deprecated-method"
|
||||
@@ -732,6 +840,30 @@ code = "mixed-operand"
|
||||
message = "Left operand in `>` comparison has `mixed` type."
|
||||
count = 2
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240331111103.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::createTable`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240331111103.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::dropTable`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240331111103.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addColumn`.'
|
||||
count = 4
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240331111103.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addUniqueIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20240331111103.php"
|
||||
code = "deprecated-method"
|
||||
@@ -780,12 +912,96 @@ code = "mixed-assignment"
|
||||
message = "Assigning `mixed` type to a variable may lead to unexpected behavior."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20241124112257.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addColumn`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20241124112257.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::dropColumn`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20241125213106.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addUniqueIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20241125213106.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::dropIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20241212131058.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::createTable`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20241212131058.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Schema::dropTable`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20241212131058.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addColumn`.'
|
||||
count = 7
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20241212131058.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addIndex`.'
|
||||
count = 2
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20241212131058.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::setPrimaryKey`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20250215100756.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::dropIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20250722060208.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Column::setNotnull`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20260524105410.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addColumn`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20260524105410.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::addIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20260524105410.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::dropColumn`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20260524105410.php"
|
||||
code = "deprecated-method"
|
||||
message = 'Call to deprecated method: `Doctrine\DBAL\Schema\Table::dropIndex`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/migrations/Version20260607082210.php"
|
||||
code = "mixed-argument"
|
||||
@@ -1065,7 +1281,7 @@ count = 2
|
||||
[[issues]]
|
||||
file = "module/Core/src/Domain/Repository/DomainRepository.php"
|
||||
code = "mixed-argument"
|
||||
message = 'Invalid argument type for argument #2 of `Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryTrait::applySpecification`: expected `Happyr\DoctrineSpecification\Filter\Filter|Happyr\DoctrineSpecification\Query\QueryModifier`, but found `mixed`.'
|
||||
message = 'Invalid argument type for argument #2 of `Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryTrait::applySpecification`: expected `Happyr\DoctrineSpecification\Filter\Filter|Happyr\DoctrineSpecification\Query\QueryModifier|null`, but found `mixed`.'
|
||||
count = 2
|
||||
|
||||
[[issues]]
|
||||
@@ -1386,12 +1602,6 @@ code = "mixed-assignment"
|
||||
message = "Assigning `mixed` type to a variable may lead to unexpected behavior."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/ShortUrl/Repository/ShortUrlListRepository.php"
|
||||
code = "possibly-null-argument"
|
||||
message = 'Argument #2 of method `Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryTrait::applySpecification` is possibly `null`, but parameter type `Happyr\DoctrineSpecification\Filter\Filter|Happyr\DoctrineSpecification\Query\QueryModifier` does not accept it.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/ShortUrl/Repository/ShortUrlRepository.php"
|
||||
code = "mixed-assignment"
|
||||
@@ -1422,12 +1632,6 @@ code = "mixed-return-statement"
|
||||
message = 'Could not infer a precise return type for function `Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlRepository::findOne`. Saw type `mixed`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/ShortUrl/Repository/ShortUrlRepository.php"
|
||||
code = "possibly-null-argument"
|
||||
message = 'Argument #2 of method `Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryTrait::applySpecification` is possibly `null`, but parameter type `Happyr\DoctrineSpecification\Filter\Filter|Happyr\DoctrineSpecification\Query\QueryModifier` does not accept it.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/ShortUrl/Resolver/PersistenceShortUrlRelationResolver.php"
|
||||
code = "less-specific-return-statement"
|
||||
@@ -1524,12 +1728,6 @@ code = "mixed-return-statement"
|
||||
message = 'Could not infer a precise return type for function `Shlinkio\Shlink\Core\Tag\Paginator\Adapter\TagsPaginatorAdapter::getSlice`. Saw type `mixed`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/Tag/Repository/TagRepository.php"
|
||||
code = "mixed-argument"
|
||||
message = 'Invalid argument type for argument #1 of `Doctrine\DBAL\Connection::quote`: expected `string`, but found `mixed`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/Tag/Repository/TagRepository.php"
|
||||
code = "mixed-argument"
|
||||
@@ -1638,12 +1836,6 @@ code = "mixed-argument"
|
||||
message = 'Invalid argument type for argument #5 of `Shlinkio\Shlink\Core\Visit\Model\WithDomainVisitsParams::__construct`: expected `null|string`, but found `mixed`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/Visit/Repository/ShortUrlVisitsCountRepository.php"
|
||||
code = "possibly-null-argument"
|
||||
message = 'Argument #2 of method `Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryTrait::applySpecification` is possibly `null`, but parameter type `Happyr\DoctrineSpecification\Filter\Filter|Happyr\DoctrineSpecification\Query\QueryModifier` does not accept it.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/Visit/Repository/VisitDeleterRepository.php"
|
||||
code = "mixed-return-statement"
|
||||
@@ -1746,12 +1938,6 @@ code = "mixed-return-statement"
|
||||
message = 'Could not infer a precise return type for function `Shlinkio\Shlink\Core\Visit\Repository\VisitRepository::resolveVisitsWithNativeQuery`. Saw type `mixed`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/Visit/Repository/VisitRepository.php"
|
||||
code = "possibly-null-argument"
|
||||
message = 'Argument #2 of method `Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryTrait::applySpecification` is possibly `null`, but parameter type `Happyr\DoctrineSpecification\Filter\Filter|Happyr\DoctrineSpecification\Query\QueryModifier` does not accept it.'
|
||||
count = 3
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/src/Visit/RequestTracker.php"
|
||||
code = "mixed-assignment"
|
||||
@@ -2028,12 +2214,6 @@ code = "less-specific-argument"
|
||||
message = 'Argument type mismatch for argument #1 of `ShlinkioTest\Shlink\Core\RedirectRule\Entity\ShortUrlRedirectRuleTest::createRule`: expected `Doctrine\Common\Collections\ArrayCollection<int, Shlinkio\Shlink\Core\RedirectRule\Entity\RedirectCondition>`, but provided type `Doctrine\Common\Collections\ArrayCollection<array-key, mixed>` is less specific.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/test/ShortUrl/Helper/ShortCodeUniquenessHelperTest.php"
|
||||
code = "redundant-comparison"
|
||||
message = "Redundant `<` comparison: left-hand side is always less than right-hand side."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Core/test/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapterTest.php"
|
||||
code = "less-specific-nested-argument-type"
|
||||
@@ -2106,30 +2286,6 @@ code = "string-member-selector"
|
||||
message = "This member selector uses a non-literal string type (`string`); its specific value cannot be statically determined."
|
||||
count = 3
|
||||
|
||||
[[issues]]
|
||||
file = "module/Rest/src/Action/MercureInfoAction.php"
|
||||
code = "mixed-argument"
|
||||
message = 'Invalid argument type for argument #1 of `Cake\Chronos\Chronos::addDays`: expected `int`, but found `nonnull`.'
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Rest/src/Action/MercureInfoAction.php"
|
||||
code = "mixed-argument"
|
||||
message = "Invalid argument type for argument #2 of `sprintf`: expected `Stringable|null|scalar`, but found `nonnull`."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Rest/src/Action/MercureInfoAction.php"
|
||||
code = "mixed-assignment"
|
||||
message = "Assigning `mixed` type to a variable may lead to unexpected behavior."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Rest/src/Action/MercureInfoAction.php"
|
||||
code = "mixed-assignment"
|
||||
message = "Assigning `nonnull` type to a variable may lead to unexpected behavior."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Rest/src/Action/RedirectRule/SetRedirectRulesAction.php"
|
||||
code = "invalid-type-cast"
|
||||
@@ -2530,7 +2686,7 @@ count = 3
|
||||
file = "module/Rest/test/Action/MercureInfoActionTest.php"
|
||||
code = "mixed-array-access"
|
||||
message = "Unsafe array access on type `mixed`."
|
||||
count = 2
|
||||
count = 3
|
||||
|
||||
[[issues]]
|
||||
file = "module/Rest/test/Action/MercureInfoActionTest.php"
|
||||
@@ -2669,9 +2825,3 @@ file = "module/Rest/test/Middleware/ShortUrl/ShortUrlOptionsPayloadMiddlewareTes
|
||||
code = "invalid-type-cast"
|
||||
message = "Object of type `object` cast to `array`. Property visibility (public, protected, private) affects the resulting array."
|
||||
count = 1
|
||||
|
||||
[[issues]]
|
||||
file = "module/Rest/test/Service/ApiKeyServiceTest.php"
|
||||
code = "redundant-comparison"
|
||||
message = "Redundant `<` comparison: left-hand side is always less than right-hand side."
|
||||
count = 1
|
||||
@@ -43,23 +43,23 @@ class ListApiKeysTest extends CliTestCase
|
||||
OUT;
|
||||
|
||||
yield 'no flags' => [[], <<<OUT
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| Name | Is enabled | Expiration date | Roles |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| valid_api_key | +++ | - | Admin |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| disabled_api_key | --- | - | Admin |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| expired_api_key | --- | {$expiredApiKeyDate} | Admin |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| author_api_key | +++ | - | Author only |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| domain_api_key | +++ | - | Domain only: example.com |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| no_orphans_api_key | +++ | - | No orphan visits |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| Name | Is enabled | Expiration date | Roles |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| valid_api_key | +++ | - | Admin |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| disabled_api_key | --- | - | Admin |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| expired_api_key | --- | {$expiredApiKeyDate} | Admin |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| author_api_key | +++ | - | Author only |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| domain_api_key | +++ | - | Domain only: example.com |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
| no_orphans_api_key | +++ | - | No orphan visits |
|
||||
+--------------------+------------+---------------------------+--------------------------+
|
||||
|
||||
OUT];
|
||||
OUT];
|
||||
yield '-e' => [['-e'], $enabledOnlyOutput];
|
||||
yield '--enabled-only' => [['--enabled-only'], $enabledOnlyOutput];
|
||||
}
|
||||
|
||||
@@ -21,79 +21,79 @@ class ListShortUrlsTest extends CliTestCase
|
||||
public static function provideFlagsAndOutput(): iterable
|
||||
{
|
||||
yield 'no flags' => [[], <<<OUTPUT
|
||||
+--------------------+---------------+-------------------------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+---------------+-------------------------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| ghi789 | | http://example.com/ghi789 | https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/ | 2019-01-01T00:00:30+00:00 | 0 |
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
| abc123 | My cool title | http://s.test/abc123 | https://shlink.io | 2018-05-01T00:00:00+00:00 | 3 |
|
||||
| ghi789 | | http://s.test/ghi789 | https://shlink.io/documentation/ | 2018-05-01T00:00:00+00:00 | 2 |
|
||||
+--------------------+---------------+-------------------------------------------+---------------------------- Page 1 of 1 ------------------------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
+--------------------+---------------+-------------------------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+---------------+-------------------------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| ghi789 | | http://example.com/ghi789 | https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/ | 2019-01-01T00:00:30+00:00 | 0 |
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
| abc123 | My cool title | http://s.test/abc123 | https://shlink.io | 2018-05-01T00:00:00+00:00 | 3 |
|
||||
| ghi789 | | http://s.test/ghi789 | https://shlink.io/documentation/ | 2018-05-01T00:00:00+00:00 | 2 |
|
||||
+--------------------+---------------+-------------------------------------------+---------------------------- Page 1 of 1 ------------------------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
yield 'start date' => [['--start-date=2019-01'], <<<OUTPUT
|
||||
+------------+-------+---------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+------------+-------+---------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| ghi789 | | http://example.com/ghi789 | https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/ | 2019-01-01T00:00:30+00:00 | 0 |
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
+------------+-------+---------------------------+-------------------------------------------- Page 1 of 1 --------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
+------------+-------+---------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+------------+-------+---------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| ghi789 | | http://example.com/ghi789 | https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/ | 2019-01-01T00:00:30+00:00 | 0 |
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
+------------+-------+---------------------------+-------------------------------------------- Page 1 of 1 --------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
yield 'end date' => [['-e 2018-12-01'], <<<OUTPUT
|
||||
+--------------------+---------------+-------------------------------------------+----------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+---------------+-------------------------------------------+----------------------------------+---------------------------+--------------+
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
| abc123 | My cool title | http://s.test/abc123 | https://shlink.io | 2018-05-01T00:00:00+00:00 | 3 |
|
||||
| ghi789 | | http://s.test/ghi789 | https://shlink.io/documentation/ | 2018-05-01T00:00:00+00:00 | 2 |
|
||||
+--------------------+---------------+----------------------------------- Page 1 of 1 ------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
+--------------------+---------------+-------------------------------------------+----------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+---------------+-------------------------------------------+----------------------------------+---------------------------+--------------+
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
| abc123 | My cool title | http://s.test/abc123 | https://shlink.io | 2018-05-01T00:00:00+00:00 | 3 |
|
||||
| ghi789 | | http://s.test/ghi789 | https://shlink.io/documentation/ | 2018-05-01T00:00:00+00:00 | 2 |
|
||||
+--------------------+---------------+----------------------------------- Page 1 of 1 ------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
yield 'start and end date' => [['-s 2018-06-20', '--end-date=2019-01-01T00:00:20+00:00'], <<<OUTPUT
|
||||
+--------------------+-------+-------------------------------------------+-----------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+-------+-------------------------------------------+-----------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
+--------------------+-------+-------------------------------------------+----------------------------- Page 1 of 1 -----------------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
+--------------------+-------+-------------------------------------------+-----------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+-------+-------------------------------------------+-----------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
+--------------------+-------+-------------------------------------------+----------------------------- Page 1 of 1 -----------------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
yield 'expired excluded' => [['--exclude-max-visits-reached', '--exclude-past-valid-until'], <<<OUTPUT
|
||||
+--------------------+-------+-------------------------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+-------+-------------------------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| ghi789 | | http://example.com/ghi789 | https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/ | 2019-01-01T00:00:30+00:00 | 0 |
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
+--------------------+-------+-------------------------------------------+-------------------------------- Page 1 of 1 --------------------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
+--------------------+-------+-------------------------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+-------+-------------------------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| ghi789 | | http://example.com/ghi789 | https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/ | 2019-01-01T00:00:30+00:00 | 0 |
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
+--------------------+-------+-------------------------------------------+-------------------------------- Page 1 of 1 --------------------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
yield 'non-default domain' => [['--domain=example.com'], <<<OUTPUT
|
||||
+------------+-------+---------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+------------+-------+---------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| ghi789 | | http://example.com/ghi789 | https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/ | 2019-01-01T00:00:30+00:00 | 0 |
|
||||
+------------+-------+---------------------------+-------------------------------------------- Page 1 of 1 --------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
+------------+-------+---------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+------------+-------+---------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| ghi789 | | http://example.com/ghi789 | https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/ | 2019-01-01T00:00:30+00:00 | 0 |
|
||||
+------------+-------+---------------------------+-------------------------------------------- Page 1 of 1 --------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
yield 'default domain' => [['--domain=DEFAULT'], <<<OUTPUT
|
||||
+------------+---------------+----------------------+-----------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+------------+---------------+----------------------+-----------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
| abc123 | My cool title | http://s.test/abc123 | https://shlink.io | 2018-05-01T00:00:00+00:00 | 3 |
|
||||
| ghi789 | | http://s.test/ghi789 | https://shlink.io/documentation/ | 2018-05-01T00:00:00+00:00 | 2 |
|
||||
+------------+---------------+----------------------+--------------------------------------- Page 1 of 1 -------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
+------------+---------------+----------------------+-----------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+------------+---------------+----------------------+-----------------------------------------------------------------------------------------------------+---------------------------+--------------+
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| def456 | | http://s.test/def456 | https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/ | 2019-01-01T00:00:10+00:00 | 2 |
|
||||
| abc123 | My cool title | http://s.test/abc123 | https://shlink.io | 2018-05-01T00:00:00+00:00 | 3 |
|
||||
| ghi789 | | http://s.test/ghi789 | https://shlink.io/documentation/ | 2018-05-01T00:00:00+00:00 | 2 |
|
||||
+------------+---------------+----------------------+--------------------------------------- Page 1 of 1 -------------------------------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
yield 'exclude tags' => [['--exclude-tag=foo'], <<<OUTPUT
|
||||
+--------------------+-------+-------------------------------------------+----------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+-------+-------------------------------------------+----------------------------------+---------------------------+--------------+
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
| ghi789 | | http://s.test/ghi789 | https://shlink.io/documentation/ | 2018-05-01T00:00:00+00:00 | 2 |
|
||||
+--------------------+-------+--------------------------------------- Page 1 of 1 --------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
+--------------------+-------+-------------------------------------------+----------------------------------+---------------------------+--------------+
|
||||
| Short Code | Title | Short URL | Long URL | Date created | Visits count |
|
||||
+--------------------+-------+-------------------------------------------+----------------------------------+---------------------------+--------------+
|
||||
| custom | | http://s.test/custom | https://shlink.io | 2019-01-01T00:00:20+00:00 | 0 |
|
||||
| custom-with-domain | | http://some-domain.com/custom-with-domain | https://google.com | 2018-10-20T00:00:00+00:00 | 0 |
|
||||
| ghi789 | | http://s.test/ghi789 | https://shlink.io/documentation/ | 2018-05-01T00:00:00+00:00 | 2 |
|
||||
+--------------------+-------+--------------------------------------- Page 1 of 1 --------------------------+---------------------------+--------------+
|
||||
OUTPUT];
|
||||
}
|
||||
}
|
||||
@@ -49,8 +49,8 @@ class InitialApiKeyCommandTest extends TestCase
|
||||
yield 'api key created, verbose' => [ApiKey::create(), true, ''];
|
||||
yield 'no api key created, no verbose' => [null, false, ''];
|
||||
yield 'no api key created, verbose' => [null, true, <<<OUT
|
||||
Other API keys already exist. Initial API key creation skipped.
|
||||
Other API keys already exist. Initial API key creation skipped.
|
||||
|
||||
OUT];
|
||||
OUT];
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Config;
|
||||
|
||||
use Shlinkio\Shlink\Common\Mercure\MercureVersion;
|
||||
use Shlinkio\Shlink\Core\Config\Options\ExtraPathMode;
|
||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlMode;
|
||||
|
||||
@@ -41,6 +42,7 @@ enum EnvVars: string
|
||||
case MERCURE_PUBLIC_HUB_URL = 'MERCURE_PUBLIC_HUB_URL';
|
||||
case MERCURE_INTERNAL_HUB_URL = 'MERCURE_INTERNAL_HUB_URL';
|
||||
case MERCURE_JWT_SECRET = 'MERCURE_JWT_SECRET';
|
||||
case MERCURE_VERSION = 'MERCURE_VERSION';
|
||||
case RABBITMQ_ENABLED = 'RABBITMQ_ENABLED';
|
||||
case RABBITMQ_HOST = 'RABBITMQ_HOST';
|
||||
case RABBITMQ_PORT = 'RABBITMQ_PORT';
|
||||
@@ -134,6 +136,7 @@ enum EnvVars: string
|
||||
},
|
||||
self::DB_USE_ENCRYPTION => false,
|
||||
self::MERCURE_ENABLED => self::MERCURE_PUBLIC_HUB_URL->existsInEnv(),
|
||||
self::MERCURE_VERSION => MercureVersion::LEGACY->value,
|
||||
self::MERCURE_INTERNAL_HUB_URL => self::MERCURE_PUBLIC_HUB_URL->loadFromEnv(),
|
||||
self::RABBITMQ_ENABLED, self::RABBITMQ_USE_SSL => false,
|
||||
self::RABBITMQ_PORT => 5672,
|
||||
|
||||
@@ -167,8 +167,10 @@ class ShortUrl extends AbstractEntity
|
||||
if (
|
||||
$this->title === null
|
||||
|| $shortUrlEdit->titleWasProvided
|
||||
|| ($this->titleWasAutoResolved
|
||||
&& $shortUrlEdit->titleWasAutoResolved)
|
||||
|| (
|
||||
$this->titleWasAutoResolved
|
||||
&& $shortUrlEdit->titleWasAutoResolved
|
||||
)
|
||||
) {
|
||||
$this->title = $shortUrlEdit->title;
|
||||
$this->titleWasAutoResolved = $shortUrlEdit->titleWasAutoResolved;
|
||||
|
||||
@@ -43,34 +43,34 @@ class RobotsActionTest extends TestCase
|
||||
public static function provideShortCodes(): iterable
|
||||
{
|
||||
yield 'three short codes' => [['foo', 'bar', 'baz'], new RobotsOptions(), <<<ROBOTS
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
|
||||
User-agent: *
|
||||
Allow: /foo
|
||||
Allow: /bar
|
||||
Allow: /baz
|
||||
Disallow: /
|
||||
ROBOTS];
|
||||
User-agent: *
|
||||
Allow: /foo
|
||||
Allow: /bar
|
||||
Allow: /baz
|
||||
Disallow: /
|
||||
ROBOTS];
|
||||
yield 'five short codes' => [['foo', 'bar', 'some', 'thing', 'baz'], new RobotsOptions(), <<<ROBOTS
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
|
||||
User-agent: *
|
||||
Allow: /foo
|
||||
Allow: /bar
|
||||
Allow: /some
|
||||
Allow: /thing
|
||||
Allow: /baz
|
||||
Disallow: /
|
||||
ROBOTS];
|
||||
User-agent: *
|
||||
Allow: /foo
|
||||
Allow: /bar
|
||||
Allow: /some
|
||||
Allow: /thing
|
||||
Allow: /baz
|
||||
Disallow: /
|
||||
ROBOTS];
|
||||
yield 'no short codes' => [[], new RobotsOptions(), <<<ROBOTS
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
|
||||
User-agent: *
|
||||
Disallow: /
|
||||
ROBOTS];
|
||||
User-agent: *
|
||||
Disallow: /
|
||||
ROBOTS];
|
||||
yield 'three short codes and allow all short urls' => [
|
||||
['foo', 'bar', 'some'],
|
||||
new RobotsOptions(allowAllShortUrls: true),
|
||||
@@ -83,20 +83,20 @@ class RobotsActionTest extends TestCase
|
||||
ROBOTS,
|
||||
];
|
||||
yield 'no short codes and allow all short urls' => [[], new RobotsOptions(allowAllShortUrls: true), <<<ROBOTS
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
|
||||
User-agent: *
|
||||
Disallow: /rest/
|
||||
ROBOTS];
|
||||
User-agent: *
|
||||
Disallow: /rest/
|
||||
ROBOTS];
|
||||
yield 'allow user agents' => [[], new RobotsOptions(userAgents: ['foo', 'bar']), <<<ROBOTS
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
|
||||
User-agent: foo
|
||||
User-agent: bar
|
||||
Disallow: /
|
||||
ROBOTS];
|
||||
User-agent: foo
|
||||
User-agent: bar
|
||||
Disallow: /
|
||||
ROBOTS];
|
||||
}
|
||||
|
||||
private function action(RobotsOptions $options): RobotsAction
|
||||
|
||||
@@ -42,7 +42,7 @@ class MapperBuilderWithCacheDelegatorFactoryTest extends TestCase
|
||||
{
|
||||
putenv(EnvVars::APP_ENV->value . '=' . $env);
|
||||
|
||||
$builder = (new MapperBuilderWithCacheDelegatorFactory())($this->container, '', fn () => $this->baseBuilder);
|
||||
$builder = new MapperBuilderWithCacheDelegatorFactory()($this->container, '', fn () => $this->baseBuilder);
|
||||
$reflection = new ReflectionObject($builder);
|
||||
/** @var Settings $settings */
|
||||
$settings = $reflection->getProperty('settings')->getValue($builder);
|
||||
@@ -56,7 +56,7 @@ class MapperBuilderWithCacheDelegatorFactoryTest extends TestCase
|
||||
{
|
||||
putenv(EnvVars::APP_ENV->value . '=prod');
|
||||
|
||||
$builder = (new MapperBuilderWithCacheDelegatorFactory())($this->container, '', fn () => $this->baseBuilder);
|
||||
$builder = new MapperBuilderWithCacheDelegatorFactory()($this->container, '', fn () => $this->baseBuilder);
|
||||
$reflection = new ReflectionObject($builder);
|
||||
/** @var Settings $settings */
|
||||
$settings = $reflection->getProperty('settings')->getValue($builder);
|
||||
|
||||
@@ -12,6 +12,7 @@ use Mezzio\Router\Middleware\ImplicitOptionsMiddleware;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Shlinkio\Shlink\Common\Doctrine\EntityRepositoryFactory;
|
||||
use Shlinkio\Shlink\Common\Mercure\LcobucciJwtProvider;
|
||||
use Shlinkio\Shlink\Common\Mercure\MercureOptions;
|
||||
use Shlinkio\Shlink\Core\Config;
|
||||
use Shlinkio\Shlink\Core\Domain\DomainService;
|
||||
use Shlinkio\Shlink\Core\RedirectRule;
|
||||
@@ -68,7 +69,7 @@ return [
|
||||
ApiKeyService::class => ['em', ApiKeyRepository::class],
|
||||
|
||||
Action\HealthAction::class => ['em', Config\Options\AppOptions::class],
|
||||
Action\MercureInfoAction::class => [LcobucciJwtProvider::class, 'config.mercure'],
|
||||
Action\MercureInfoAction::class => [LcobucciJwtProvider::class, MercureOptions::class],
|
||||
Action\ShortUrl\CreateShortUrlAction::class => [
|
||||
ShortUrl\UrlShortener::class,
|
||||
ShortUrlDataTransformer::class,
|
||||
|
||||
@@ -9,6 +9,7 @@ use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Shlinkio\Shlink\Common\Mercure\JwtProviderInterface;
|
||||
use Shlinkio\Shlink\Common\Mercure\MercureOptions;
|
||||
use Shlinkio\Shlink\Rest\Exception\MercureException;
|
||||
|
||||
use function sprintf;
|
||||
@@ -20,24 +21,25 @@ class MercureInfoAction extends AbstractRestAction
|
||||
|
||||
public function __construct(
|
||||
private readonly JwtProviderInterface $jwtProvider,
|
||||
private readonly array $mercureConfig,
|
||||
private readonly MercureOptions $mercureOptions,
|
||||
) {}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$hubUrl = $this->mercureConfig['public_hub_url'] ?? null;
|
||||
$hubUrl = $this->mercureOptions->publicHubUrl;
|
||||
if ($hubUrl === null) {
|
||||
throw MercureException::mercureNotConfigured();
|
||||
}
|
||||
|
||||
$days = $this->mercureConfig['jwt_days_duration'] ?? 1;
|
||||
$expiresAt = Chronos::now()->addDays($days);
|
||||
// Make subscription tokens expire in 1 day
|
||||
$expiresAt = Chronos::now()->addDays(1);
|
||||
$jwt = $this->jwtProvider->buildSubscriptionToken($expiresAt);
|
||||
|
||||
return new JsonResponse([
|
||||
'mercureHubUrl' => sprintf('%s/.well-known/mercure', $hubUrl),
|
||||
'token' => $jwt,
|
||||
'jwtExpiration' => $expiresAt->toAtomString(),
|
||||
'version' => $this->mercureOptions->version->value,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,13 @@ use Cake\Chronos\Chronos;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Laminas\Diactoros\ServerRequestFactory;
|
||||
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\Attributes\TestWith;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Mercure\JwtProviderInterface;
|
||||
use Shlinkio\Shlink\Common\Mercure\MercureOptions;
|
||||
use Shlinkio\Shlink\Common\Mercure\MercureVersion;
|
||||
use Shlinkio\Shlink\Rest\Action\MercureInfoAction;
|
||||
use Shlinkio\Shlink\Rest\Exception\MercureException;
|
||||
|
||||
@@ -25,39 +27,29 @@ class MercureInfoActionTest extends TestCase
|
||||
$this->provider = $this->createMock(JwtProviderInterface::class);
|
||||
}
|
||||
|
||||
#[Test, DataProvider('provideNoHostConfigs')]
|
||||
public function throwsExceptionWhenConfigDoesNotHavePublicHost(array $mercureConfig): void
|
||||
#[Test]
|
||||
public function throwsExceptionWhenConfigDoesNotHavePublicHost(): void
|
||||
{
|
||||
$this->provider->expects($this->never())->method('buildSubscriptionToken');
|
||||
|
||||
$action = new MercureInfoAction($this->provider, $mercureConfig);
|
||||
$action = new MercureInfoAction($this->provider, new MercureOptions());
|
||||
|
||||
$this->expectException(MercureException::class);
|
||||
|
||||
$action->handle(ServerRequestFactory::fromGlobals());
|
||||
}
|
||||
|
||||
public static function provideNoHostConfigs(): iterable
|
||||
{
|
||||
yield 'host not defined' => [[]];
|
||||
yield 'host is null' => [['public_hub_url' => null]];
|
||||
}
|
||||
|
||||
public function provideValidConfigs(): iterable
|
||||
{
|
||||
yield 'days not defined' => [['public_hub_url' => 'http://foobar.com']];
|
||||
yield 'days defined' => [['public_hub_url' => 'http://foobar.com', 'jwt_days_duration' => 20]];
|
||||
}
|
||||
|
||||
#[Test, DataProvider('provideDays')]
|
||||
public function returnsExpectedInfoWhenEverythingIsOk(int|null $days): void
|
||||
#[Test]
|
||||
#[TestWith([MercureVersion::LEGACY])]
|
||||
#[TestWith([MercureVersion::STABLE])]
|
||||
public function returnsExpectedInfoWhenEverythingIsOk(MercureVersion $version): void
|
||||
{
|
||||
$this->provider->expects($this->once())->method('buildSubscriptionToken')->willReturn('abc.123');
|
||||
|
||||
$action = new MercureInfoAction($this->provider, [
|
||||
'public_hub_url' => 'http://foobar.com',
|
||||
'jwt_days_duration' => $days,
|
||||
]);
|
||||
$action = new MercureInfoAction($this->provider, new MercureOptions(
|
||||
publicHubUrl: 'http://foobar.com',
|
||||
version: $version,
|
||||
));
|
||||
|
||||
/** @var JsonResponse $resp */
|
||||
$resp = $action->handle(ServerRequestFactory::fromGlobals());
|
||||
@@ -68,15 +60,10 @@ class MercureInfoActionTest extends TestCase
|
||||
self::assertArrayHasKey('token', $payload);
|
||||
self::assertArrayHasKey('jwtExpiration', $payload);
|
||||
self::assertEquals(
|
||||
Chronos::now()->addDays($days ?? 1)->startOfDay(),
|
||||
Chronos::now()->addDays(1)->startOfDay(),
|
||||
Chronos::parse($payload['jwtExpiration'])->startOfDay(),
|
||||
);
|
||||
}
|
||||
|
||||
public static function provideDays(): iterable
|
||||
{
|
||||
yield 'days not defined' => [null];
|
||||
yield 'days defined' => [10];
|
||||
self::assertEquals($version->value, $payload['version']);
|
||||
}
|
||||
|
||||
#[Test, AllowMockObjectsWithoutExpectations]
|
||||
|
||||
Reference in new issue
Block a user