Skip to content

Commit

Permalink
Merge pull request #207 from acelaya-forks/feature/remove-functional
Browse files Browse the repository at this point in the history
Feature/remove functional
  • Loading branch information
acelaya authored Nov 29, 2023
2 parents e75f69c + 7cb46c9 commit cb0eaea
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 68 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
* *Nothing*

### Changed
* Removed dependency on functional-php

### Deprecated
* *Nothing*

### Removed
* *Nothing*

### Fixed
* *Nothing*


## [8.6.0] - 2023-11-25
### Added
* Add `CacheNamespaceConfigOption` to customize the cache namespace.
Expand Down
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"laminas/laminas-config-aggregator": "^1.14",
"laminas/laminas-servicemanager": "^3.22",
"laminas/laminas-stdlib": "^3.18",
"lstrojny/functional-php": "^1.17",
"shlinkio/shlink-config": "^2.4",
"symfony/console": "^6.3",
"symfony/filesystem": "^6.3",
Expand Down
10 changes: 5 additions & 5 deletions src/Command/InitCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

use function Functional\every;
use function array_reduce;

class InitCommand extends Command
{
Expand Down Expand Up @@ -56,10 +56,10 @@ protected function execute(InputInterface $input, OutputInterface $output): ?int
generateApiKey: $this->initialApiKey->get($input),
downloadGeoLiteDb: ! $this->skipDownloadGeoLiteDb->get($input),
);
$commands = InstallationCommand::resolveCommandsForConfig($config);
$commands = [...InstallationCommand::resolveCommandsForConfig($config)];
$io = new SymfonyStyle($input, $output);

return every($commands, function (array $commandInfo) use ($input, $io): bool {
return array_reduce($commands, function (bool $carry, array $commandInfo) use ($input, $io): bool {
/** @var array{InstallationCommand, string | null} $commandInfo */
[$command, $arg] = $commandInfo;

Expand All @@ -68,7 +68,7 @@ protected function execute(InputInterface $input, OutputInterface $output): ?int
io: $io,
interactive: $input->isInteractive(),
args: $arg !== null ? [$arg] : [],
);
}) ? 0 : -1;
) && $carry;
}, initial: true) ? 0 : -1;
}
}
7 changes: 5 additions & 2 deletions src/Command/SetOptionCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Shlinkio\Shlink\Installer\Exception\InvalidShlinkPathException;
use Shlinkio\Shlink\Installer\Service\ShlinkAssetsHandler;
use Shlinkio\Shlink\Installer\Service\ShlinkAssetsHandlerInterface;
use Shlinkio\Shlink\Installer\Util\ArrayUtils;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -19,7 +20,6 @@

use function array_filter;
use function array_keys;
use function Functional\contains;
use function getcwd;
use function is_iterable;
use function is_numeric;
Expand All @@ -43,7 +43,10 @@ public function __construct(
parent::__construct();
$this->groups = array_filter(
iterator_to_array($this->flattenGroupsWithTitle($groups)),
static fn (string $configOption) => $enabledOptions === null || contains($enabledOptions, $configOption),
static fn (string $configOption) => $enabledOptions === null || ArrayUtils::contains(
$configOption,
$enabledOptions,
),
);
$this->generatedConfigPath = getcwd() . '/' . ShlinkAssetsHandler::GENERATED_CONFIG_PATH;
}
Expand Down
55 changes: 32 additions & 23 deletions src/Config/ConfigGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@
use Shlinkio\Shlink\Installer\Config\Option\ConfigOptionInterface;
use Shlinkio\Shlink\Installer\Config\Option\ConfigOptionMigratorInterface;
use Shlinkio\Shlink\Installer\Config\Option\DependentConfigOptionInterface;
use Shlinkio\Shlink\Installer\Util\ArrayUtils;
use Symfony\Component\Console\Style\StyleInterface;

use function array_combine;
use function Functional\compose;
use function Functional\contains;
use function Functional\map;
use function Functional\select;
use function Functional\sort;
use function get_class;
use function array_filter;
use function array_map;
use function usort;

class ConfigGenerator implements ConfigGeneratorInterface
{
Expand All @@ -35,7 +33,10 @@ public function generateConfigInteractively(StyleInterface $io, array $previousC
// FIXME Improve code quality on these nested loops
foreach ($pluginsGroups as $title => $configOptions) {
foreach ($configOptions as $configOption => $plugin) {
$optionIsEnabled = $this->enabledOptions === null || contains($this->enabledOptions, $configOption);
$optionIsEnabled = $this->enabledOptions === null || ArrayUtils::contains(
$configOption,
$this->enabledOptions,
);
$shouldAsk = $optionIsEnabled && $plugin->shouldBeAsked($answers);
if (! $shouldAsk) {
if ($plugin instanceof ConfigOptionMigratorInterface && isset($answers[$plugin->getEnvVar()])) {
Expand All @@ -46,7 +47,7 @@ public function generateConfigInteractively(StyleInterface $io, array $previousC
}

// Render every title only once, and only as soon as we find a plugin that should be asked
if (! contains($alreadyRenderedTitles, $title)) {
if (! ArrayUtils::contains($title, $alreadyRenderedTitles)) {
$alreadyRenderedTitles[] = $title;
$io->title($title);
}
Expand All @@ -63,24 +64,32 @@ public function generateConfigInteractively(StyleInterface $io, array $previousC
*/
private function resolveAndSortOptions(): array
{
// Sort plugins based on which other plugins they depend on
$dependentPluginSorter = static fn (ConfigOptionInterface $a, ConfigOptionInterface $b): int =>
$a instanceof DependentConfigOptionInterface && $a->getDependentOption() === get_class($b) ? 1 : 0;
$sortAndResolvePlugins = fn (array $configOptions) => array_combine(
$resolveAndSortPlugins = function (array $configOptions) {
$plugins = array_map(
fn (string $configOption) => $this->configOptionsManager->get($configOption),
$configOptions,
);

// Sort plugins based on which other plugins they depend on
usort(
$plugins,
static fn (ConfigOptionInterface $a, ConfigOptionInterface $b): int =>
$a instanceof DependentConfigOptionInterface && $a->getDependentOption() === $b::class ? 1 : 0,
);

return array_combine($configOptions, $plugins);
};
$filterDisabledOptions = fn (array $configOptions) => array_filter(
$configOptions,
sort(
map(
$configOptions,
fn (string $configOption) => $this->configOptionsManager->get($configOption),
),
$dependentPluginSorter,
fn (string $option) => $this->enabledOptions === null || ArrayUtils::contains(
$option,
$this->enabledOptions,
),
);
$filterDisabledOptions = fn (array $configOptions) => select(
$configOptions,
fn (string $option) => $this->enabledOptions === null || contains($this->enabledOptions, $option),
);

return map($this->configOptionsGroups, compose($filterDisabledOptions, $sortAndResolvePlugins));
return array_map(
static fn (array $configOptions) => $resolveAndSortPlugins($filterDisabledOptions($configOptions)),
$this->configOptionsGroups,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
use Shlinkio\Shlink\Installer\Config\Option\BaseConfigOption;
use Shlinkio\Shlink\Installer\Config\Option\DependentConfigOptionInterface;
use Shlinkio\Shlink\Installer\Config\Util\ConfigOptionsValidatorsTrait;
use Shlinkio\Shlink\Installer\Util\ArrayUtils;
use Symfony\Component\Console\Style\StyleInterface;

use function Functional\contains;

class RedirectCacheLifeTimeConfigOption extends BaseConfigOption implements DependentConfigOptionInterface
{
use ConfigOptionsValidatorsTrait;
Expand All @@ -28,7 +27,7 @@ public function shouldBeAsked(array $currentOptions): bool

private function isPermanentRedirectStatus(int $redirectStatus): bool
{
return contains([301, 308], $redirectStatus);
return ArrayUtils::contains($redirectStatus, [301, 308]);
}

public function ask(StyleInterface $io, array $currentOptions): int
Expand Down
4 changes: 2 additions & 2 deletions src/Config/Util/ConfigOptionsValidatorsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Shlinkio\Shlink\Installer\Exception\InvalidConfigOptionException;
use Shlinkio\Shlink\Installer\Util\Utils;

use function Functional\map;
use function array_map;
use function is_numeric;
use function preg_match;
use function sprintf;
Expand Down Expand Up @@ -37,7 +37,7 @@ public function splitAndValidateMultipleUrls(?string $urls): array
}

$splitUrls = Utils::commaSeparatedToList($urls);
return map($splitUrls, [$this, 'validateUrl']);
return array_map($this->validateUrl(...), $splitUrls);
}

public function validateOptionalPositiveNumber(mixed $value): ?int
Expand Down
29 changes: 29 additions & 0 deletions src/Util/ArrayUtils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Shlinkio\Shlink\Installer\Util;

use function array_reduce;
use function in_array;

final class ArrayUtils
{
public static function contains(mixed $value, array $array): bool
{
return in_array($value, $array, strict: true);
}

/**
* @param array[] $multiArray
* @return array
*/
public static function flatten(array $multiArray): array
{
return array_reduce(
$multiArray,
static fn (array $carry, array $value) => [...$carry, ...$value],
initial: [],
);
}
}
37 changes: 21 additions & 16 deletions src/Util/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
use Shlinkio\Shlink\Installer\Config\Util\DatabaseDriver;

use function array_filter;
use function array_map;
use function array_reduce;
use function ctype_upper;
use function explode;
use function Functional\every;
use function Functional\map;
use function implode;
use function is_array;
use function is_bool;
Expand All @@ -25,32 +25,37 @@ class Utils
{
public static function commaSeparatedToList(string $list): array
{
return map(explode(',', $list), static fn (string $value) => trim($value));
return array_map(static fn (string $value) => trim($value), explode(',', $list));
}

public static function normalizeAndKeepEnvVarKeys(array $array): array
{
$dbEnvVar = DatabaseDriverConfigOption::ENV_VAR;
$filteredEnvVars = array_filter(
$array,
static fn (string $key) =>
// Filter out env vars which are not fully in uppercase.
// Numbers are also valid, as some env vars (like `DEFAULT_REGULAR_404_REDIRECT`) contain them.
array_reduce(
explode('_', $key),
static fn (bool $carry, string $part) => $carry && (ctype_upper($part) || is_numeric($part)),
initial: true,
),
ARRAY_FILTER_USE_KEY,
);

return map(
array_filter(
$array,
static fn (string $key) =>
// Filter out env vars which are not fully in uppercase.
// Numbers are also valid, as some env vars (like `DEFAULT_REGULAR_404_REDIRECT`) contain them.
every(explode('_', $key), static fn (string $part) => ctype_upper($part) || is_numeric($part)),
ARRAY_FILTER_USE_KEY,
),
// This maps old values that have been imported, to the new expected values
static fn (mixed $value, string $envVar) => match (true) {
foreach ($filteredEnvVars as $envVar => $value) {
$filteredEnvVars[$envVar] = match (true) {
is_array($value) => implode(',', $value),
$envVar === ShortDomainSchemaConfigOption::ENV_VAR && ! is_bool($value) => $value === 'https',
$envVar === $dbEnvVar && $value === 'pdo_pgsql' => DatabaseDriver::POSTGRES->value,
$envVar === $dbEnvVar && $value === 'pdo_sqlite' => DatabaseDriver::SQLITE->value,
$envVar === $dbEnvVar && $value === 'pdo_sqlsrv' => DatabaseDriver::MSSQL->value,
$envVar === $dbEnvVar && $value === 'pdo_mysql' => DatabaseDriver::MYSQL->value,
default => $value,
},
);
};
}

return $filteredEnvVars;
}
}
4 changes: 2 additions & 2 deletions test/Config/ConfigGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
use Shlinkio\Shlink\Installer\Config\Option\ConfigOptionInterface;
use Shlinkio\Shlink\Installer\Config\Option\ConfigOptionMigratorInterface;
use Shlinkio\Shlink\Installer\Config\Option\DependentConfigOptionInterface;
use Shlinkio\Shlink\Installer\Util\ArrayUtils;
use Symfony\Component\Console\Style\StyleInterface;

use function count;
use function Functional\flatten;
use function get_class;

class ConfigGeneratorTest extends TestCase
Expand All @@ -38,7 +38,7 @@ public function configuresExpectedPlugins(
?array $enabledOptions,
int $expectedPrintTitleCalls,
): void {
$totalPlugins = count(flatten($configOptionsGroups));
$totalPlugins = count(ArrayUtils::flatten($configOptionsGroups));
$expectedQuestions = $enabledOptions === null ? $totalPlugins : count($enabledOptions);

$this->plugin->expects($this->exactly($expectedQuestions))->method('shouldBeAsked')->willReturn(true);
Expand Down
4 changes: 2 additions & 2 deletions test/Factory/ApplicationFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Installer\Factory\ApplicationFactory;
use Shlinkio\Shlink\Installer\Util\ArrayUtils;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputDefinition;

use function array_filter;
use function Functional\contains;

use const ARRAY_FILTER_USE_KEY;

Expand Down Expand Up @@ -55,7 +55,7 @@ public function serviceIsCreated(): void
$commands = array_filter(
$app->all(),
// Remove standard symfony commands
static fn (string $key) => ! contains(['list', 'help', 'completion', '_complete'], $key),
static fn (string $key) => ! ArrayUtils::contains($key, ['list', 'help', 'completion', '_complete']),
ARRAY_FILTER_USE_KEY,
);

Expand Down
21 changes: 12 additions & 9 deletions test/Service/InstallationCommandsRunnerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Symfony\Component\Process\Process;

use function array_combine;
use function Functional\map;
use function array_map;
use function implode;
use function sprintf;
use function str_contains;
Expand Down Expand Up @@ -46,14 +46,17 @@ public function setUp(): void
private function buildCommands(): array
{
$names = ['foo', 'bar', 'null_command', 'multiple spaces '];
return array_combine($names, map($names, fn (string $name) => [
'command' => $name === 'null_command' ? null : sprintf('%s something', $name),
'initMessage' => sprintf('%s_init', $name),
'errorMessage' => sprintf('%s_error', $name),
'failOnError' => $name === 'foo',
'printOutput' => false,
'timeout' => $name === 'foo' ? 1000 : null,
]));
return array_combine(
$names,
array_map(fn (string $name) => [
'command' => $name === 'null_command' ? null : sprintf('%s something', $name),
'initMessage' => sprintf('%s_init', $name),
'errorMessage' => sprintf('%s_error', $name),
'failOnError' => $name === 'foo',
'printOutput' => false,
'timeout' => $name === 'foo' ? 1000 : null,
], $names),
);
}

#[Test]
Expand Down
Loading

0 comments on commit cb0eaea

Please sign in to comment.