Move env var default values to EnvVars enum

This commit is contained in:
Alejandro Celaya 2024-10-13 12:24:59 +02:00
parent be822646e4
commit 83e8801827
20 changed files with 147 additions and 78 deletions

View file

@ -45,7 +45,7 @@
"ramsey/uuid": "^4.7", "ramsey/uuid": "^4.7",
"shlinkio/doctrine-specification": "^2.1.1", "shlinkio/doctrine-specification": "^2.1.1",
"shlinkio/shlink-common": "^6.3", "shlinkio/shlink-common": "^6.3",
"shlinkio/shlink-config": "dev-main#76a96ee as 3.1", "shlinkio/shlink-config": "dev-main#5e43e96 as 3.1",
"shlinkio/shlink-event-dispatcher": "^4.1", "shlinkio/shlink-event-dispatcher": "^4.1",
"shlinkio/shlink-importer": "^5.3.2", "shlinkio/shlink-importer": "^5.3.2",
"shlinkio/shlink-installer": "^9.2", "shlinkio/shlink-installer": "^9.2",

View file

@ -6,7 +6,7 @@ use Shlinkio\Shlink\Core\Config\EnvVars;
return (static function (): array { return (static function (): array {
$redisServers = EnvVars::REDIS_SERVERS->loadFromEnv(); $redisServers = EnvVars::REDIS_SERVERS->loadFromEnv();
$redis = ['pub_sub_enabled' => $redisServers !== null && EnvVars::REDIS_PUB_SUB_ENABLED->loadFromEnv(false)]; $redis = ['pub_sub_enabled' => $redisServers !== null && EnvVars::REDIS_PUB_SUB_ENABLED->loadFromEnv()];
$cacheRedisBlock = $redisServers === null ? [] : [ $cacheRedisBlock = $redisServers === null ? [] : [
'redis' => [ 'redis' => [
'servers' => $redisServers, 'servers' => $redisServers,
@ -16,7 +16,7 @@ return (static function (): array {
return [ return [
'cache' => [ 'cache' => [
'namespace' => EnvVars::CACHE_NAMESPACE->loadFromEnv('Shlink'), 'namespace' => EnvVars::CACHE_NAMESPACE->loadFromEnv(),
...$cacheRedisBlock, ...$cacheRedisBlock,
], ],
'redis' => $redis, 'redis' => $redis,

View file

@ -23,11 +23,6 @@ return (static function (): array {
$value = $envVar->loadFromEnv(); $value = $envVar->loadFromEnv();
return $value === null ? null : (string) $value; return $value === null ? null : (string) $value;
}; };
$resolveDefaultPort = static fn () => match ($driver) {
'postgres' => '5432',
'mssql' => '1433',
default => '3306',
};
$resolveCharset = static fn () => match ($driver) { $resolveCharset = static fn () => match ($driver) {
// This does not determine charsets or collations in tables or columns, but the charset used in the data // This does not determine charsets or collations in tables or columns, but the charset used in the data
// flowing in the connection, so it has to match what has been set in the database. // flowing in the connection, so it has to match what has been set in the database.
@ -43,11 +38,11 @@ return (static function (): array {
], ],
default => [ default => [
'driver' => $resolveDriver(), 'driver' => $resolveDriver(),
'dbname' => EnvVars::DB_NAME->loadFromEnv('shlink'), 'dbname' => EnvVars::DB_NAME->loadFromEnv(),
'user' => $readCredentialAsString(EnvVars::DB_USER), 'user' => $readCredentialAsString(EnvVars::DB_USER),
'password' => $readCredentialAsString(EnvVars::DB_PASSWORD), 'password' => $readCredentialAsString(EnvVars::DB_PASSWORD),
'host' => EnvVars::DB_HOST->loadFromEnv(EnvVars::DB_UNIX_SOCKET->loadFromEnv()), 'host' => EnvVars::DB_HOST->loadFromEnv(),
'port' => EnvVars::DB_PORT->loadFromEnv($resolveDefaultPort()), 'port' => EnvVars::DB_PORT->loadFromEnv(),
'unix_socket' => $isMysqlCompatible ? EnvVars::DB_UNIX_SOCKET->loadFromEnv() : null, 'unix_socket' => $isMysqlCompatible ? EnvVars::DB_UNIX_SOCKET->loadFromEnv() : null,
'charset' => $resolveCharset(), 'charset' => $resolveCharset(),
'driverOptions' => $driver !== 'mssql' ? [] : [ 'driverOptions' => $driver !== 'mssql' ? [] : [

View file

@ -7,7 +7,7 @@ use Shlinkio\Shlink\Core\Config\EnvVars;
return [ return [
'matomo' => [ 'matomo' => [
'enabled' => (bool) EnvVars::MATOMO_ENABLED->loadFromEnv(false), 'enabled' => (bool) EnvVars::MATOMO_ENABLED->loadFromEnv(),
'base_url' => EnvVars::MATOMO_BASE_URL->loadFromEnv(), 'base_url' => EnvVars::MATOMO_BASE_URL->loadFromEnv(),
'site_id' => EnvVars::MATOMO_SITE_ID->loadFromEnv(), 'site_id' => EnvVars::MATOMO_SITE_ID->loadFromEnv(),
'api_token' => EnvVars::MATOMO_API_TOKEN->loadFromEnv(), 'api_token' => EnvVars::MATOMO_API_TOKEN->loadFromEnv(),

View file

@ -15,7 +15,7 @@ return (static function (): array {
'mercure' => [ 'mercure' => [
'public_hub_url' => $publicUrl, 'public_hub_url' => $publicUrl,
'internal_hub_url' => EnvVars::MERCURE_INTERNAL_HUB_URL->loadFromEnv($publicUrl), 'internal_hub_url' => EnvVars::MERCURE_INTERNAL_HUB_URL->loadFromEnv(),
'jwt_secret' => EnvVars::MERCURE_JWT_SECRET->loadFromEnv(), 'jwt_secret' => EnvVars::MERCURE_JWT_SECRET->loadFromEnv(),
'jwt_issuer' => 'Shlink', 'jwt_issuer' => 'Shlink',
], ],

View file

@ -4,32 +4,17 @@ declare(strict_types=1);
use Shlinkio\Shlink\Core\Config\EnvVars; use Shlinkio\Shlink\Core\Config\EnvVars;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_BG_COLOR;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_COLOR;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_ENABLED_FOR_DISABLED_SHORT_URLS;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_ERROR_CORRECTION;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_FORMAT;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_MARGIN;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_ROUND_BLOCK_SIZE;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_SIZE;
return [ return [
'qr_codes' => [ 'qr_codes' => [
'size' => (int) EnvVars::DEFAULT_QR_CODE_SIZE->loadFromEnv(DEFAULT_QR_CODE_SIZE), 'size' => (int) EnvVars::DEFAULT_QR_CODE_SIZE->loadFromEnv(),
'margin' => (int) EnvVars::DEFAULT_QR_CODE_MARGIN->loadFromEnv(DEFAULT_QR_CODE_MARGIN), 'margin' => (int) EnvVars::DEFAULT_QR_CODE_MARGIN->loadFromEnv(),
'format' => EnvVars::DEFAULT_QR_CODE_FORMAT->loadFromEnv(DEFAULT_QR_CODE_FORMAT), 'format' => EnvVars::DEFAULT_QR_CODE_FORMAT->loadFromEnv(),
'error_correction' => EnvVars::DEFAULT_QR_CODE_ERROR_CORRECTION->loadFromEnv( 'error_correction' => EnvVars::DEFAULT_QR_CODE_ERROR_CORRECTION->loadFromEnv(),
DEFAULT_QR_CODE_ERROR_CORRECTION, 'round_block_size' => (bool) EnvVars::DEFAULT_QR_CODE_ROUND_BLOCK_SIZE->loadFromEnv(),
), 'enabled_for_disabled_short_urls' => (bool) EnvVars::QR_CODE_FOR_DISABLED_SHORT_URLS->loadFromEnv(),
'round_block_size' => (bool) EnvVars::DEFAULT_QR_CODE_ROUND_BLOCK_SIZE->loadFromEnv( 'color' => EnvVars::DEFAULT_QR_CODE_COLOR->loadFromEnv(),
DEFAULT_QR_CODE_ROUND_BLOCK_SIZE, 'bg_color' => EnvVars::DEFAULT_QR_CODE_BG_COLOR->loadFromEnv(),
),
'enabled_for_disabled_short_urls' => (bool) EnvVars::QR_CODE_FOR_DISABLED_SHORT_URLS->loadFromEnv(
DEFAULT_QR_CODE_ENABLED_FOR_DISABLED_SHORT_URLS,
),
'color' => EnvVars::DEFAULT_QR_CODE_COLOR->loadFromEnv(DEFAULT_QR_CODE_COLOR),
'bg_color' => EnvVars::DEFAULT_QR_CODE_BG_COLOR->loadFromEnv(DEFAULT_QR_CODE_BG_COLOR),
'logo_url' => EnvVars::DEFAULT_QR_CODE_LOGO_URL->loadFromEnv(), 'logo_url' => EnvVars::DEFAULT_QR_CODE_LOGO_URL->loadFromEnv(),
], ],

View file

@ -7,13 +7,13 @@ use Shlinkio\Shlink\Core\Config\EnvVars;
return [ return [
'rabbitmq' => [ 'rabbitmq' => [
'enabled' => (bool) EnvVars::RABBITMQ_ENABLED->loadFromEnv(false), 'enabled' => (bool) EnvVars::RABBITMQ_ENABLED->loadFromEnv(),
'host' => EnvVars::RABBITMQ_HOST->loadFromEnv(), 'host' => EnvVars::RABBITMQ_HOST->loadFromEnv(),
'use_ssl' => (bool) EnvVars::RABBITMQ_USE_SSL->loadFromEnv(false), 'use_ssl' => (bool) EnvVars::RABBITMQ_USE_SSL->loadFromEnv(),
'port' => (int) EnvVars::RABBITMQ_PORT->loadFromEnv('5672'), 'port' => (int) EnvVars::RABBITMQ_PORT->loadFromEnv(),
'user' => EnvVars::RABBITMQ_USER->loadFromEnv(), 'user' => EnvVars::RABBITMQ_USER->loadFromEnv(),
'password' => EnvVars::RABBITMQ_PASSWORD->loadFromEnv(), 'password' => EnvVars::RABBITMQ_PASSWORD->loadFromEnv(),
'vhost' => EnvVars::RABBITMQ_VHOST->loadFromEnv('/'), 'vhost' => EnvVars::RABBITMQ_VHOST->loadFromEnv(),
], ],
]; ];

View file

@ -4,9 +4,6 @@ declare(strict_types=1);
use Shlinkio\Shlink\Core\Config\EnvVars; use Shlinkio\Shlink\Core\Config\EnvVars;
use const Shlinkio\Shlink\DEFAULT_REDIRECT_CACHE_LIFETIME;
use const Shlinkio\Shlink\DEFAULT_REDIRECT_STATUS_CODE;
return [ return [
'not_found_redirects' => [ 'not_found_redirects' => [
@ -16,10 +13,8 @@ return [
], ],
'redirects' => [ 'redirects' => [
'redirect_status_code' => (int) EnvVars::REDIRECT_STATUS_CODE->loadFromEnv(DEFAULT_REDIRECT_STATUS_CODE->value), 'redirect_status_code' => (int) EnvVars::REDIRECT_STATUS_CODE->loadFromEnv(),
'redirect_cache_lifetime' => (int) EnvVars::REDIRECT_CACHE_LIFETIME->loadFromEnv( 'redirect_cache_lifetime' => (int) EnvVars::REDIRECT_CACHE_LIFETIME->loadFromEnv(),
DEFAULT_REDIRECT_CACHE_LIFETIME,
),
], ],
]; ];

View file

@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Core;
return [ return [
'robots' => [ 'robots' => [
'allow-all-short-urls' => (bool) Config\EnvVars::ROBOTS_ALLOW_ALL_SHORT_URLS->loadFromEnv(false), 'allow-all-short-urls' => (bool) Config\EnvVars::ROBOTS_ALLOW_ALL_SHORT_URLS->loadFromEnv(),
'user-agents' => splitByComma(Config\EnvVars::ROBOTS_USER_AGENTS->loadFromEnv()), 'user-agents' => splitByComma(Config\EnvVars::ROBOTS_USER_AGENTS->loadFromEnv()),
], ],

View file

@ -8,7 +8,7 @@ use Shlinkio\Shlink\Core\Config\EnvVars;
return [ return [
'router' => [ 'router' => [
'base_path' => EnvVars::BASE_PATH->loadFromEnv(''), 'base_path' => EnvVars::BASE_PATH->loadFromEnv(),
'fastroute' => [ 'fastroute' => [
// Disabling config cache for cli, ensures it's never used for RoadRunner, and also that console // Disabling config cache for cli, ensures it's never used for RoadRunner, and also that console

View file

@ -21,7 +21,7 @@ return (static function (): array {
$overrideDomainMiddleware = Middleware\ShortUrl\OverrideDomainMiddleware::class; $overrideDomainMiddleware = Middleware\ShortUrl\OverrideDomainMiddleware::class;
// TODO This should be based on config, not the env var // TODO This should be based on config, not the env var
$shortUrlRouteSuffix = EnvVars::SHORT_URL_TRAILING_SLASH->loadFromEnv(false) ? '[/]' : ''; $shortUrlRouteSuffix = EnvVars::SHORT_URL_TRAILING_SLASH->loadFromEnv() ? '[/]' : '';
return [ return [

View file

@ -11,25 +11,25 @@ return [
'tracking' => [ 'tracking' => [
// Tells if IP addresses should be anonymized before persisting, to fulfil data protection regulations // Tells if IP addresses should be anonymized before persisting, to fulfil data protection regulations
// This applies only if IP address tracking is enabled // This applies only if IP address tracking is enabled
'anonymize_remote_addr' => (bool) EnvVars::ANONYMIZE_REMOTE_ADDR->loadFromEnv(true), 'anonymize_remote_addr' => (bool) EnvVars::ANONYMIZE_REMOTE_ADDR->loadFromEnv(),
// Tells if visits to not-found URLs should be tracked. The disable_tracking option takes precedence // Tells if visits to not-found URLs should be tracked. The disable_tracking option takes precedence
'track_orphan_visits' => (bool) EnvVars::TRACK_ORPHAN_VISITS->loadFromEnv(true), 'track_orphan_visits' => (bool) EnvVars::TRACK_ORPHAN_VISITS->loadFromEnv(),
// A query param that, if provided, will disable tracking of one particular visit. Always takes precedence // A query param that, if provided, will disable tracking of one particular visit. Always takes precedence
'disable_track_param' => EnvVars::DISABLE_TRACK_PARAM->loadFromEnv(), 'disable_track_param' => EnvVars::DISABLE_TRACK_PARAM->loadFromEnv(),
// If true, visits will not be tracked at all // If true, visits will not be tracked at all
'disable_tracking' => (bool) EnvVars::DISABLE_TRACKING->loadFromEnv(false), 'disable_tracking' => (bool) EnvVars::DISABLE_TRACKING->loadFromEnv(),
// If true, visits will be tracked, but neither the IP address, nor the location will be resolved // If true, visits will be tracked, but neither the IP address, nor the location will be resolved
'disable_ip_tracking' => (bool) EnvVars::DISABLE_IP_TRACKING->loadFromEnv(false), 'disable_ip_tracking' => (bool) EnvVars::DISABLE_IP_TRACKING->loadFromEnv(),
// If true, the referrer will not be tracked // If true, the referrer will not be tracked
'disable_referrer_tracking' => (bool) EnvVars::DISABLE_REFERRER_TRACKING->loadFromEnv(false), 'disable_referrer_tracking' => (bool) EnvVars::DISABLE_REFERRER_TRACKING->loadFromEnv(),
// If true, the user agent will not be tracked // If true, the user agent will not be tracked
'disable_ua_tracking' => (bool) EnvVars::DISABLE_UA_TRACKING->loadFromEnv(false), 'disable_ua_tracking' => (bool) EnvVars::DISABLE_UA_TRACKING->loadFromEnv(),
// A list of IP addresses, patterns or CIDR blocks from which tracking is disabled by default // A list of IP addresses, patterns or CIDR blocks from which tracking is disabled by default
'disable_tracking_from' => splitByComma(EnvVars::DISABLE_TRACKING_FROM->loadFromEnv()), 'disable_tracking_from' => splitByComma(EnvVars::DISABLE_TRACKING_FROM->loadFromEnv()),

View file

@ -5,29 +5,28 @@ declare(strict_types=1);
use Shlinkio\Shlink\Core\Config\EnvVars; use Shlinkio\Shlink\Core\Config\EnvVars;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlMode; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlMode;
use const Shlinkio\Shlink\DEFAULT_SHORT_CODES_LENGTH;
use const Shlinkio\Shlink\MIN_SHORT_CODES_LENGTH; use const Shlinkio\Shlink\MIN_SHORT_CODES_LENGTH;
return (static function (): array { return (static function (): array {
$shortCodesLength = max( $shortCodesLength = max(
(int) EnvVars::DEFAULT_SHORT_CODES_LENGTH->loadFromEnv(DEFAULT_SHORT_CODES_LENGTH), (int) EnvVars::DEFAULT_SHORT_CODES_LENGTH->loadFromEnv(),
MIN_SHORT_CODES_LENGTH, MIN_SHORT_CODES_LENGTH,
); );
$modeFromEnv = EnvVars::SHORT_URL_MODE->loadFromEnv(ShortUrlMode::STRICT->value); $modeFromEnv = EnvVars::SHORT_URL_MODE->loadFromEnv();
$mode = ShortUrlMode::tryFrom($modeFromEnv) ?? ShortUrlMode::STRICT; $mode = ShortUrlMode::tryFrom($modeFromEnv) ?? ShortUrlMode::STRICT;
return [ return [
'url_shortener' => [ 'url_shortener' => [
'domain' => [ // TODO Refactor this structure to url_shortener.schema and url_shortener.default_domain 'domain' => [ // TODO Refactor this structure to url_shortener.schema and url_shortener.default_domain
'schema' => ((bool) EnvVars::IS_HTTPS_ENABLED->loadFromEnv(true)) ? 'https' : 'http', 'schema' => ((bool) EnvVars::IS_HTTPS_ENABLED->loadFromEnv()) ? 'https' : 'http',
'hostname' => EnvVars::DEFAULT_DOMAIN->loadFromEnv(''), 'hostname' => EnvVars::DEFAULT_DOMAIN->loadFromEnv(),
], ],
'default_short_codes_length' => $shortCodesLength, 'default_short_codes_length' => $shortCodesLength,
'auto_resolve_titles' => (bool) EnvVars::AUTO_RESOLVE_TITLES->loadFromEnv(true), 'auto_resolve_titles' => (bool) EnvVars::AUTO_RESOLVE_TITLES->loadFromEnv(),
'append_extra_path' => (bool) EnvVars::REDIRECT_APPEND_EXTRA_PATH->loadFromEnv(false), 'append_extra_path' => (bool) EnvVars::REDIRECT_APPEND_EXTRA_PATH->loadFromEnv(),
'multi_segment_slugs_enabled' => (bool) EnvVars::MULTI_SEGMENT_SLUGS_ENABLED->loadFromEnv(false), 'multi_segment_slugs_enabled' => (bool) EnvVars::MULTI_SEGMENT_SLUGS_ENABLED->loadFromEnv(),
'trailing_slash_enabled' => (bool) EnvVars::SHORT_URL_TRAILING_SLASH->loadFromEnv(false), 'trailing_slash_enabled' => (bool) EnvVars::SHORT_URL_TRAILING_SLASH->loadFromEnv(),
'mode' => $mode, 'mode' => $mode,
], ],

View file

@ -19,8 +19,8 @@ require 'vendor/autoload.php';
loadEnvVarsFromConfig('config/params/generated_config.php', enumValues(EnvVars::class)); loadEnvVarsFromConfig('config/params/generated_config.php', enumValues(EnvVars::class));
// This is one of the first files loaded. Configure the timezone and memory limit here // This is one of the first files loaded. Configure the timezone and memory limit here
ini_set('memory_limit', EnvVars::MEMORY_LIMIT->loadFromEnv('512M')); ini_set('memory_limit', EnvVars::MEMORY_LIMIT->loadFromEnv());
date_default_timezone_set(EnvVars::TIMEZONE->loadFromEnv(date_default_timezone_get())); date_default_timezone_set(EnvVars::TIMEZONE->loadFromEnv());
// This class alias tricks the ConfigAbstractFactory to return Lock\Factory instances even with a different service name // This class alias tricks the ConfigAbstractFactory to return Lock\Factory instances even with a different service name
// It needs to be placed here as individual config files will not be loaded once config is cached // It needs to be placed here as individual config files will not be loaded once config is cached

View file

@ -8,6 +8,11 @@ mkdir -p data/cache data/locks data/log data/proxies
flags="--no-interaction --clear-db-cache" flags="--no-interaction --clear-db-cache"
# Read env vars through Shlink command, so that it applies the `_FILE` env var fallback logic
GEOLITE_LICENSE_KEY=$(bin/cli env-var:read GEOLITE_LICENSE_KEY)
SKIP_INITIAL_GEOLITE_DOWNLOAD=$(bin/cli env-var:read SKIP_INITIAL_GEOLITE_DOWNLOAD)
INITIAL_API_KEY=$(bin/cli env-var:read INITIAL_API_KEY)
# Skip downloading GeoLite2 db file if the license key env var was not defined or skipping was explicitly set # Skip downloading GeoLite2 db file if the license key env var was not defined or skipping was explicitly set
if [ -z "${GEOLITE_LICENSE_KEY}" ] || [ "${SKIP_INITIAL_GEOLITE_DOWNLOAD}" = "true" ]; then if [ -z "${GEOLITE_LICENSE_KEY}" ] || [ "${SKIP_INITIAL_GEOLITE_DOWNLOAD}" = "true" ]; then
flags="${flags} --skip-download-geolite" flags="${flags} --skip-download-geolite"

View file

@ -45,6 +45,8 @@ return [
Command\RedirectRule\ManageRedirectRulesCommand::class, Command\RedirectRule\ManageRedirectRulesCommand::class,
Command\Integration\MatomoSendVisitsCommand::NAME => Command\Integration\MatomoSendVisitsCommand::class, Command\Integration\MatomoSendVisitsCommand::NAME => Command\Integration\MatomoSendVisitsCommand::class,
Command\Config\ReadEnvVarCommand::NAME => Command\Config\ReadEnvVarCommand::class,
], ],
], ],

View file

@ -75,6 +75,8 @@ return [
Command\RedirectRule\ManageRedirectRulesCommand::class => ConfigAbstractFactory::class, Command\RedirectRule\ManageRedirectRulesCommand::class => ConfigAbstractFactory::class,
Command\Integration\MatomoSendVisitsCommand::class => ConfigAbstractFactory::class, Command\Integration\MatomoSendVisitsCommand::class => ConfigAbstractFactory::class,
Command\Config\ReadEnvVarCommand::class => InvokableFactory::class,
], ],
], ],

View file

@ -17,7 +17,7 @@ abstract class AbstractDatabaseCommand extends AbstractLockedCommand
public function __construct( public function __construct(
LockFactory $locker, LockFactory $locker,
private ProcessRunnerInterface $processRunner, private readonly ProcessRunnerInterface $processRunner,
PhpExecutableFinder $phpFinder, PhpExecutableFinder $phpFinder,
) { ) {
parent::__construct($locker); parent::__construct($locker);

View file

@ -4,12 +4,27 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Config; namespace Shlinkio\Shlink\Core\Config;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlMode;
use function date_default_timezone_get;
use function file_get_contents; use function file_get_contents;
use function getenv;
use function is_file; use function is_file;
use function Shlinkio\Shlink\Config\env; use function Shlinkio\Shlink\Config\env;
use function Shlinkio\Shlink\Config\parseEnvVar; use function Shlinkio\Shlink\Config\parseEnvVar;
use function sprintf; use function sprintf;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_COLOR;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_ENABLED_FOR_DISABLED_SHORT_URLS;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_ERROR_CORRECTION;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_FORMAT;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_MARGIN;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_ROUND_BLOCK_SIZE;
use const Shlinkio\Shlink\DEFAULT_QR_CODE_SIZE;
use const Shlinkio\Shlink\DEFAULT_REDIRECT_CACHE_LIFETIME;
use const Shlinkio\Shlink\DEFAULT_REDIRECT_STATUS_CODE;
use const Shlinkio\Shlink\DEFAULT_SHORT_CODES_LENGTH;
enum EnvVars: string enum EnvVars: string
{ {
case DELETE_SHORT_URL_THRESHOLD = 'DELETE_SHORT_URL_THRESHOLD'; case DELETE_SHORT_URL_THRESHOLD = 'DELETE_SHORT_URL_THRESHOLD';
@ -74,10 +89,67 @@ enum EnvVars: string
case ROBOTS_USER_AGENTS = 'ROBOTS_USER_AGENTS'; case ROBOTS_USER_AGENTS = 'ROBOTS_USER_AGENTS';
case TIMEZONE = 'TIMEZONE'; case TIMEZONE = 'TIMEZONE';
case MEMORY_LIMIT = 'MEMORY_LIMIT'; case MEMORY_LIMIT = 'MEMORY_LIMIT';
case INITIAL_API_KEY = 'INITIAL_API_KEY';
case SKIP_INITIAL_GEOLITE_DOWNLOAD = 'SKIP_INITIAL_GEOLITE_DOWNLOAD';
public function loadFromEnv(mixed $default = null): mixed public function loadFromEnv(): mixed
{ {
return env($this->value) ?? $this->loadFromFileEnv() ?? $default; return env($this->value) ?? $this->loadFromFileEnv() ?? $this->defaultValue();
}
private function defaultValue(): string|int|bool|null
{
return match ($this) {
self::MEMORY_LIMIT => '512M',
self::TIMEZONE => date_default_timezone_get(),
self::DEFAULT_SHORT_CODES_LENGTH => DEFAULT_SHORT_CODES_LENGTH,
self::SHORT_URL_MODE => ShortUrlMode::STRICT->value,
self::IS_HTTPS_ENABLED, self::AUTO_RESOLVE_TITLES => true,
self::REDIRECT_APPEND_EXTRA_PATH,
self::MULTI_SEGMENT_SLUGS_ENABLED,
self::SHORT_URL_TRAILING_SLASH => false,
self::DEFAULT_DOMAIN, self::BASE_PATH => '',
self::CACHE_NAMESPACE => 'Shlink',
self::REDIS_PUB_SUB_ENABLED,
self::MATOMO_ENABLED,
self::ROBOTS_ALLOW_ALL_SHORT_URLS => false,
self::DB_NAME => 'shlink',
self::DB_HOST => self::DB_UNIX_SOCKET->loadFromEnv(),
self::DB_DRIVER => 'sqlite',
self::DB_PORT => match (self::DB_DRIVER->loadFromEnv()) {
'postgres' => '5432',
'mssql' => '1433',
default => '3306',
},
self::MERCURE_INTERNAL_HUB_URL => self::MERCURE_PUBLIC_HUB_URL->loadFromEnv(),
self::DEFAULT_QR_CODE_SIZE, => DEFAULT_QR_CODE_SIZE,
self::DEFAULT_QR_CODE_MARGIN, => DEFAULT_QR_CODE_MARGIN,
self::DEFAULT_QR_CODE_FORMAT, => DEFAULT_QR_CODE_FORMAT,
self::DEFAULT_QR_CODE_ERROR_CORRECTION, => DEFAULT_QR_CODE_ERROR_CORRECTION,
self::DEFAULT_QR_CODE_ROUND_BLOCK_SIZE, => DEFAULT_QR_CODE_ROUND_BLOCK_SIZE,
self::QR_CODE_FOR_DISABLED_SHORT_URLS, => DEFAULT_QR_CODE_ENABLED_FOR_DISABLED_SHORT_URLS,
self::DEFAULT_QR_CODE_COLOR, => DEFAULT_QR_CODE_COLOR,
self::RABBITMQ_ENABLED, self::RABBITMQ_USE_SSL => false,
self::RABBITMQ_PORT => 5672,
self::RABBITMQ_VHOST => '/',
self::REDIRECT_STATUS_CODE => DEFAULT_REDIRECT_STATUS_CODE->value,
self::REDIRECT_CACHE_LIFETIME => DEFAULT_REDIRECT_CACHE_LIFETIME,
self::ANONYMIZE_REMOTE_ADDR, self::TRACK_ORPHAN_VISITS => true,
self::DISABLE_TRACKING,
self::DISABLE_IP_TRACKING,
self::DISABLE_REFERRER_TRACKING,
self::DISABLE_UA_TRACKING => false,
default => null,
};
} }
/** /**

View file

@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\Config;
use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Core\Config\EnvVars; use Shlinkio\Shlink\Core\Config\EnvVars;
@ -44,19 +45,16 @@ class EnvVarsTest extends TestCase
} }
#[Test, DataProvider('provideEnvVarsValues')] #[Test, DataProvider('provideEnvVarsValues')]
public function expectedValueIsLoadedFromEnv(EnvVars $envVar, mixed $expected, mixed $default): void public function expectedValueIsLoadedFromEnv(EnvVars $envVar, mixed $expected): void
{ {
self::assertEquals($expected, $envVar->loadFromEnv($default)); self::assertEquals($expected, $envVar->loadFromEnv());
} }
public static function provideEnvVarsValues(): iterable public static function provideEnvVarsValues(): iterable
{ {
yield 'DB_NAME without default' => [EnvVars::DB_NAME, 'shlink', null]; yield 'DB_NAME (is set)' => [EnvVars::DB_NAME, 'shlink'];
yield 'DB_NAME with default' => [EnvVars::DB_NAME, 'shlink', 'foobar']; yield 'BASE_PATH (is set)' => [EnvVars::BASE_PATH, 'the_base_path'];
yield 'BASE_PATH without default' => [EnvVars::BASE_PATH, 'the_base_path', null]; yield 'DB_DRIVER (has default)' => [EnvVars::DB_DRIVER, 'sqlite'];
yield 'BASE_PATH with default' => [EnvVars::BASE_PATH, 'the_base_path', 'foobar'];
yield 'DB_DRIVER without default' => [EnvVars::DB_DRIVER, null, null];
yield 'DB_DRIVER with default' => [EnvVars::DB_DRIVER, 'foobar', 'foobar'];
} }
#[Test] #[Test]
@ -64,4 +62,20 @@ class EnvVarsTest extends TestCase
{ {
self::assertEquals('this_is_the_password', EnvVars::DB_PASSWORD->loadFromEnv()); self::assertEquals('this_is_the_password', EnvVars::DB_PASSWORD->loadFromEnv());
} }
#[Test]
#[TestWith(['mysql', '3306'])]
#[TestWith(['maria', '3306'])]
#[TestWith(['postgres', '5432'])]
#[TestWith(['mssql', '1433'])]
public function defaultPortIsResolvedBasedOnDbDriver(string $dbDriver, string $expectedPort): void
{
putenv(EnvVars::DB_DRIVER->value . '=' . $dbDriver);
try {
self::assertEquals($expectedPort, EnvVars::DB_PORT->loadFromEnv());
} finally {
putenv(EnvVars::DB_DRIVER->value . '=');
}
}
} }