diff --git a/composer.json b/composer.json index c6e8484..92c9724 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "hexlet/code", + "name": "Rasmus2024/php-project-48", "description": "My 2 project on Hexlet - Gendiff", "type": "project", "license": "MIT", @@ -25,7 +25,8 @@ ], "require": { "docopt/docopt": "^1.0", - "symfony/yaml": "^6.0" + "symfony/yaml": "^6.0", + "lstrojny/functional-php": "^1.17" }, "bin": [ "bin/gendiff" @@ -36,7 +37,8 @@ "phpstan/phpstan": "1.10.24", "phpstan/extension-installer": "1.4.3", "phpstan/phpstan-beberlei-assert": "^1.1", - "phpstan/phpstan-strict-rules": "^1.5" + "phpstan/phpstan-strict-rules": "^1.5", + "hexlet/phpstan-fp": "^2.0" }, "config": { "allow-plugins": { diff --git a/composer.lock b/composer.lock index 7be50ab..6395cc3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2ae3084e2ff45c3fdc0369c256ffe6ac", + "content-hash": "ba14010428b18f39d515689469fae4b7", "packages": [ { "name": "docopt/docopt", @@ -53,6 +53,160 @@ }, "time": "2023-03-22T12:31:48+00:00" }, + { + "name": "lstrojny/functional-php", + "version": "1.17.0", + "source": { + "type": "git", + "url": "https://github.com/lstrojny/functional-php.git", + "reference": "e459d5cb307bc6e10e9e992c4e96bb71a0262506" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lstrojny/functional-php/zipball/e459d5cb307bc6e10e9e992c4e96bb71a0262506", + "reference": "e459d5cb307bc6e10e9e992c4e96bb71a0262506", + "shasum": "" + }, + "require": { + "php": "^7.1|~8" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.17", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.5", + "squizlabs/php_codesniffer": "~3.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/Functional/Ary.php", + "src/Functional/Average.php", + "src/Functional/ButLast.php", + "src/Functional/Capture.php", + "src/Functional/ConstFunction.php", + "src/Functional/CompareOn.php", + "src/Functional/CompareObjectHashOn.php", + "src/Functional/Compose.php", + "src/Functional/Concat.php", + "src/Functional/Contains.php", + "src/Functional/Converge.php", + "src/Functional/Curry.php", + "src/Functional/CurryN.php", + "src/Functional/Difference.php", + "src/Functional/DropFirst.php", + "src/Functional/DropLast.php", + "src/Functional/Each.php", + "src/Functional/Equal.php", + "src/Functional/ErrorToException.php", + "src/Functional/Every.php", + "src/Functional/False.php", + "src/Functional/Falsy.php", + "src/Functional/Filter.php", + "src/Functional/First.php", + "src/Functional/FirstIndexOf.php", + "src/Functional/FlatMap.php", + "src/Functional/Flatten.php", + "src/Functional/Flip.php", + "src/Functional/GreaterThan.php", + "src/Functional/GreaterThanOrEqual.php", + "src/Functional/Group.php", + "src/Functional/Head.php", + "src/Functional/Id.php", + "src/Functional/IfElse.php", + "src/Functional/Identical.php", + "src/Functional/IndexesOf.php", + "src/Functional/Intersperse.php", + "src/Functional/Invoke.php", + "src/Functional/InvokeFirst.php", + "src/Functional/InvokeIf.php", + "src/Functional/InvokeLast.php", + "src/Functional/Invoker.php", + "src/Functional/Last.php", + "src/Functional/LastIndexOf.php", + "src/Functional/LessThan.php", + "src/Functional/LessThanOrEqual.php", + "src/Functional/LexicographicCompare.php", + "src/Functional/Map.php", + "src/Functional/Matching.php", + "src/Functional/Maximum.php", + "src/Functional/Memoize.php", + "src/Functional/Minimum.php", + "src/Functional/None.php", + "src/Functional/Noop.php", + "src/Functional/Not.php", + "src/Functional/OmitKeys.php", + "src/Functional/PartialAny.php", + "src/Functional/PartialLeft.php", + "src/Functional/PartialMethod.php", + "src/Functional/PartialRight.php", + "src/Functional/Partition.php", + "src/Functional/Pick.php", + "src/Functional/Pluck.php", + "src/Functional/Poll.php", + "src/Functional/Product.php", + "src/Functional/Ratio.php", + "src/Functional/ReduceLeft.php", + "src/Functional/ReduceRight.php", + "src/Functional/Reindex.php", + "src/Functional/Reject.php", + "src/Functional/Repeat.php", + "src/Functional/Retry.php", + "src/Functional/Select.php", + "src/Functional/SelectKeys.php", + "src/Functional/SequenceConstant.php", + "src/Functional/SequenceExponential.php", + "src/Functional/SequenceLinear.php", + "src/Functional/Some.php", + "src/Functional/Sort.php", + "src/Functional/Sum.php", + "src/Functional/SuppressError.php", + "src/Functional/Tap.php", + "src/Functional/Tail.php", + "src/Functional/TailRecursion.php", + "src/Functional/TakeLeft.php", + "src/Functional/TakeRight.php", + "src/Functional/True.php", + "src/Functional/Truthy.php", + "src/Functional/Unique.php", + "src/Functional/ValueToKey.php", + "src/Functional/With.php", + "src/Functional/Zip.php", + "src/Functional/ZipAll.php" + ], + "psr-4": { + "Functional\\": "src/Functional" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Strojny", + "email": "lstrojny@php.net", + "homepage": "https://usrportage.de" + }, + { + "name": "Max Beutel", + "email": "nash12@gmail.com" + } + ], + "description": "Functional primitives for PHP", + "keywords": [ + "functional" + ], + "support": { + "issues": "https://github.com/lstrojny/functional-php/issues", + "source": "https://github.com/lstrojny/functional-php/tree/1.17.0" + }, + "funding": [ + { + "url": "https://github.com/lstrojny", + "type": "github" + } + ], + "time": "2021-03-07T00:25:34+00:00" + }, { "name": "symfony/deprecation-contracts", "version": "v3.5.0", @@ -273,6 +427,249 @@ } ], "packages-dev": [ + { + "name": "hexlet/phpstan-fp", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/Hexlet/phpstan-functional-programming.git", + "reference": "bb33471a772f6c437dc3231eb046cdfc743dd7d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Hexlet/phpstan-functional-programming/zipball/bb33471a772f6c437dc3231eb046cdfc743dd7d2", + "reference": "bb33471a772f6c437dc3231eb046cdfc743dd7d2", + "shasum": "" + }, + "require": { + "illuminate/collections": "^10.14.1", + "php": ">=8.1", + "phpstan/phpstan": "^1.10.24" + }, + "require-dev": { + "phpunit/phpunit": "^9.5.18", + "squizlabs/php_codesniffer": "^3.6.2" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Hexlet\\PHPStanFp\\": "src/", + "Hexlet\\PHPStanFp\\Tests\\": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan rules for functional programming", + "support": { + "issues": "https://github.com/Hexlet/phpstan-functional-programming/issues", + "source": "https://github.com/Hexlet/phpstan-functional-programming/tree/v2.0.0" + }, + "time": "2023-07-05T18:17:16+00:00" + }, + { + "name": "illuminate/collections", + "version": "v10.48.22", + "source": { + "type": "git", + "url": "https://github.com/illuminate/collections.git", + "reference": "37c863cffb345869dd134eff8e646bc82a19cc96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/collections/zipball/37c863cffb345869dd134eff8e646bc82a19cc96", + "reference": "37c863cffb345869dd134eff8e646bc82a19cc96", + "shasum": "" + }, + "require": { + "illuminate/conditionable": "^10.0", + "illuminate/contracts": "^10.0", + "illuminate/macroable": "^10.0", + "php": "^8.1" + }, + "suggest": { + "symfony/var-dumper": "Required to use the dump method (^6.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Collections package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-06-19T14:25:05+00:00" + }, + { + "name": "illuminate/conditionable", + "version": "v10.48.22", + "source": { + "type": "git", + "url": "https://github.com/illuminate/conditionable.git", + "reference": "d0958e4741fc9d6f516a552060fd1b829a85e009" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/conditionable/zipball/d0958e4741fc9d6f516a552060fd1b829a85e009", + "reference": "d0958e4741fc9d6f516a552060fd1b829a85e009", + "shasum": "" + }, + "require": { + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Conditionable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-02-03T08:06:17+00:00" + }, + { + "name": "illuminate/contracts", + "version": "v10.48.22", + "source": { + "type": "git", + "url": "https://github.com/illuminate/contracts.git", + "reference": "8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac", + "reference": "8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac", + "shasum": "" + }, + "require": { + "php": "^8.1", + "psr/container": "^1.1.1|^2.0.1", + "psr/simple-cache": "^1.0|^2.0|^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Contracts\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Contracts package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-01-15T18:52:32+00:00" + }, + { + "name": "illuminate/macroable", + "version": "v10.48.22", + "source": { + "type": "git", + "url": "https://github.com/illuminate/macroable.git", + "reference": "dff667a46ac37b634dcf68909d9d41e94dc97c27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/macroable/zipball/dff667a46ac37b634dcf68909d9d41e94dc97c27", + "reference": "dff667a46ac37b634dcf68909d9d41e94dc97c27", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Macroable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-06-05T12:46:42+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.12.0", @@ -1139,6 +1536,110 @@ ], "time": "2023-02-03T07:16:15+00:00" }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, { "name": "sebastian/cli-parser", "version": "2.0.1", diff --git a/formatters/Json.php b/formatters/Json.php index 452bf3c..300d74c 100644 --- a/formatters/Json.php +++ b/formatters/Json.php @@ -4,6 +4,7 @@ function json(array $tree): string { - $json_string = json_encode($tree, JSON_PRETTY_PRINT); + //$json_string = json_encode($tree, JSON_PRETTY_PRINT); + $json_string = json_encode($tree); return $json_string; } diff --git a/formatters/Plain.php b/formatters/Plain.php index 5b39f55..e6ed046 100644 --- a/formatters/Plain.php +++ b/formatters/Plain.php @@ -2,7 +2,7 @@ namespace Differ\Formatters\Plain; -use function Differ\Formatters\Stylish\array_flatten; +use function Functional\flatten; function iter(mixed $value1, string $level = '', mixed $key1 = null): array { @@ -12,42 +12,48 @@ function iter(mixed $value1, string $level = '', mixed $key1 = null): array $type = $value['type']; $tkey = $value['key']; if ($level === '') { - $level = $tkey; + $newLevel = $tkey; } else { - $level = "{$level}.{$tkey}"; + $newLevel = "{$level}.{$tkey}"; } - $arrayResult = iter($value['value'], $level, $tkey); - $arrayResult2 = array_flatten($arrayResult); + $arrayResult = iter($value['value'], $newLevel, $tkey); + $arrayResult2 = flatten($arrayResult); $arrayResult3 = implode('', $arrayResult2); if (array_key_exists('new_value', $value)) { - $newVal = $value['new_value']; - if (is_string($newVal)) { - $newVal = "'{$newVal}'"; + if (is_string($value['new_value'])) { + $newVal = "'{$value['new_value']}'"; } else { - $newVal = json_encode($newVal); + $newVal = json_encode($value['new_value']); + } + if ($type === '_') { + $temp = "Property '{$newLevel}' was updated. From [complex value] to {$newVal}\n"; + return "{$temp}{$arrayResult3}"; } } $result = match ($type) { ' ' => '', - '+' => "Property '{$level}' was added with value: [complex value]\n", - '-' => "Property '{$level}' was removed\n", - '_' => "Property '{$level}' was updated. From [complex value] to {$newVal}\n", + '+' => "Property '{$newLevel}' was added with value: [complex value]\n", + '-' => "Property '{$newLevel}' was removed\n", + default => '', }; return "{$result}{$arrayResult3}"; } else { $type = $value['type']; $tkey = $value['key']; - $val = $value['value']; - $val = (is_string($val)) ? "'{$val}'" : json_encode($val); + $val = (is_string($value['value'])) ? "'{$value['value']}'" : json_encode($value['value']); if (array_key_exists('new_value', $value)) { - $newVal = $value['new_value']; - $newVal = (is_string($newVal)) ? "'{$newVal}'" : json_encode($newVal); + $newVal = (is_string($value['new_value'])) ? + "'{$value['new_value']}'" : + json_encode($value['new_value']); + if ($type === '_') { + return "Property '{$level}.{$tkey}' was updated. From {$val} to {$newVal}\n"; + } } $result = match ($type) { ' ' => '', '+' => "Property '{$level}.{$tkey}' was added with value: {$val}\n", '-' => "Property '{$level}.{$tkey}' was removed\n", - '_' => "Property '{$level}.{$tkey}' was updated. From {$val} to {$newVal}\n", + default => '', }; } return $result; @@ -58,7 +64,7 @@ function iter(mixed $value1, string $level = '', mixed $key1 = null): array function plain(array $tree): string { - $result = iter($tree, ''); - $result = implode('', array_flatten($result)); + $temp = iter($tree, ''); + $result = implode('', flatten($temp)); return substr($result, 0, -1); } diff --git a/formatters/Stylish.php b/formatters/Stylish.php index 3a4bf21..bb89c40 100644 --- a/formatters/Stylish.php +++ b/formatters/Stylish.php @@ -2,55 +2,41 @@ namespace Differ\Formatters\Stylish; +use function Functional\flatten; + function getLevelSpaces(int $level) { return str_repeat(' ', $level * 4 - 2); } -function array_flatten(array $tree, int $depth = 0) -{ - $result = []; - foreach ($tree as $key => $value) { - if ($depth >= 0 && is_array($value)) { - $value = array_flatten($value, $depth > 1 ? $depth - 1 : 0 - $depth); - $result = array_merge($result, $value); - } else { - $result[] = $value; - } - } - return $result; -} - -function iter(mixed $value1, int $level = 1, $key1 = null): array +function iter(mixed $value1, int $level = 1): array { $output = array_map(function ($key, $value) use ($level) { + $spaces = getLevelSpaces($level); if (is_array($value) && array_key_exists('value', $value)) { if (is_array($value['value'])) { - $spaces = getLevelSpaces($level); - $type = $value['type']; $tkey = $value['key']; - $level++; - $temp = iter($value['value'], $level, $tkey); - $temp = array_flatten($temp); - $temp = implode('', $temp); + $type = $value['type']; + $levelNew = $level + 1; + $temp = iter($value['value'], $levelNew); + $tempFlatten = flatten($temp); + $tempImplode = implode('', $tempFlatten); if ($type === "_") { - $newVal = $value['new_value']; - $newVal = (is_string($newVal)) ? $newVal : json_encode($newVal); - return "{$spaces}- {$tkey}: {\n{$temp}{$spaces} }\n{$spaces}+ {$tkey}: {$newVal}\n"; + $newValue = $value['new_value']; + $newVal = (is_string($newValue)) ? $newValue : json_encode($newValue); + return "{$spaces}- {$tkey}: {\n{$tempImplode}{$spaces} }\n{$spaces}+ {$tkey}: {$newVal}\n"; } else { - return "{$spaces}{$type} {$tkey}: {\n{$temp}{$spaces} }\n"; + return "{$spaces}{$type} {$tkey}: {\n{$tempImplode}{$spaces} }\n"; } } else { - $spaces = getLevelSpaces($level); $type = $value['type']; $tkey = $value['key']; - $val = $value['value']; - $val = (is_string($val)) ? "$val" : json_encode($val); - $val = ($val === '') ? ' ' : " {$val}"; + $tempValue = (is_string($value['value'])) ? $value['value'] : json_encode($value['value']); + $val = ($tempValue === '') ? ' ' : " {$tempValue}"; if ($type === "_") { - $newVal = $value['new_value']; - $newVal = (is_string($newVal)) ? $newVal : json_encode($newVal); - $newVal = ($newVal === '') ? ' ' : " {$newVal}"; + $newValue = $value['new_value']; + $tempNewValue = (is_string($newValue)) ? $newValue : json_encode($newValue); + $newVal = ($tempNewValue === '') ? ' ' : " {$tempNewValue}"; return "{$spaces}- {$tkey}:{$val}\n{$spaces}+ {$tkey}:{$newVal}\n"; } else { return "{$spaces}{$type} {$tkey}:{$val}\n"; @@ -61,10 +47,10 @@ function iter(mixed $value1, int $level = 1, $key1 = null): array return $output; } -function stylish(array $tree) +function stylish(array $tree): string { - $result[] = "{\n"; - $result[] = iter($tree, 1); - $result[] = "}"; - return implode('', array_flatten($result)); + $temp1 = iter($tree, 1); + $temp2 = flatten($temp1); + $result = implode($temp2); + return "{\n{$result}}"; } diff --git a/phpstan.neon b/phpstan.neon index 66d670c..108de64 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,7 +1,9 @@ parameters: level: 8 paths: - - code + - src + - formatters + - bin checkMissingIterableValueType: false @@ -18,5 +20,5 @@ parameters: - '#should return .* but returns#' - '#Anonymous function should have native return type#' - #phpstanFunctionalProgramming: - # disallowThrow: false +#phpstanFunctionalProgramming: +# disallowThrow: false diff --git a/phpunit.xml b/phpunit.xml index 55dc53c..16403d5 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -4,12 +4,13 @@ bootstrap="vendor/autoload.php" cacheResultFile=".phpunit.cache/test-results" executionOrder="depends,defects" + displayDetailsOnTestsThatTriggerDeprecations="true" beStrictAboutTestsThatDoNotTestAnything="false" beStrictAboutOutputDuringTests="true" beStrictAboutTodoAnnotatedTests="true" beStrictAboutCoverageMetadata="true" - failOnRisky="false" - failOnWarning="false"> + failOnRisky="true" + failOnWarning="true"> tests diff --git a/src/Differ.php b/src/Differ.php index 0368834..7f4e836 100644 --- a/src/Differ.php +++ b/src/Differ.php @@ -4,27 +4,28 @@ use function Differ\Formatters\formatSelect; use function Differ\Parsers\fileParser; +use function Functional\sort; function genDiff(mixed $file1Path, mixed $file2Path, string $formatName = 'stylish'): string { $data1 = fileParser($file1Path); $data2 = fileParser($file2Path); - $result = ''; - if ($data1 && $data2) { - $dataDiff = filesDiffer($data1, $data2); - $result = formatSelect($dataDiff, $formatName); + if ($data1 !== false && $data2 !== false) { + $dataDiff = arraysDiffer($data1, $data2); + return formatSelect($dataDiff, $formatName); + } else { + return ''; } - return $result; } function getSortedKeys(array $json1, array $json2): array { $keys1 = array_keys($json1); $keys2 = array_keys($json2); - $keys = array_merge($keys1, $keys2); - $keys = array_unique($keys); - sort($keys, SORT_STRING); - return $keys; + $unionKeys = array_merge($keys1, $keys2); + $keys = array_unique($unionKeys); + $keysSorted = sort($keys, fn ($left, $right) => $left <=> $right); + return $keysSorted; } function arrayKeysInsert(array $array): array @@ -39,7 +40,7 @@ function arrayKeysInsert(array $array): array return $value1; } -function filesDiffer(mixed $data1, mixed $data2): mixed +function arraysDiffer(mixed $data1, mixed $data2): mixed { $sortedKeys = getSortedKeys($data1, $data2); $data = array_map(function ($key) use ($data1, $data2) { @@ -61,18 +62,22 @@ function filesDiffer(mixed $data1, mixed $data2): mixed $value1 = $data1[$key]; $value2 = $data2[$key]; if (is_array($value1) && is_array($value2)) { - return ['type' => ' ', 'key' => $key, 'value' => filesDiffer($value1, $value2)]; + return ['type' => ' ', 'key' => $key, 'value' => arraysDiffer($value1, $value2)]; } if ($value1 === $value2) { return ['type' => ' ', 'key' => $key, 'value' => $value1]; } else { if (is_array($value1)) { - $value1 = arrayKeysInsert($value1); + $value1New = arrayKeysInsert($value1); + } else { + $value1New = $value1; } if (is_array($value2)) { - $value2 = arrayKeysInsert($value2); + $value2New = arrayKeysInsert($value2); + } else { + $value2New = $value2; } - return ['type' => '_', 'key' => $key, 'value' => $value1, 'new_value' => $value2]; + return ['type' => '_', 'key' => $key, 'value' => $value1New, 'new_value' => $value2New]; } }, $sortedKeys); return $data; diff --git a/src/Formatters.php b/src/Formatters.php index c967a6c..2ca6a3b 100644 --- a/src/Formatters.php +++ b/src/Formatters.php @@ -12,6 +12,7 @@ function formatSelect(array $diffSource, string $formatName): string 'stylish' => stylish($diffSource), 'plain' => plain($diffSource), 'json' => json($diffSource), + default => '', }; return $result; } diff --git a/src/Parsers.php b/src/Parsers.php index 921525c..6637ee4 100644 --- a/src/Parsers.php +++ b/src/Parsers.php @@ -6,17 +6,21 @@ function fileParser(string $pathToFile): mixed { - $extension = pathinfo($pathToFile)['extension']; - $fileContent = file_get_contents($pathToFile); - if ($fileContent !== false) { - return match ($extension) { - 'json' => json_decode($fileContent, true), - 'yaml' => Yaml::parseFile($pathToFile), - 'yml' => Yaml::parseFile($pathToFile), - default => '', - }; + $pathToFileElements = pathinfo($pathToFile); + if (array_key_exists('extension', $pathToFileElements)) { + $extension = $pathToFileElements['extension']; + $fileContent = file_get_contents($pathToFile); + if ($fileContent !== false) { + return match ($extension) { + 'json' => json_decode($fileContent, true), + 'yaml' => Yaml::parseFile($pathToFile), + 'yml' => Yaml::parseFile($pathToFile), + default => '', + }; + } else { + return false; + } } else { - print_r("Error! - File '{$pathToFile}' not read.\n"); return false; } } diff --git a/tests/fixtures/Jsonresult.txt b/tests/fixtures/Jsonresult.txt index eb0fd86..842f442 100644 --- a/tests/fixtures/Jsonresult.txt +++ b/tests/fixtures/Jsonresult.txt @@ -1,152 +1 @@ -[ - { - "type": " ", - "key": "common", - "value": [ - { - "type": "+", - "key": "follow", - "value": false - }, - { - "type": " ", - "key": "setting1", - "value": "Value 1" - }, - { - "type": "-", - "key": "setting2", - "value": 200 - }, - { - "type": "_", - "key": "setting3", - "value": true, - "new_value": null - }, - { - "type": "+", - "key": "setting4", - "value": "blah blah" - }, - { - "type": "+", - "key": "setting5", - "value": [ - { - "type": " ", - "key": "key5", - "value": "value5" - } - ] - }, - { - "type": " ", - "key": "setting6", - "value": [ - { - "type": " ", - "key": "doge", - "value": [ - { - "type": "_", - "key": "wow", - "value": "", - "new_value": "so much" - } - ] - }, - { - "type": " ", - "key": "key", - "value": "value" - }, - { - "type": "+", - "key": "ops", - "value": "vops" - } - ] - } - ] - }, - { - "type": " ", - "key": "group1", - "value": [ - { - "type": "_", - "key": "baz", - "value": "bas", - "new_value": "bars" - }, - { - "type": " ", - "key": "foo", - "value": "bar" - }, - { - "type": "_", - "key": "nest", - "value": [ - { - "type": " ", - "key": "key", - "value": "value" - } - ], - "new_value": "str" - } - ] - }, - { - "type": "-", - "key": "group2", - "value": [ - { - "type": " ", - "key": "abc", - "value": 12345 - }, - { - "type": " ", - "key": "deep", - "value": [ - { - "type": " ", - "key": "id", - "value": 45 - } - ] - } - ] - }, - { - "type": "+", - "key": "group3", - "value": [ - { - "type": " ", - "key": "deep", - "value": [ - { - "type": " ", - "key": "id", - "value": [ - { - "type": " ", - "key": "number", - "value": 45 - } - ] - } - ] - }, - { - "type": " ", - "key": "fee", - "value": 100500 - } - ] - } -] \ No newline at end of file +[{"type":" ","key":"common","value":[{"type":"+","key":"follow","value":false},{"type":" ","key":"setting1","value":"Value 1"},{"type":"-","key":"setting2","value":200},{"type":"_","key":"setting3","value":true,"new_value":null},{"type":"+","key":"setting4","value":"blah blah"},{"type":"+","key":"setting5","value":[{"type":" ","key":"key5","value":"value5"}]},{"type":" ","key":"setting6","value":[{"type":" ","key":"doge","value":[{"type":"_","key":"wow","value":"","new_value":"so much"}]},{"type":" ","key":"key","value":"value"},{"type":"+","key":"ops","value":"vops"}]}]},{"type":" ","key":"group1","value":[{"type":"_","key":"baz","value":"bas","new_value":"bars"},{"type":" ","key":"foo","value":"bar"},{"type":"_","key":"nest","value":[{"type":" ","key":"key","value":"value"}],"new_value":"str"}]},{"type":"-","key":"group2","value":[{"type":" ","key":"abc","value":12345},{"type":" ","key":"deep","value":[{"type":" ","key":"id","value":45}]}]},{"type":"+","key":"group3","value":[{"type":" ","key":"deep","value":[{"type":" ","key":"id","value":[{"type":" ","key":"number","value":45}]}]},{"type":" ","key":"fee","value":100500}]}] \ No newline at end of file