From d87cc4f5cff668c54ea4c0b81b99fb0014525b42 Mon Sep 17 00:00:00 2001
From: Simon Gilli <typo3@gilbertsoft.org>
Date: Fri, 5 Nov 2021 20:56:04 +0100
Subject: [PATCH] [TASK] Move Composer package artifact to vendor folder

Storing the package artifact in the var/build folder raised
questions how this folder shall be treated in general and during
deployment. Since the Package Artifact is built in
a `composer install` process, it should be treated the same as
other build artifacts like all files in the vendor folder.

To make this more clear, the package artifact is now also stored in
the vendor folder.

Accessing the vendor folder during runtime is now possible with
using Composer 2.1 runtime API, which is required anyway already.

The path to the vendor folder is determined indirectly, by using
the path to the typo3/cms-composer-installers package. This means,
this package must not be replaced by another package with a different
name. Since no public replacements for this package exist and
there are no benefits for a private replacement of this package over
having a private fork with the same package name,
this should not be an impediment.

To ease the required related changes in the testing framework,
late static binding is used for calling
SystemEnvironmentBuilder::usesComposerClassLoading

Resolves: #95897
Releases: master
Change-Id: I3cfc982c289b312d22f59d2704d7e7932efc8cc1
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72071
Tested-by: core-ci <typo3@b13.com>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack <benni@typo3.org>
---
 .../core/Classes/Composer/PackageArtifactBuilder.php  |  4 ++--
 typo3/sysext/core/Classes/Core/Bootstrap.php          |  8 +++++++-
 .../core/Classes/Core/SystemEnvironmentBuilder.php    |  2 +-
 .../Classes/Package/Cache/ComposerPackageArtifact.php |  6 +++---
 ...t-95647-ComposerInstallationsAndExtensionUsage.rst | 11 +++++++++--
 5 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/typo3/sysext/core/Classes/Composer/PackageArtifactBuilder.php b/typo3/sysext/core/Classes/Composer/PackageArtifactBuilder.php
index e959d2a59728..597ca7d59d72 100644
--- a/typo3/sysext/core/Classes/Composer/PackageArtifactBuilder.php
+++ b/typo3/sysext/core/Classes/Composer/PackageArtifactBuilder.php
@@ -81,7 +81,7 @@ class PackageArtifactBuilder extends PackageManager implements InstallerScript
         $this->event = $event;
         $this->config = Config::load($this->event->getComposer(), $this->event->getIO());
         $composer = $this->event->getComposer();
-        $basePath = Config::load($composer)->get('base-dir');
+        $basePath = $this->config->get('base-dir');
         $this->packagesBasePath = $basePath . '/';
         foreach ($this->extractPackageMapFromComposer() as [$composerPackage, $path, $extensionKey]) {
             $packagePath = PathUtility::sanitizeTrailingSeparator($path);
@@ -93,7 +93,7 @@ class PackageArtifactBuilder extends PackageManager implements InstallerScript
         }
         $this->sortPackagesAndConfiguration();
         $cacheIdentifier = md5(serialize($composer->getLocker()->getLockData()));
-        $this->setPackageCache(new ComposerPackageArtifact($this->config->get('app-dir') . '/var', new Filesystem(), $cacheIdentifier));
+        $this->setPackageCache(new ComposerPackageArtifact($composer->getConfig()->get('vendor-dir') . '/typo3', new Filesystem(), $cacheIdentifier));
         $this->saveToPackageCache();
 
         return true;
diff --git a/typo3/sysext/core/Classes/Core/Bootstrap.php b/typo3/sysext/core/Classes/Core/Bootstrap.php
index cf1bcba4ac93..b42c83acd424 100644
--- a/typo3/sysext/core/Classes/Core/Bootstrap.php
+++ b/typo3/sysext/core/Classes/Core/Bootstrap.php
@@ -16,6 +16,7 @@
 namespace TYPO3\CMS\Core\Core;
 
 use Composer\Autoload\ClassLoader;
+use Composer\InstalledVersions;
 use Doctrine\Common\Annotations\AnnotationReader;
 use Doctrine\Common\Annotations\AnnotationRegistry;
 use Psr\Container\ContainerInterface;
@@ -268,7 +269,12 @@ class Bootstrap
             return new PackageStatesPackageCache(Environment::getLegacyConfigPath() . '/PackageStates.php', $coreCache);
         }
 
-        return new ComposerPackageArtifact(Environment::getVarPath());
+        $composerInstallersPath = InstalledVersions::getInstallPath('typo3/cms-composer-installers');
+        if ($composerInstallersPath === null) {
+            throw new \RuntimeException('Package "typo3/cms-composer-installers" not found. Replacing the package is not allowed. Fork the package instead and pull in the fork with the same name.', 1636145677);
+        }
+
+        return new ComposerPackageArtifact(dirname($composerInstallersPath));
     }
 
     /**
diff --git a/typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php b/typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php
index bf4294a70d95..6ab6e11b8e7b 100644
--- a/typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php
+++ b/typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php
@@ -220,7 +220,7 @@ class SystemEnvironmentBuilder
         Environment::initialize(
             static::createApplicationContext(),
             self::isCliRequestType($requestType),
-            self::usesComposerClassLoading(),
+            static::usesComposerClassLoading(),
             $isDifferentRootPath ? $projectRootPath : $sitePath,
             $sitePath,
             $isDifferentRootPath ? $projectRootPath . '/var'    : $sitePath . '/typo3temp/var',
diff --git a/typo3/sysext/core/Classes/Package/Cache/ComposerPackageArtifact.php b/typo3/sysext/core/Classes/Package/Cache/ComposerPackageArtifact.php
index 50002bf237f0..7737acb8468c 100644
--- a/typo3/sysext/core/Classes/Package/Cache/ComposerPackageArtifact.php
+++ b/typo3/sysext/core/Classes/Package/Cache/ComposerPackageArtifact.php
@@ -31,7 +31,7 @@ class ComposerPackageArtifact implements PackageCacheInterface
     /**
      * Location of the file inside the var folder
      */
-    private const ARTIFACTS_FILE = '/build/PackageArtifact.php';
+    private const ARTIFACTS_FILE = '/PackageArtifact.php';
 
     /**
      * Full filesystem path to the file
@@ -62,9 +62,9 @@ class ComposerPackageArtifact implements PackageCacheInterface
      */
     private ?string $cacheIdentifier;
 
-    public function __construct(string $varPath, ?Filesystem $filesystem = null, string $cacheIdentifier = null)
+    public function __construct(string $packageArtifactsPath, ?Filesystem $filesystem = null, string $cacheIdentifier = null)
     {
-        $this->packageArtifactsFile = $varPath . self::ARTIFACTS_FILE;
+        $this->packageArtifactsFile = $packageArtifactsPath . self::ARTIFACTS_FILE;
         $this->filesystem = $filesystem;
         $this->cacheIdentifier = $cacheIdentifier;
     }
diff --git a/typo3/sysext/core/Documentation/Changelog/11.4/Important-95647-ComposerInstallationsAndExtensionUsage.rst b/typo3/sysext/core/Documentation/Changelog/11.4/Important-95647-ComposerInstallationsAndExtensionUsage.rst
index 98a0d1c39f1d..54ea00676361 100644
--- a/typo3/sysext/core/Documentation/Changelog/11.4/Important-95647-ComposerInstallationsAndExtensionUsage.rst
+++ b/typo3/sysext/core/Documentation/Changelog/11.4/Important-95647-ComposerInstallationsAndExtensionUsage.rst
@@ -44,9 +44,16 @@ contain this file e.g. under version control, the file can safely be removed.
 Use the TYPO3 CLI command :shell:`extension:setup` to set up all extensions
 available in Composer.
 
+Package information (like paths or extension meta data) is still stored in and evaluated from
+a file in Composer's :file:`vendor` folder. This file is written after Composer dumps autoload information.
+Make sure all files from that (:file:`vendor`) folder are transferred during a deployment.
+This means no special action compared to previous TYPO3 versions is required regarding the :file:`vendor` folder
+with TYPO3 11 LTS.
+
 .. Important::
-   As a successor, the :file:`var/build/PackageArtifact.php` is used which also
-   needs to be deployed.
+   TYPO3 version 11.5.0 to 11.5.2 stored package information in :file:`var/build/` folder,
+   which previously required this folder to be transferred as well during a deployment.
+   This is not required any more now. Transferring the :file:`vendor` folder is sufficient now.
 
 All extensions are always active
 --------------------------------
-- 
GitLab