From: Philipp Date: Sat, 14 Jan 2023 23:53:51 +0000 (+0100) Subject: Config: Improve the node.config.php transformation X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=4c28f9cf9c882803cc810327b657437f815afa43;p=friendica.git Config: Improve the node.config.php transformation - Add more types - Improvement for assoziative arrays and key-value arrays - Add a lot more tests --- diff --git a/src/Core/Config/Util/ConfigFileTransformer.php b/src/Core/Config/Util/ConfigFileTransformer.php index ac4990df13..7cd351ab8f 100644 --- a/src/Core/Config/Util/ConfigFileTransformer.php +++ b/src/Core/Config/Util/ConfigFileTransformer.php @@ -26,67 +26,191 @@ namespace Friendica\Core\Config\Util; */ class ConfigFileTransformer { + /** + * The public method to start the encoding + * + * @param array $data A full config array + * + * @return string The config stream, which can be saved + */ public static function encode(array $data): string { + // Add the typical header values $dataString = ' null," . PHP_EOL; - continue; - } - - $dataString .= "\t'$category' => [" . PHP_EOL; + // the last array line, close it with a semicolon + $dataString .= ";" . PHP_EOL; - if (is_array($data[$category])) { - $keys = array_keys($data[$category]); + return $dataString; + } - foreach ($keys as $key) { - $dataString .= static::mapConfigValue($key, $data[$category][$key]); - } - } - $dataString .= "\t]," . PHP_EOL; + /** + * Extracts an inner config array. + * Either as a Key => Value pair array or as an assoziative array + * + * @param array $config The config array which should get extracted + * @param int $level The current level of recursion (necessary for tab-indentation calculation) + * @param bool $inAssoziativeArray If true, the current array resides inside another assoziative array. Different rules may be applicable + * + * @return string The config string + */ + protected static function extractArray(array $config, int $level = 0, bool $inAssoziativeArray = false): string + { + if (array_values($config) === $config) { + return self::extractAssoziativeArray($config, $level, $inAssoziativeArray); + } else { + return self::extractKeyValueArray($config, $level, $inAssoziativeArray); } - - $dataString .= "];" . PHP_EOL; - - return $dataString; } - protected static function extractArray(array $config, int $level = 0): string + /** + * Extracts a key-value array and save it into a string + * output: + * [ + * 'key' => value, + * 'key' => value, + * ... + * ] + * + * @param array $config The key-value array + * @param int $level The current level of recursion (necessary for tab-indentation calculation) + * @param bool $inAssoziativeArray If true, the current array resides inside another assoziative array. Different rules may be applicable + * + * @return string The config string + */ + protected static function extractKeyValueArray(array $config, int $level = 0, bool $inAssoziativeArray = false): string { $string = ''; + // Because we're in an assoziative array, we have to add a line-break first + if ($inAssoziativeArray) { + $string .= PHP_EOL . str_repeat("\t", $level); + } + + // Add a typical Line break for a taxative list of key-value pairs + $string .= '[' . PHP_EOL; + foreach ($config as $configKey => $configValue) { - $string .= static::mapConfigValue($configKey, $configValue, $level); + $string .= str_repeat("\t", $level + 1) . + "'$configKey' => " . + static::transformConfigValue($configValue, $level) . + ',' . PHP_EOL; } + $string .= str_repeat("\t", $level) . ']'; + return $string; } - protected static function mapConfigValue(string $key, $value, $level = 0): string + /** + * Extracts an assoziative array and save it into a string + * output1 - simple: + * [ value, value, value ] + * + * output2 - complex: + * [ + * [ value, value, value ], + * value, + * [ + * key => value, + * key => value, + * ], + * ] + * + * @param array $config The assoziative array + * @param int $level The current level of recursion (necessary for tab-indentation calculation) + * @param bool $inAssoziativeArray If true, the current array resides inside another assoziative array. Different rules may be applicable + * + * @return string The config string + */ + protected static function extractAssoziativeArray(array $config, int $level = 0, bool $inAssoziativeArray = false): string { - $string = str_repeat("\t", $level + 2) . "'$key' => "; - - if (is_null($value)) { - $string .= "null,"; - } elseif (is_array($value)) { - $string .= "[" . PHP_EOL; - $string .= static::extractArray($value, ++$level); - $string .= str_repeat("\t", $level + 1) . '],'; - } elseif (is_bool($value)) { - $string .= ($value ? 'true' : 'false') . ","; - } elseif (is_numeric($value)) { - $string .= $value . ","; - } else { - $string .= sprintf('\'%s\',', addcslashes($value, '\'\\')); + $string = '['; + + $countConfigValues = count($config); + // multiline defines, if each entry uses a new line + $multiline = false; + + // Search if any value is an array, because then other formatting rules are applicable + foreach ($config as $item) { + if (is_array($item)) { + $multiline = true; + break; + } + } + + for ($i = 0; $i < $countConfigValues; $i++) { + $isArray = is_array($config[$i]); + + /** + * In case this is an array in an array, directly extract this array again and continue + * Skip any other logic since this isn't applicable for an array in an array + */ + if ($isArray) { + $string .= PHP_EOL . str_repeat("\t", $level + 1); + $string .= static::extractArray($config[$i], $level + 1, $inAssoziativeArray) . ','; + continue; + } + + if ($multiline) { + $string .= PHP_EOL . str_repeat("\t", $level + 1); + } + + $string .= static::transformConfigValue($config[$i], $level, true); + + // add trailing commas or whitespaces for certain config entries + if (($i < ($countConfigValues - 1))) { + $string .= ','; + if (!$multiline) { + $string .= ' '; + } + } + } + + // Add a new line for the last bracket as well + if ($multiline) { + $string .= PHP_EOL . str_repeat("\t", $level); } - $string .= PHP_EOL; + $string .= ']'; return $string; } + + /** + * Transforms one config value and returns the corresponding text-representation + * + * @param mixed $value Any value to transform + * @param int $level The current level of recursion (necessary for tab-indentation calculation) + * @param bool $inAssoziativeArray If true, the current array resides inside another assoziative array. Different rules may be applicable + * + * @return string + */ + protected static function transformConfigValue($value, int $level = 0, bool $inAssoziativeArray = false): string + { + switch (gettype($value)) { + case "boolean": + return ($value ? 'true' : 'false'); + case "integer": + case "double": + return $value; + case "string": + return sprintf('\'%s\'', addcslashes($value, '\'\\')); + case "array": + return static::extractArray($value, ++$level, $inAssoziativeArray); + case "NULL": + return "null"; + case "object": + case "resource": + case "resource (closed)": + throw new \InvalidArgumentException(sprintf('%s in configs are not supported yet.', gettype($value))); + case "unknown type": + throw new \InvalidArgumentException(sprintf('%s is an unknown value', $value)); + default: + throw new \InvalidArgumentException(sprintf('%s is currently unsupported', $value)); + } + } } diff --git a/tests/datasets/config/B.node.config.php b/tests/datasets/config/B.node.config.php index 499e092a45..6b0f15ad1e 100644 --- a/tests/datasets/config/B.node.config.php +++ b/tests/datasets/config/B.node.config.php @@ -23,9 +23,13 @@ return [ 'string2' => 'false', ], ], - 'v' => true, - 'v3' => 1, + 'bool_true' => true, + 'bool_false' => false, + 'int_1_not_true' => 1, + 'int_0_not_false' => 0, 'v4' => 5.6443, + 'string_1_not_true' => '1', + 'string_0_not_false' => '0', ], ], 'system' => [ diff --git a/tests/datasets/config/C.node.config.php b/tests/datasets/config/C.node.config.php deleted file mode 100644 index 6d93d8d7ad..0000000000 --- a/tests/datasets/config/C.node.config.php +++ /dev/null @@ -1,48 +0,0 @@ - [ - 'hostname' => 'friendica.local', - ], - 'system' => [ - 'disable_email_validation' => 1, - 'disable_password_exposed' => 1, - 'throttle_limit_day' => 100, - 'throttle_limit_week' => 100, - 'throttle_limit_month' => 100, - 'temppath' => '/tmp/friendica.local', - 'theme' => 'frio', - 'url' => 'https://friendica.local', - 'urlpath' => '', - 'build' => 1508, - 'maintenance' => false, - 'dbupdate' => 1, - 'update' => 0, - 'spoolpath' => '/tmp/localhost/spool', - 'actor_name' => 'friendica', - 'site_prvkey' => '-----BEGIN PRIVATE KEY----- -MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALgypZoZ2X7rYCHT -pXZRPKZYOJrtzAZoAD6a2FESfax/mW7tGF8/XGcsu4E8a0WUs18CDb09iDlECs0r -WFkyxOsS55FyDPVNOVheU6ziqmjTNggr1qR8iIpPW2xHAnFjCfvJxgaUfszdoeUV -mhA++BrxFGRpfcH49O+dVcjisJEVAgMBAAECgYEAq0QsRkSSvjgMgmdQCdsvEVwm -BafldG9vCsbfK0KOJ73c5A8AAk/fku88yMVs2J2SylwWekakStrBUFNlKkrSXEv3 -r1l0b+dfniaTGJkawqgRh+U/0G9LN+cdZYt5EuhNhCbmIQB+FOI12jAx6COwEENi -824zrrwn0BU1VTOMwwECQQDnBqq0J9JCJAtjqX+3xd8DvTRYjYvtvXlQ8fwrGxBc -GwURNG8aMGTaj+sn2kVWNt4wLQqj/CTJ42y0bkKYMJftAkEAzBwSqfuMZD/+nEkM -wDQb1G2z+BaxLh5JJQo80WX9tORbspOkbEuPgFprO6NB0/vNH5m4AaL3jymokH1p -JfVoyQJBAN+GSsmOMdf+qepeiA0V7OXgPXJkWXvHtEZGK1bFk7maBvgThF+RbTMu -xjZD8IwvACEao03wWuPfIEEe4V4Avi0CQCc5FdUYg+gX7CO4XfzphpeR5U29fprw -MvotN3a99L04TO7KNISjGJZ/ya+SNeo4rzhtX9DgslYOmVf64aPrvxECQQDB79vF -Kx2HyacBSErXrlqqkPdFo8KxhKCAVhrs0VBU1WPswolzsZvRdFuielhGP49DjjE7 -JV1Als1hl1xTduNb ------END PRIVATE KEY----- - ', - 'site_pubkey' => '-----BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4MqWaGdl+62Ah06V2UTymWDia -7cwGaAA+mthREn2sf5lu7RhfP1xnLLuBPGtFlLNfAg29PYg5RArNK1hZMsTrEueR -cgz1TTlYXlOs4qpo0zYIK9akfIiKT1tsRwJxYwn7ycYGlH7M3aHlFZoQPvga8RRk -aX3B+PTvnVXI4rCRFQIDAQAB ------END PUBLIC KEY----- - ', - ], -]; diff --git a/tests/datasets/config/transformer/C.node.config.php b/tests/datasets/config/transformer/C.node.config.php new file mode 100644 index 0000000000..6d93d8d7ad --- /dev/null +++ b/tests/datasets/config/transformer/C.node.config.php @@ -0,0 +1,48 @@ + [ + 'hostname' => 'friendica.local', + ], + 'system' => [ + 'disable_email_validation' => 1, + 'disable_password_exposed' => 1, + 'throttle_limit_day' => 100, + 'throttle_limit_week' => 100, + 'throttle_limit_month' => 100, + 'temppath' => '/tmp/friendica.local', + 'theme' => 'frio', + 'url' => 'https://friendica.local', + 'urlpath' => '', + 'build' => 1508, + 'maintenance' => false, + 'dbupdate' => 1, + 'update' => 0, + 'spoolpath' => '/tmp/localhost/spool', + 'actor_name' => 'friendica', + 'site_prvkey' => '-----BEGIN PRIVATE KEY----- +MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALgypZoZ2X7rYCHT +pXZRPKZYOJrtzAZoAD6a2FESfax/mW7tGF8/XGcsu4E8a0WUs18CDb09iDlECs0r +WFkyxOsS55FyDPVNOVheU6ziqmjTNggr1qR8iIpPW2xHAnFjCfvJxgaUfszdoeUV +mhA++BrxFGRpfcH49O+dVcjisJEVAgMBAAECgYEAq0QsRkSSvjgMgmdQCdsvEVwm +BafldG9vCsbfK0KOJ73c5A8AAk/fku88yMVs2J2SylwWekakStrBUFNlKkrSXEv3 +r1l0b+dfniaTGJkawqgRh+U/0G9LN+cdZYt5EuhNhCbmIQB+FOI12jAx6COwEENi +824zrrwn0BU1VTOMwwECQQDnBqq0J9JCJAtjqX+3xd8DvTRYjYvtvXlQ8fwrGxBc +GwURNG8aMGTaj+sn2kVWNt4wLQqj/CTJ42y0bkKYMJftAkEAzBwSqfuMZD/+nEkM +wDQb1G2z+BaxLh5JJQo80WX9tORbspOkbEuPgFprO6NB0/vNH5m4AaL3jymokH1p +JfVoyQJBAN+GSsmOMdf+qepeiA0V7OXgPXJkWXvHtEZGK1bFk7maBvgThF+RbTMu +xjZD8IwvACEao03wWuPfIEEe4V4Avi0CQCc5FdUYg+gX7CO4XfzphpeR5U29fprw +MvotN3a99L04TO7KNISjGJZ/ya+SNeo4rzhtX9DgslYOmVf64aPrvxECQQDB79vF +Kx2HyacBSErXrlqqkPdFo8KxhKCAVhrs0VBU1WPswolzsZvRdFuielhGP49DjjE7 +JV1Als1hl1xTduNb +-----END PRIVATE KEY----- + ', + 'site_pubkey' => '-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4MqWaGdl+62Ah06V2UTymWDia +7cwGaAA+mthREn2sf5lu7RhfP1xnLLuBPGtFlLNfAg29PYg5RArNK1hZMsTrEueR +cgz1TTlYXlOs4qpo0zYIK9akfIiKT1tsRwJxYwn7ycYGlH7M3aHlFZoQPvga8RRk +aX3B+PTvnVXI4rCRFQIDAQAB +-----END PUBLIC KEY----- + ', + ], +]; diff --git a/tests/datasets/config/transformer/D.node.config.php b/tests/datasets/config/transformer/D.node.config.php new file mode 100644 index 0000000000..9e5707a9bb --- /dev/null +++ b/tests/datasets/config/transformer/D.node.config.php @@ -0,0 +1,8 @@ + [ + 'string_1_not_true' => '1', + 'string_0_not_false' => '0', + ], +]; diff --git a/tests/datasets/config/transformer/object.node.config.php b/tests/datasets/config/transformer/object.node.config.php new file mode 100644 index 0000000000..f1807199bc --- /dev/null +++ b/tests/datasets/config/transformer/object.node.config.php @@ -0,0 +1,7 @@ + [ + 'objects_not_supported' => new stdClass(), + ], +]; diff --git a/tests/datasets/config/transformer/ressource.node.config.php b/tests/datasets/config/transformer/ressource.node.config.php new file mode 100644 index 0000000000..b83a139e34 --- /dev/null +++ b/tests/datasets/config/transformer/ressource.node.config.php @@ -0,0 +1,7 @@ + [ + 'ressources_not_allowed' => new \GuzzleHttp\Psr7\AppendStream(), + ], +]; diff --git a/tests/datasets/config/transformer/small_types.node.config.php b/tests/datasets/config/transformer/small_types.node.config.php new file mode 100644 index 0000000000..4bf92e3b9b --- /dev/null +++ b/tests/datasets/config/transformer/small_types.node.config.php @@ -0,0 +1,12 @@ + [ + [ + 'key' => 'value', + ], + [ + 'key2' => 'value2', + ], + ], +]; diff --git a/tests/datasets/config/transformer/types.node.config.php b/tests/datasets/config/transformer/types.node.config.php new file mode 100644 index 0000000000..d2a7dfe57d --- /dev/null +++ b/tests/datasets/config/transformer/types.node.config.php @@ -0,0 +1,75 @@ + [ + 'bool_true' => true, + 'bool_false' => false, + 'int_1' => 1, + 'int_0' => 2, + 'int_12345' => 12345, + 'float' => 1.234, + 'double_E+' => 1.24E+20, + 'double_E-' => 7.0E-10, + 'null' => null, + 'array' => [1, '2', '3', 4.0E-10, 12345, 0, false, 'true', true], + 'array_keys' => [ + 'int_1' => 1, + 'string_2' => '2', + 'string_3' => '3', + 'double' => 4.0E-10, + 'int' => 12345, + 'int_0' => 0, + 'false' => false, + 'string_true' => 'true', + 'true' => true, + ], + 'array_extended' => [ + [ + 'key_1' => 'value_1', + 'key_2' => 'value_2', + 'key_3' => [ + 'inner_key' => 'inner_value', + ], + ], + [ + 'key_2' => false, + '0' => [ + 'is_that' => true, + '0' => [ + 'working' => '?', + ], + ], + 'inner_array' => [ + [ + 'key' => 'value', + 'key2' => 12, + ], + ], + 'key_3' => true, + ], + ['value', 'value2'], + [ + [ + 'key' => 123, + ], + 'test', + 'test52', + 'test23', + [ + 'key' => 456, + ], + ], + ], + ], + 'other_cat' => [ + 'key' => 'value', + ], + 'other_cat2' => [ + [ + 'key' => 'value', + ], + [ + 'key2' => 'value2', + ], + ], +]; diff --git a/tests/src/Core/Config/Util/ConfigFileTransformerTest.php b/tests/src/Core/Config/Util/ConfigFileTransformerTest.php index 5a0ab96a46..bb156cf282 100644 --- a/tests/src/Core/Config/Util/ConfigFileTransformerTest.php +++ b/tests/src/Core/Config/Util/ConfigFileTransformerTest.php @@ -36,8 +36,25 @@ class ConfigFileTransformerTest extends MockedTest 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/B.node.config.php'), ], 'friendica.local' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/C.node.config.php'), + 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/C.node.config.php'), ], + 'friendica.local.2' => [ + 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/D.node.config.php'), + ], + 'object_invalid' => [ + 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/object.node.config.php'), + 'assertException' => true, + ], + 'ressource_invalid' => [ + 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/ressource.node.config.php'), + 'assertException' => true, + ], + 'test_types' => [ + 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/types.node.config.php'), + ], + 'small_types' => [ + 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/small_types.node.config.php'), + ] ]; } @@ -46,10 +63,14 @@ class ConfigFileTransformerTest extends MockedTest * * @dataProvider dataTests */ - public function testConfigFile(string $configFile) + public function testConfigFile(string $configFile, bool $assertException = false) { $dataArray = include $configFile; + if ($assertException) { + self::expectException(\InvalidArgumentException::class); + } + $newConfig = ConfigFileTransformer::encode($dataArray); self::assertEquals(file_get_contents($configFile), $newConfig);