1313
1414use Composer \Json \JsonFile ;
1515use Composer \Json \JsonManipulator ;
16+ use Composer \Semver \Constraint \ConstraintInterface ;
17+ use Composer \Semver \Intervals ;
18+ use Composer \Semver \VersionParser ;
1619
1720/**
1821 * Synchronize package.json files detected in installed PHP packages with
@@ -41,6 +44,8 @@ public function synchronize(array $packagesNames): bool
4144 $ didAddLink = $ this ->addPackageJsonLink ($ packageName ) || $ didAddLink ;
4245 }
4346
47+ $ this ->registerPeerDependencies ($ packagesNames );
48+
4449 // Register controllers and entrypoints in controllers.json
4550 $ this ->registerWebpackResources ($ packagesNames );
4651
@@ -106,11 +111,8 @@ private function registerWebpackResources(array $phpPackages)
106111 continue ;
107112 }
108113
109- if (!file_exists ($ packageJsonPath = $ this ->rootDir .'/vendor/ ' .$ phpPackage .$ assetsDir .'/package.json ' )) {
110- continue ;
111- }
112-
113114 // Register in config
115+ $ packageJsonPath = $ this ->rootDir .'/vendor/ ' .$ phpPackage .$ assetsDir .'/package.json ' ;
114116 $ packageJson = (new JsonFile ($ packageJsonPath ))->read ();
115117
116118 foreach ($ packageJson ['symfony ' ]['controllers ' ] ?? [] as $ controllerName => $ defaultConfig ) {
@@ -158,6 +160,41 @@ private function registerWebpackResources(array $phpPackages)
158160 file_put_contents ($ controllersJsonPath , json_encode ($ newControllersJson , \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES )."\n" );
159161 }
160162
163+ public function registerPeerDependencies (array $ phpPackages )
164+ {
165+ $ peerDependencies = [];
166+
167+ foreach ($ phpPackages as $ phpPackage ) {
168+ if (!$ assetsDir = $ this ->resolveAssetsDir ($ phpPackage )) {
169+ continue ;
170+ }
171+
172+ $ packageJsonPath = $ this ->rootDir .'/vendor/ ' .$ phpPackage .$ assetsDir .'/package.json ' ;
173+ $ packageJson = (new JsonFile ($ packageJsonPath ))->read ();
174+ $ versionParser = new VersionParser ();
175+
176+ foreach ($ packageJson ['peerDependencies ' ] ?? [] as $ peerDependency => $ constraint ) {
177+ $ peerDependencies [$ peerDependency ][$ constraint ] = $ versionParser ->parseConstraints ($ constraint );
178+ }
179+ }
180+
181+ if (!$ peerDependencies ) {
182+ return ;
183+ }
184+
185+ $ manipulator = new JsonManipulator (file_get_contents ($ this ->rootDir .'/package.json ' ));
186+ $ content = json_decode ($ manipulator ->getContents (), true );
187+ $ devDependencies = $ content ['devDependencies ' ] ?? [];
188+
189+ foreach ($ peerDependencies as $ peerDependency => $ constraints ) {
190+ $ devDependencies [$ peerDependency ] = $ this ->compactConstraints ($ constraints );
191+ }
192+ uksort ($ devDependencies , 'strnatcmp ' );
193+ $ manipulator ->addMainKey ('devDependencies ' , $ devDependencies );
194+
195+ file_put_contents ($ this ->rootDir .'/package.json ' , $ manipulator ->getContents ());
196+ }
197+
161198 private function resolveAssetsDir (string $ phpPackage )
162199 {
163200 foreach (['/assets ' , '/Resources/assets ' ] as $ subdir ) {
@@ -168,4 +205,28 @@ private function resolveAssetsDir(string $phpPackage)
168205
169206 return null ;
170207 }
208+
209+ /**
210+ * @param ConstraintInterface[] $constraints
211+ */
212+ private function compactConstraints (array $ constraints ): string
213+ {
214+ if (method_exists (Intervals::class, 'isSubsetOf ' )) {
215+ foreach ($ constraints as $ k1 => $ constraint1 ) {
216+ foreach ($ constraints as $ k2 => $ constraint2 ) {
217+ if ($ k1 !== $ k2 && Intervals::isSubsetOf ($ constraint1 , $ constraint2 )) {
218+ unset($ constraints [$ k2 ]);
219+ }
220+ }
221+ }
222+ }
223+
224+ uksort ($ constraints , 'strnatcmp ' );
225+
226+ foreach ($ constraints as $ k => $ constraint ) {
227+ $ constraints [$ k ] = \count ($ constraints ) > 1 && false !== strpos ($ k , '| ' ) ? '( ' .$ k .') ' : $ k ;
228+ }
229+
230+ return implode (', ' , $ constraints );
231+ }
171232}
0 commit comments