1717use Composer \Json \JsonFile ;
1818use Composer \Json \JsonManipulator ;
1919use Composer \Package \Locker ;
20+ use Composer \Package \Package ;
2021use Composer \Package \Version \VersionParser ;
2122use Composer \Package \Version \VersionSelector ;
2223use Composer \Plugin \PluginInterface ;
2324use Composer \Repository \InstalledRepositoryInterface ;
2425use Composer \Repository \RepositorySet ;
2526use Composer \Script \Event ;
2627use Composer \Script \ScriptEvents ;
28+ use Composer \Util \Filesystem ;
2729
2830/**
2931 * @internal
@@ -83,6 +85,56 @@ public function uninstall(Composer $composer, IOInterface $io)
8385 {
8486 }
8587
88+ public function preAutoloadDump (Event $ event )
89+ {
90+ $ filesystem = new Filesystem ();
91+ $ vendor = $ filesystem ->normalizePath (realpath (realpath ($ event ->getComposer ()->getConfig ()->get ('vendor-dir ' ))));
92+ $ filesystem ->ensureDirectoryExists ($ vendor .'/composer ' );
93+
94+ $ repo = $ event ->getComposer ()->getRepositoryManager ()->getLocalRepository ();
95+ $ vendors = self ::initializeConcreteImplementation ($ repo );
96+
97+ $ namespace = __NAMESPACE__ ;
98+ $ psr7Vendor = str_replace (['NULL ' , '\\\\' ], ['null ' , '\\' ], var_export (PSR7_VENDOR , true ));
99+ $ psr18Vendor = str_replace (['NULL ' , '\\\\' ], ['null ' , '\\' ], var_export (PSR18_VENDOR , true ));
100+ $ httplugVendor = str_replace (['NULL ' , '\\\\' ], ['null ' , '\\' ], var_export (HTTPLUG_VENDOR , true ));
101+
102+ $ filesystem ->filePutContentsIfModified ($ vendor .'/composer/WellKnownConcreteImplementation.php ' , <<<EOPHP
103+ <?php
104+
105+ namespace $ namespace;
106+
107+ class ConcreteImplementation
108+ {
109+ public const PSR7_VENDOR = $ psr7Vendor;
110+ public const PSR18_VENDOR = $ psr18Vendor;
111+ public const HTTPLUG_VENDOR = $ httplugVendor;
112+ }
113+
114+ EOPHP
115+ );
116+
117+ $ rootPackage = $ event ->getComposer ()->getPackage ();
118+ $ autoload = $ rootPackage ->getAutoload ();
119+ $ autoload ['classmap ' ][] = $ vendor .'/composer/WellKnownConcreteImplementation.php ' ;
120+ $ rootPackage ->setAutoload ($ autoload );
121+
122+ unset($ vendors [PSR7_VENDOR ], $ vendors [PSR18_VENDOR ], $ vendors [HTTPLUG_VENDOR ]);
123+
124+ foreach ($ repo ->getPackages () as $ package ) {
125+ if ('friendsofphp/well-known-implementations ' !== $ package ->getName () || !$ package instanceof Package) {
126+ continue ;
127+ }
128+ $ autoload = $ package ->getAutoload ();
129+ $ autoload ['exclude-from-classmap ' ][] = 'src/Internal/ComposerPlugin.php ' ;
130+ $ autoload ['exclude-from-classmap ' ][] = 'src/Internal/ConcreteImplementation.php ' ;
131+ foreach ($ vendors as $ vendor ) {
132+ $ autoload ['exclude-from-classmap ' ][] = 'src/Internal/ ' .$ vendor .'/ ' ;
133+ }
134+ $ package ->setAutoload ($ autoload );
135+ }
136+ }
137+
86138 public function postUpdate (Event $ event )
87139 {
88140 $ composer = $ event ->getComposer ();
@@ -125,6 +177,7 @@ public function postUpdate(Event $event)
125177
126178 /** @var Installer $installer */
127179 $ installer = clone $ installer ;
180+ $ trace ['object ' ]->setAudit (false );
128181 $ installer ->__construct (
129182 $ event ->getIO (),
130183 $ composer ->getConfig (),
@@ -276,6 +329,7 @@ public function updateComposerJson(array $missingRequires, bool $sortPackages)
276329 public static function getSubscribedEvents (): array
277330 {
278331 return [
332+ ScriptEvents::PRE_AUTOLOAD_DUMP => 'preAutoloadDump ' ,
279333 ScriptEvents::POST_UPDATE_CMD => 'postUpdate ' ,
280334 ];
281335 }
@@ -290,4 +344,41 @@ private function updateComposerLock(Composer $composer, IOInterface $io)
290344 $ lockData ['content-hash ' ] = Locker::getContentHash ($ composerJson );
291345 $ lockFile ->write ($ lockData );
292346 }
347+
348+ private static function initializeConcreteImplementation (InstalledRepositoryInterface $ repo ): array
349+ {
350+ $ vendors = [];
351+
352+ foreach (ConcreteImplementation::IMPLEMENTATIONS as $ const => $ packages ) {
353+ $ vendors += $ packages ;
354+ if (\defined (__NAMESPACE__ ."\\{$ const }_VENDOR " )) {
355+ continue ;
356+ }
357+ foreach ([false , true ] as $ includeDevRequirements ) {
358+ foreach ($ packages as $ namespace => $ versions ) {
359+ foreach ((array ) $ versions as $ package => $ version ) {
360+ if (\is_int ($ package )) {
361+ $ package = $ version ;
362+ $ version = null ;
363+ }
364+ if (!$ includeDevRequirements && \in_array ($ package , $ repo ->getDevPackageNames (), true )) {
365+ continue 2 ;
366+ }
367+ if (!$ repo ->findPackage ($ package , null !== $ version ? '>= ' .$ version : '* ' )) {
368+ continue 2 ;
369+ }
370+ }
371+ \define (__NAMESPACE__ ."\\{$ const }_VENDOR " , $ namespace );
372+ continue 3 ;
373+ }
374+ }
375+ \define (__NAMESPACE__ ."\\{$ const }_VENDOR " , null );
376+ }
377+
378+ foreach ($ vendors as $ vendor => $ versions ) {
379+ $ vendors [$ vendor ] = $ vendor ;
380+ }
381+
382+ return $ vendors ;
383+ }
293384}
0 commit comments