22
33namespace Differ \Differ ;
44
5- use function Differ \Parsers \{ getFileFormat , parse } ;
6- use function Differ \DiffBuilder \ buildDiff ;
7- use function Differ \ Formatters \ format ;
5+ use function Differ \Parsers \parse ;
6+ use function Differ \Formatters \ render ;
7+ use function Functional \ sort ;
88
99function genDiff (string $ filePath1 , string $ filePath2 , string $ format = 'stylish ' ): string
1010{
11- $ data1 = getDataFromFile ($ filePath1 );
12- $ data2 = getDataFromFile ($ filePath2 );
11+ $ content1 = getFileContent ($ filePath1 );
12+ $ content2 = getFileContent ($ filePath2 );
13+
14+ $ data1 = parse ($ content1 , getFileFormat ($ filePath1 ));
15+ $ data2 = parse ($ content2 , getFileFormat ($ filePath2 ));
1316
1417 $ diff = buildDiff ($ data1 , $ data2 );
15- return format ($ diff , $ format );
18+ return render ($ diff , $ format );
1619}
1720
18- function getDataFromFile (string $ filePath ): object
21+ function getFileContent (string $ filePath ): string
1922{
2023 if (!file_exists ($ filePath )) {
2124 throw new \Exception ("File ' {$ filePath }' does not exist " );
@@ -26,6 +29,118 @@ function getDataFromFile(string $filePath): object
2629 throw new \Exception ("Failed to read file ' {$ filePath }' " );
2730 }
2831
29- $ fileFormat = getFileFormat ($ filePath );
30- return parse ($ content , $ fileFormat );
32+ return $ content ;
33+ }
34+
35+ function getFileFormat (string $ filePath ): string
36+ {
37+ $ extension = pathinfo ($ filePath , PATHINFO_EXTENSION );
38+
39+ return match ($ extension ) {
40+ 'json ' => 'json ' ,
41+ 'yaml ' , 'yml ' => 'yaml ' ,
42+ default => throw new \Exception ("Unsupported file format: {$ extension }" )
43+ };
44+ }
45+
46+ function buildDiff (object $ data1 , object $ data2 ): array
47+ {
48+ $ keys1 = array_keys (get_object_vars ($ data1 ));
49+ $ keys2 = array_keys (get_object_vars ($ data2 ));
50+ $ allKeys = array_unique (array_merge ($ keys1 , $ keys2 ));
51+ $ sortedKeys = sortKeys ($ allKeys );
52+
53+ return array_map (function ($ key ) use ($ data1 , $ data2 ) {
54+ return buildNode ($ key , $ data1 , $ data2 );
55+ }, $ sortedKeys );
56+ }
57+
58+ function buildNode (string $ key , object $ data1 , object $ data2 ): array
59+ {
60+ $ value1 = getValue ($ data1 , $ key );
61+ $ value2 = getValue ($ data2 , $ key );
62+
63+ $ hasInFirst = property_exists ($ data1 , $ key );
64+ $ hasInSecond = property_exists ($ data2 , $ key );
65+
66+ if (!$ hasInFirst ) {
67+ return buildAddedNode ($ key , $ value2 );
68+ }
69+
70+ if (!$ hasInSecond ) {
71+ return buildRemovedNode ($ key , $ value1 );
72+ }
73+
74+ if (isObject ($ value1 ) && isObject ($ value2 )) {
75+ return buildNestedNode ($ key , $ value1 , $ value2 );
76+ }
77+
78+ if ($ value1 === $ value2 ) {
79+ return buildUnchangedNode ($ key , $ value1 );
80+ }
81+
82+ return buildChangedNode ($ key , $ value1 , $ value2 );
83+ }
84+
85+ function buildAddedNode (string $ key , mixed $ value ): array
86+ {
87+ return [
88+ 'type ' => 'added ' ,
89+ 'key ' => $ key ,
90+ 'value ' => $ value
91+ ];
92+ }
93+
94+ function buildRemovedNode (string $ key , mixed $ value ): array
95+ {
96+ return [
97+ 'type ' => 'removed ' ,
98+ 'key ' => $ key ,
99+ 'value ' => $ value
100+ ];
101+ }
102+
103+ function buildUnchangedNode (string $ key , mixed $ value ): array
104+ {
105+ return [
106+ 'type ' => 'unchanged ' ,
107+ 'key ' => $ key ,
108+ 'value ' => $ value
109+ ];
110+ }
111+
112+ function buildChangedNode (string $ key , mixed $ oldValue , mixed $ newValue ): array
113+ {
114+ return [
115+ 'type ' => 'changed ' ,
116+ 'key ' => $ key ,
117+ 'oldValue ' => $ oldValue ,
118+ 'newValue ' => $ newValue
119+ ];
120+ }
121+
122+ function buildNestedNode (string $ key , object $ oldValue , object $ newValue ): array
123+ {
124+ return [
125+ 'type ' => 'nested ' ,
126+ 'key ' => $ key ,
127+ 'children ' => buildDiff ($ oldValue , $ newValue )
128+ ];
129+ }
130+
131+ function getValue (object $ data , string $ key ): mixed
132+ {
133+ return property_exists ($ data , $ key ) ? $ data ->$ key : null ;
134+ }
135+
136+ function isObject (mixed $ value ): bool
137+ {
138+ return is_object ($ value );
139+ }
140+
141+ function sortKeys (array $ keys ): array
142+ {
143+ return sort ($ keys , function ($ a , $ b ) {
144+ return strcmp ($ a , $ b );
145+ });
31146}
0 commit comments