mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-20 01:09:56 +03:00
Merge pull request #242 from acelaya/feature/functions-as-object
Moved global functions to handle array paths to a wrapper class
This commit is contained in:
commit
46482522bb
4 changed files with 159 additions and 48 deletions
|
@ -4,11 +4,8 @@ declare(strict_types=1);
|
||||||
namespace Shlinkio\Shlink\Common;
|
namespace Shlinkio\Shlink\Common;
|
||||||
|
|
||||||
use const JSON_ERROR_NONE;
|
use const JSON_ERROR_NONE;
|
||||||
use function array_key_exists;
|
|
||||||
use function array_shift;
|
|
||||||
use function getenv;
|
use function getenv;
|
||||||
use function in_array;
|
use function in_array;
|
||||||
use function is_array;
|
|
||||||
use function json_last_error;
|
use function json_last_error;
|
||||||
use function json_last_error_msg;
|
use function json_last_error_msg;
|
||||||
use function strtolower;
|
use function strtolower;
|
||||||
|
@ -62,39 +59,3 @@ function json_decode(string $json, int $depth = 512, int $options = 0): array
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function array_path_exists(array $path, array $array): bool
|
|
||||||
{
|
|
||||||
// As soon as a step is not found, the path does not exist
|
|
||||||
$step = array_shift($path);
|
|
||||||
if (! array_key_exists($step, $array)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Once the path is empty, we have found all the parts in the path
|
|
||||||
if (empty($path)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If current value is not an array, then we have not found the path
|
|
||||||
$newArray = $array[$step];
|
|
||||||
if (! is_array($newArray)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_path_exists($path, $newArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_get_path(array $path, array $array)
|
|
||||||
{
|
|
||||||
do {
|
|
||||||
$step = array_shift($path);
|
|
||||||
if (! is_array($array) || ! array_key_exists($step, $array)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$array = $array[$step];
|
|
||||||
} while (! empty($path));
|
|
||||||
|
|
||||||
return $array;
|
|
||||||
}
|
|
||||||
|
|
67
module/Common/src/Collection/PathCollection.php
Normal file
67
module/Common/src/Collection/PathCollection.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Common\Collection;
|
||||||
|
|
||||||
|
use function array_key_exists;
|
||||||
|
use function array_shift;
|
||||||
|
use function is_array;
|
||||||
|
|
||||||
|
final class PathCollection
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $array;
|
||||||
|
|
||||||
|
public function __construct(array $array)
|
||||||
|
{
|
||||||
|
$this->array = $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pathExists(array $path): bool
|
||||||
|
{
|
||||||
|
return $this->checkPathExists($path, $this->array);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkPathExists(array $path, array $array): bool
|
||||||
|
{
|
||||||
|
// As soon as a step is not found, the path does not exist
|
||||||
|
$step = array_shift($path);
|
||||||
|
if (! array_key_exists($step, $array)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the path is empty, we have found all the parts in the path
|
||||||
|
if (empty($path)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If current value is not an array, then we have not found the path
|
||||||
|
$newArray = $array[$step];
|
||||||
|
if (! is_array($newArray)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->checkPathExists($path, $newArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getValueInPath(array $path)
|
||||||
|
{
|
||||||
|
$array = $this->array;
|
||||||
|
|
||||||
|
do {
|
||||||
|
$step = array_shift($path);
|
||||||
|
if (! is_array($array) || ! array_key_exists($step, $array)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$array = $array[$step];
|
||||||
|
} while (! empty($path));
|
||||||
|
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
}
|
82
module/Common/test/Collection/PathCollectionTest.php
Normal file
82
module/Common/test/Collection/PathCollectionTest.php
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ShlinkioTest\Shlink\Common\Collection;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Shlinkio\Shlink\Common\Collection\PathCollection;
|
||||||
|
|
||||||
|
class PathCollectionTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var PathCollection
|
||||||
|
*/
|
||||||
|
private $collection;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->collection = new PathCollection([
|
||||||
|
'foo' => [
|
||||||
|
'bar' => [
|
||||||
|
'baz' => 'Hello world!',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'something' => [],
|
||||||
|
'another' => [
|
||||||
|
'one' => 'Shlink',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @dataProvider providePaths
|
||||||
|
*/
|
||||||
|
public function pathExistsReturnsExpectedValue(array $path, bool $expected)
|
||||||
|
{
|
||||||
|
$this->assertEquals($expected, $this->collection->pathExists($path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providePaths(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[[], false],
|
||||||
|
[['boo'], false],
|
||||||
|
[['foo', 'nop'], false],
|
||||||
|
[['another', 'one', 'nop'], false],
|
||||||
|
[['foo'], true],
|
||||||
|
[['foo', 'bar'], true],
|
||||||
|
[['foo', 'bar', 'baz'], true],
|
||||||
|
[['something'], true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @dataProvider providePathsWithValue
|
||||||
|
*/
|
||||||
|
public function getValueInPathReturnsExpectedValue(array $path, $expected)
|
||||||
|
{
|
||||||
|
$this->assertEquals($expected, $this->collection->getValueInPath($path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providePathsWithValue(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[[], null],
|
||||||
|
[['boo'], null],
|
||||||
|
[['foo', 'nop'], null],
|
||||||
|
[['another', 'one', 'nop'], null],
|
||||||
|
[['foo'], [
|
||||||
|
'bar' => [
|
||||||
|
'baz' => 'Hello world!',
|
||||||
|
],
|
||||||
|
]],
|
||||||
|
[['foo', 'bar'], [
|
||||||
|
'baz' => 'Hello world!',
|
||||||
|
]],
|
||||||
|
[['foo', 'bar', 'baz'], 'Hello world!'],
|
||||||
|
[['something'], []],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,13 +3,12 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Shlinkio\Shlink\Installer\Model;
|
namespace Shlinkio\Shlink\Installer\Model;
|
||||||
|
|
||||||
|
use Shlinkio\Shlink\Common\Collection\PathCollection;
|
||||||
use Shlinkio\Shlink\Installer\Config\Plugin\ApplicationConfigCustomizer;
|
use Shlinkio\Shlink\Installer\Config\Plugin\ApplicationConfigCustomizer;
|
||||||
use Shlinkio\Shlink\Installer\Config\Plugin\DatabaseConfigCustomizer;
|
use Shlinkio\Shlink\Installer\Config\Plugin\DatabaseConfigCustomizer;
|
||||||
use Shlinkio\Shlink\Installer\Config\Plugin\LanguageConfigCustomizer;
|
use Shlinkio\Shlink\Installer\Config\Plugin\LanguageConfigCustomizer;
|
||||||
use Shlinkio\Shlink\Installer\Config\Plugin\UrlShortenerConfigCustomizer;
|
use Shlinkio\Shlink\Installer\Config\Plugin\UrlShortenerConfigCustomizer;
|
||||||
use Zend\Stdlib\ArraySerializableInterface;
|
use Zend\Stdlib\ArraySerializableInterface;
|
||||||
use function Shlinkio\Shlink\Common\array_get_path;
|
|
||||||
use function Shlinkio\Shlink\Common\array_path_exists;
|
|
||||||
|
|
||||||
final class CustomizableAppConfig implements ArraySerializableInterface
|
final class CustomizableAppConfig implements ArraySerializableInterface
|
||||||
{
|
{
|
||||||
|
@ -118,12 +117,14 @@ final class CustomizableAppConfig implements ArraySerializableInterface
|
||||||
|
|
||||||
public function exchangeArray(array $array): void
|
public function exchangeArray(array $array): void
|
||||||
{
|
{
|
||||||
|
$pathCollection = new PathCollection($array);
|
||||||
|
|
||||||
$this->setApp($this->mapExistingPathsToKeys([
|
$this->setApp($this->mapExistingPathsToKeys([
|
||||||
ApplicationConfigCustomizer::SECRET => ['app_options', 'secret_key'],
|
ApplicationConfigCustomizer::SECRET => ['app_options', 'secret_key'],
|
||||||
ApplicationConfigCustomizer::DISABLE_TRACK_PARAM => ['app_options', 'disable_track_param'],
|
ApplicationConfigCustomizer::DISABLE_TRACK_PARAM => ['app_options', 'disable_track_param'],
|
||||||
ApplicationConfigCustomizer::CHECK_VISITS_THRESHOLD => ['delete_short_urls', 'check_visits_threshold'],
|
ApplicationConfigCustomizer::CHECK_VISITS_THRESHOLD => ['delete_short_urls', 'check_visits_threshold'],
|
||||||
ApplicationConfigCustomizer::VISITS_THRESHOLD => ['delete_short_urls', 'visits_threshold'],
|
ApplicationConfigCustomizer::VISITS_THRESHOLD => ['delete_short_urls', 'visits_threshold'],
|
||||||
], $array));
|
], $pathCollection));
|
||||||
|
|
||||||
$this->setDatabase($this->mapExistingPathsToKeys([
|
$this->setDatabase($this->mapExistingPathsToKeys([
|
||||||
DatabaseConfigCustomizer::DRIVER => ['entity_manager', 'connection', 'driver'],
|
DatabaseConfigCustomizer::DRIVER => ['entity_manager', 'connection', 'driver'],
|
||||||
|
@ -132,27 +133,27 @@ final class CustomizableAppConfig implements ArraySerializableInterface
|
||||||
DatabaseConfigCustomizer::NAME => ['entity_manager', 'connection', 'dbname'],
|
DatabaseConfigCustomizer::NAME => ['entity_manager', 'connection', 'dbname'],
|
||||||
DatabaseConfigCustomizer::HOST => ['entity_manager', 'connection', 'host'],
|
DatabaseConfigCustomizer::HOST => ['entity_manager', 'connection', 'host'],
|
||||||
DatabaseConfigCustomizer::PORT => ['entity_manager', 'connection', 'port'],
|
DatabaseConfigCustomizer::PORT => ['entity_manager', 'connection', 'port'],
|
||||||
], $array));
|
], $pathCollection));
|
||||||
|
|
||||||
$this->setLanguage($this->mapExistingPathsToKeys([
|
$this->setLanguage($this->mapExistingPathsToKeys([
|
||||||
LanguageConfigCustomizer::DEFAULT_LANG => ['translator', 'locale'],
|
LanguageConfigCustomizer::DEFAULT_LANG => ['translator', 'locale'],
|
||||||
LanguageConfigCustomizer::CLI_LANG => ['cli', 'locale'],
|
LanguageConfigCustomizer::CLI_LANG => ['cli', 'locale'],
|
||||||
], $array));
|
], $pathCollection));
|
||||||
|
|
||||||
$this->setUrlShortener($this->mapExistingPathsToKeys([
|
$this->setUrlShortener($this->mapExistingPathsToKeys([
|
||||||
UrlShortenerConfigCustomizer::SCHEMA => ['url_shortener', 'domain', 'schema'],
|
UrlShortenerConfigCustomizer::SCHEMA => ['url_shortener', 'domain', 'schema'],
|
||||||
UrlShortenerConfigCustomizer::HOSTNAME => ['url_shortener', 'domain', 'hostname'],
|
UrlShortenerConfigCustomizer::HOSTNAME => ['url_shortener', 'domain', 'hostname'],
|
||||||
UrlShortenerConfigCustomizer::CHARS => ['url_shortener', 'shortcode_chars'],
|
UrlShortenerConfigCustomizer::CHARS => ['url_shortener', 'shortcode_chars'],
|
||||||
UrlShortenerConfigCustomizer::VALIDATE_URL => ['url_shortener', 'validate_url'],
|
UrlShortenerConfigCustomizer::VALIDATE_URL => ['url_shortener', 'validate_url'],
|
||||||
], $array));
|
], $pathCollection));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function mapExistingPathsToKeys(array $map, array $config): array
|
private function mapExistingPathsToKeys(array $map, PathCollection $pathCollection): array
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($map as $key => $path) {
|
foreach ($map as $key => $path) {
|
||||||
if (array_path_exists($path, $config)) {
|
if ($pathCollection->pathExists($path)) {
|
||||||
$result[$key] = array_get_path($path, $config);
|
$result[$key] = $pathCollection->getValueInPath($path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue