Skip to content

Commit 3980a74

Browse files
authored
Merge pull request #249 from shlinkio/develop
Release 9.6.0
2 parents 27e54e5 + bd7a9c1 commit 3980a74

File tree

67 files changed

+788
-138
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+788
-138
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,3 @@ on:
1010
jobs:
1111
ci:
1212
uses: shlinkio/github-actions/.github/workflows/php-lib-ci.yml@main
13-
with:
14-
coverage-driver: 'xdebug'

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
66

7+
## [9.6.0] - 2025-07-24
8+
### Added
9+
* Add `REAL_TIME_UPDATES_TOPICS` config option.
10+
* Add CORS-related config options.
11+
* Add `TRUSTED_PROXIES` config option.
12+
* Add `REDIRECT_CACHE_VISIBILITY` config option.
13+
* Add `LOGS_FORMAT` config option.
14+
15+
### Changed
16+
* Update to PHPUnit 12
17+
18+
### Deprecated
19+
* *Nothing*
20+
21+
### Removed
22+
* Drop support for shlink-config 3.0
23+
24+
### Fixed
25+
* *Nothing*
26+
27+
728
## [9.5.0] - 2025-01-25
829
### Added
930
* Support shlink-config 4.0

composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@
1616
"laminas/laminas-config-aggregator": "^1.17",
1717
"laminas/laminas-servicemanager": "^4.3 || ^3.23",
1818
"laminas/laminas-stdlib": "^3.20",
19-
"shlinkio/shlink-config": "^4.0 || ^3.4",
19+
"shlinkio/shlink-config": "^4.0",
2020
"symfony/console": "^7.2",
2121
"symfony/filesystem": "^7.2",
2222
"symfony/process": "^7.2",
2323
"webimpress/safe-writer": "^2.2"
2424
},
2525
"require-dev": {
2626
"devster/ubench": "^2.1",
27-
"phpstan/phpstan": "^2.0",
27+
"phpstan/phpstan": "^2.1",
2828
"phpstan/phpstan-phpunit": "^2.0",
29-
"phpunit/phpunit": "^11.5",
29+
"phpunit/phpunit": "^12.0",
3030
"roave/security-advisories": "dev-master",
3131
"shlinkio/php-coding-standard": "~2.4.0",
3232
"symfony/var-dumper": "^7.2"

config/config.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
'SERVER' => [
4242
Config\Option\Server\RuntimeConfigOption::class,
4343
'Memory limit' => Config\Option\Server\MemoryLimitConfigOption::class,
44+
'Logs format' => Config\Option\Server\LogsFormatConfigOption::class,
4445
],
4546
'DATABASE' => [
4647
'Database > Driver' => Config\Option\Database\DatabaseDriverConfigOption::class,
@@ -67,8 +68,11 @@
6768
'URL shortener > Trailing slashes' => Config\Option\UrlShortener\EnableTrailingSlashConfigOption::class,
6869
'URL shortener > Mode' => Config\Option\UrlShortener\ShortUrlModeConfigOption::class,
6970
'GeoLite2 license key' => Config\Option\UrlShortener\GeoLiteLicenseKeyConfigOption::class,
70-
'Redirects > Status code (301/302)' => Config\Option\UrlShortener\RedirectStatusCodeConfigOption::class,
71+
'Redirects > Status code (301/302/307/308)'
72+
=> Config\Option\UrlShortener\RedirectStatusCodeConfigOption::class,
7173
'Redirects > Caching life time' => Config\Option\UrlShortener\RedirectCacheLifeTimeConfigOption::class,
74+
'Redirects > Caching visibility'
75+
=> Config\Option\UrlShortener\RedirectCacheVisibilityConfigOption::class,
7276
],
7377
'TRACKING' => [
7478
'Tracking > Orphan visits tracking' => Config\Option\Tracking\OrphanVisitsTrackingConfigOption::class,
@@ -86,7 +90,7 @@
8690
'Redirects > Invalid short URL' => Config\Option\Redirect\InvalidShortUrlRedirectConfigOption::class,
8791
'Redirects > Regular 404' => Config\Option\Redirect\Regular404RedirectConfigOption::class,
8892
],
89-
'QR CODES' => [
93+
'QR CODES [DEPRECATED]' => [
9094
'QR codes > Default size' => Config\Option\QrCode\DefaultSizeConfigOption::class,
9195
'QR codes > Default margin' => Config\Option\QrCode\DefaultMarginConfigOption::class,
9296
'QR codes > Default format' => Config\Option\QrCode\DefaultFormatConfigOption::class,
@@ -102,11 +106,17 @@
102106
'Robots.txt > allow all' => Config\Option\Robots\RobotsAllowAllShortUrlsConfigOption::class,
103107
'Robots.txt > user agents' => Config\Option\Robots\RobotsUserAgentsConfigOption::class,
104108
],
109+
'CORS' => [
110+
'CORS > Allow origin' => Config\Option\Cors\CorsAllowOriginConfigOption::class,
111+
'CORS > Allow credentials' => Config\Option\Cors\CorsAllowCredentialsConfigOption::class,
112+
'CORS > Max age' => Config\Option\Cors\CorsMaxAgeConfigOption::class,
113+
],
105114
'APPLICATION' => [
106115
'Delete short URLs > Visits threshold' => Config\Option\Visit\VisitsThresholdConfigOption::class,
107116
'Base path' => Config\Option\BasePathConfigOption::class,
108117
'Timezone' => Config\Option\TimezoneConfigOption::class,
109118
'Cache > namespace' => Config\Option\Cache\CacheNamespaceConfigOption::class,
119+
'Trusted proxies' => Config\Option\TrustedProxiesConfigOption::class,
110120
],
111121
'INTEGRATIONS' => [
112122
'Redis > servers' => Config\Option\Redis\RedisServersConfigOption::class,
@@ -127,12 +137,14 @@
127137
'Matomo > Server URL' => Config\Option\Matomo\MatomoBaseUrlConfigOption::class,
128138
'Matomo > Site ID' => Config\Option\Matomo\MatomoSiteIdConfigOption::class,
129139
'Matomo > API token' => Config\Option\Matomo\MatomoApiTokenConfigOption::class,
140+
'Real-time updates > topics' => Config\Option\RealTimeUpdates\RealTimeUpdatesTopicsConfigOption::class,
130141
],
131142
],
132143

133144
'factories' => [
134145
Config\Option\Server\RuntimeConfigOption::class => InvokableFactory::class,
135146
Config\Option\Server\MemoryLimitConfigOption::class => InvokableFactory::class,
147+
Config\Option\Server\LogsFormatConfigOption::class => InvokableFactory::class,
136148
Config\Option\BasePathConfigOption::class => InvokableFactory::class,
137149
Config\Option\TimezoneConfigOption::class => InvokableFactory::class,
138150
Config\Option\Cache\CacheNamespaceConfigOption::class => InvokableFactory::class,
@@ -187,6 +199,11 @@
187199
Config\Option\Tracking\DisableUaTrackingConfigOption::class => InvokableFactory::class,
188200
Config\Option\UrlShortener\RedirectStatusCodeConfigOption::class => InvokableFactory::class,
189201
Config\Option\UrlShortener\RedirectCacheLifeTimeConfigOption::class => InvokableFactory::class,
202+
Config\Option\UrlShortener\RedirectCacheVisibilityConfigOption::class => InvokableFactory::class,
203+
Config\Option\RealTimeUpdates\RealTimeUpdatesTopicsConfigOption::class => InvokableFactory::class,
204+
Config\Option\Cors\CorsAllowOriginConfigOption::class => InvokableFactory::class,
205+
Config\Option\Cors\CorsAllowCredentialsConfigOption::class => InvokableFactory::class,
206+
Config\Option\Cors\CorsMaxAgeConfigOption::class => InvokableFactory::class,
190207
Config\Option\QrCode\DefaultSizeConfigOption::class => InvokableFactory::class,
191208
Config\Option\QrCode\DefaultMarginConfigOption::class => InvokableFactory::class,
192209
Config\Option\QrCode\DefaultFormatConfigOption::class => InvokableFactory::class,

src/Command/InitCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
class InitCommand extends Command
2020
{
21-
public const NAME = 'init';
21+
public const string NAME = 'init';
2222

2323
private readonly CLIOption $skipInitDb;
2424
private readonly CLIOption $clearDbCache;

src/Command/InstallCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
class InstallCommand extends AbstractInstallCommand
88
{
9-
public const NAME = 'install';
9+
public const string NAME = 'install';
1010

1111
protected function configure(): void
1212
{

src/Command/SetOptionCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
class SetOptionCommand extends Command
2929
{
30-
public const NAME = 'set-option';
30+
public const string NAME = 'set-option';
3131

3232
private array $groups;
3333
private string $generatedConfigPath;

src/Command/UpdateCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
class UpdateCommand extends AbstractInstallCommand
88
{
9-
public const NAME = 'update';
9+
public const string NAME = 'update';
1010

1111
protected function configure(): void
1212
{
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Shlinkio\Shlink\Installer\Config\Option\Cors;
6+
7+
use Shlinkio\Shlink\Installer\Config\Option\BaseConfigOption;
8+
use Symfony\Component\Console\Style\StyleInterface;
9+
10+
class CorsAllowCredentialsConfigOption extends BaseConfigOption
11+
{
12+
public function getEnvVar(): string
13+
{
14+
return 'CORS_ALLOW_CREDENTIALS';
15+
}
16+
17+
public function ask(StyleInterface $io, array $currentOptions): bool
18+
{
19+
return $io->confirm(
20+
'Do you want browsers to forward credentials to your Shlink server during CORS requests?',
21+
default: false,
22+
);
23+
}
24+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Shlinkio\Shlink\Installer\Config\Option\Cors;
6+
7+
use Shlinkio\Shlink\Installer\Config\Option\BaseConfigOption;
8+
use Symfony\Component\Console\Style\StyleInterface;
9+
10+
class CorsAllowOriginConfigOption extends BaseConfigOption
11+
{
12+
public function getEnvVar(): string
13+
{
14+
return 'CORS_ALLOW_ORIGIN';
15+
}
16+
17+
public function ask(StyleInterface $io, array $currentOptions): string
18+
{
19+
$answer = $io->choice(
20+
'How do you want Shlink to determine which origins are allowed for CORS requests?',
21+
[
22+
'*' => 'All hosts are implicitly allowed (Access-Control-Allow-Origin is set to "*")',
23+
'<origin>' =>
24+
'All hosts are explicitly allowed (Access-Control-Allow-Origin is set to the value in request\'s '
25+
. 'Origin header)',
26+
'allowlist' => 'Provide a list of hosts that are allowed',
27+
],
28+
'*',
29+
);
30+
31+
return $answer !== 'allowlist' ? $answer : $io->ask(
32+
'Provide a comma-separated list of origins that should be allowed to perform CORS requests to Shlink',
33+
);
34+
}
35+
}

0 commit comments

Comments
 (0)