Repository: humbug/php-scoper (php)

Issue:
Class `Composer\InstalledVersions` not found (again)
## Bug report

| Question    | Answer
| ------------| ---------------
| PHP-Scoper version | 3.16.0, 4.0.2
| PHP version | 8.1.7
| Platform with version | Manjaro (ArchLinux)
| Composer | 2.2.1
| Github Repo | https://github.com/martinssipenko/php-scoper-issue


This is basically a reopen of https://github.com/humbug/php-scoper/issues/532 with new details. It still doesn't work. 

### How to reproduce?

```bash
git clone git@github.com:martinssipenko/php-scoper-issue.git
cd php-scoper-issue

composer install

wget -q https://github.com/humbug/box/releases/download/4.0.2/box.phar --output-document=./box
chmod +x box

./box compile

# and test generated PHAR
./test.phar
```

Result: 

 ```bash
 PHP Fatal error:  Uncaught Error: Class "_HumbugBoxc78d51bc45e9\Composer\InstalledVersions" not found in phar:///tmp/temp/php-scoper-issue/test.phar/cli.php:8
Stack trace:
#0 /tmp/temp/php-scoper-issue/test.phar(14): require()
#1 {main}
  thrown in phar:///tmp/temp/php-scoper-issue/test.phar/cli.php on line 8
 ```

### Workaround

If I add the following `scoper.inc.php`:

```php
return [
    'exclude-classes' => [\Composer\InstalledVersions::class],
    'exclude-files' => ['vendor/composer/InstalledVersions.php'],
];
```

then, after generating new `test.phar` everything works as expected. 

I think that PHP-Scoper (or Box) doesn't properly handle `vendor/composer/InstalledVersions.php` file. Without `scoper.inc.php`, this file is prefixed (has a prefix in a namespace), however `vendor/composer/autoload_classmap.php` contains not prefixed key:

```php
<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',

    // ^^^^^^ look at this, it's not prefixed
);
```

Related to https://github.com/infection/infection/pull/1708

Pull request:
Fix InstalledVersions not found
Closes #678

Patch:
diff --git a/Makefile b/Makefile
index 5e190cd..5e38f84 100644
--- a/Makefile
+++ b/Makefile
@@ -155,7 +155,7 @@ blackfire: vendor
 
 .PHONY: e2e
 e2e:	 ## Runs end-to-end tests
-e2e: e2e_004 e2e_005 e2e_011 e2e_013 e2e_014 e2e_015 e2e_016 e2e_017 e2e_018 e2e_019 e2e_020 e2e_022 e2e_023 e2e_024 e2e_025 e2e_026 e2e_027 e2e_028 e2e_029 e2e_030 e2e_031 e2e_032 e2e_033
+e2e: e2e_004 e2e_005 e2e_011 e2e_013 e2e_014 e2e_015 e2e_016 e2e_017 e2e_018 e2e_019 e2e_020 e2e_022 e2e_023 e2e_024 e2e_025 e2e_026 e2e_027 e2e_028 e2e_029 e2e_030 e2e_031 e2e_032 e2e_033 e2e_034
 
 .PHONY: e2e_004
 e2e_004: ## Runs end-to-end tests for the fixture set 004 — Minimalistic codebase
@@ -495,6 +495,25 @@ e2e_033: $(PHP_SCOPER_PHAR_BIN)
 	diff fixtures/set033-user-global-function/expected-output build/set033-user-global-function/output
 
 
+
+.PHONY: e2e_034
+e2e_034: ## Runs end-to-end tests for the fixture set 034 — Leverage Composer InstalledVersions
+e2e_034: $(PHP_SCOPER_PHAR_BIN)
+	$(PHP_SCOPER_PHAR) add-prefix \
+		--working-dir=fixtures/set034-installed-versions \
+		--output-dir=../../build/set034-installed-versions \
+		--force \
+		--no-interaction \
+		--stop-on-failure
+
+	php fixtures/set034-installed-versions/index.php > fixtures/set034-installed-versions/expected-output
+
+	composer --working-dir=build/set034-installed-versions dump-autoload --no-dev
+	php build/set034-installed-versions/index.php > build/set034-installed-versions/output
+
+	diff fixtures/set034-installed-versions/expected-output build/set034-installed-versions/output
+
+
 #
 # Rules from files
 #---------------------------------------------------------------------------
diff --git a/fixtures/set034-installed-versions/composer.json b/fixtures/set034-installed-versions/composer.json
new file mode 100644
index 0000000..8aa1527
--- /dev/null
+++ b/fixtures/set034-installed-versions/composer.json
@@ -0,0 +1,6 @@
+{
+    "bin": "index.php",
+    "require": {
+        "nikic/iter": "^2.0"
+    }
+}
diff --git a/fixtures/set034-installed-versions/composer.lock b/fixtures/set034-installed-versions/composer.lock
new file mode 100644
index 0000000..856f1d1
--- /dev/null
+++ b/fixtures/set034-installed-versions/composer.lock
@@ -0,0 +1,69 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "0e88c545a234e507aec82c192563842e",
+    "packages": [
+        {
+            "name": "nikic/iter",
+            "version": "v2.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/nikic/iter.git",
+                "reference": "d1323929952ddcb0b06439991f93bde3816a39e9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/nikic/iter/zipball/d1323929952ddcb0b06439991f93bde3816a39e9",
+                "reference": "d1323929952ddcb0b06439991f93bde3816a39e9",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/iter.func.php",
+                    "src/iter.php",
+                    "src/iter.rewindable.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Nikita Popov",
+                    "email": "nikic@php.net"
+                }
+            ],
+            "description": "Iteration primitives using generators",
+            "keywords": [
+                "functional",
+                "generator",
+                "iterator"
+            ],
+            "support": {
+                "issues": "https://github.com/nikic/iter/issues",
+                "source": "https://github.com/nikic/iter/tree/v2.2.0"
+            },
+            "time": "2021-08-02T15:04:32+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": [],
+    "platform-dev": [],
+    "plugin-api-version": "2.3.0"
+}
diff --git a/fixtures/set034-installed-versions/expected-output b/fixtures/set034-installed-versions/expected-output
new file mode 100644
index 0000000..90b5016
--- /dev/null
+++ b/fixtures/set034-installed-versions/expected-output
@@ -0,0 +1,1 @@
+ok.
diff --git a/fixtures/set034-installed-versions/index.php b/fixtures/set034-installed-versions/index.php
new file mode 100644
index 0000000..44b1fbf
--- /dev/null
+++ b/fixtures/set034-installed-versions/index.php
@@ -0,0 +1,15 @@
+<?php declare(strict_types=1);
+
+namespace Acme;
+
+use Composer\InstalledVersions;
+use function file_exists;
+use const PHP_EOL;
+
+require file_exists(__DIR__.'/vendor/scoper-autoload.php')
+    ? __DIR__.'/vendor/scoper-autoload.php'
+    : __DIR__.'/vendor/autoload.php';
+
+if (InstalledVersions::isInstalled('nikic/iter')) {
+    echo "ok.".PHP_EOL;
+}
diff --git a/fixtures/set034-installed-versions/scoper.inc.php b/fixtures/set034-installed-versions/scoper.inc.php
new file mode 100644
index 0000000..03248da
--- /dev/null
+++ b/fixtures/set034-installed-versions/scoper.inc.php
@@ -0,0 +1,12 @@
+<?php
+
+use Isolated\Symfony\Component\Finder\Finder;
+
+return [
+    'finders' => [
+        (new Finder())
+            ->files()
+            ->in(__DIR__),
+    ],
+    'exclude-functions' => ['trigger_deprecation'],
+];
diff --git a/src/Autoload/ScoperAutoloadGenerator.php b/src/Autoload/ScoperAutoloadGenerator.php
index 4fdc9c6..781a234 100644
--- a/src/Autoload/ScoperAutoloadGenerator.php
+++ b/src/Autoload/ScoperAutoloadGenerator.php
@@ -79,6 +79,7 @@ final class ScoperAutoloadGenerator
 
                 namespace {
                     \$loader = require_once __DIR__.'/autoload.php';
+                    require_once __DIR__.'/composer/InstalledVersions.php';
                 }
 
                 {$statements}
@@ -95,6 +96,7 @@ final class ScoperAutoloadGenerator
                 // scoper-autoload.php @generated by PhpScoper
 
                 \$loader = require_once __DIR__.'/autoload.php';
+                require_once __DIR__.'/composer/InstalledVersions.php';
 
                 {$statements}
 


Test patch:
diff --git a/tests/Autoload/ScoperAutoloadGeneratorTest.php b/tests/Autoload/ScoperAutoloadGeneratorTest.php
index 70d0e5d..84ec067 100644
--- a/tests/Autoload/ScoperAutoloadGeneratorTest.php
+++ b/tests/Autoload/ScoperAutoloadGeneratorTest.php
@@ -45,6 +45,7 @@ class ScoperAutoloadGeneratorTest extends TestCase
                 // scoper-autoload.php @generated by PhpScoper
 
                 $loader = require_once __DIR__.'/autoload.php';
+                require_once __DIR__.'/composer/InstalledVersions.php';
 
                 return $loader;
 
@@ -65,6 +66,7 @@ class ScoperAutoloadGeneratorTest extends TestCase
                 // scoper-autoload.php @generated by PhpScoper
 
                 $loader = require_once __DIR__.'/autoload.php';
+                require_once __DIR__.'/composer/InstalledVersions.php';
 
                 // Exposed functions. For more information see:
                 // https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#exposing-functions
@@ -100,6 +102,7 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 namespace {
                     $loader = require_once __DIR__.'/autoload.php';
+                    require_once __DIR__.'/composer/InstalledVersions.php';
                 }
 
                 // Exposed functions. For more information see:
@@ -146,6 +149,7 @@ class ScoperAutoloadGeneratorTest extends TestCase
                 // scoper-autoload.php @generated by PhpScoper
 
                 $loader = require_once __DIR__.'/autoload.php';
+                require_once __DIR__.'/composer/InstalledVersions.php';
 
                 // Exposed classes. For more information see:
                 // https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#exposing-classes
@@ -172,6 +176,7 @@ class ScoperAutoloadGeneratorTest extends TestCase
                 // scoper-autoload.php @generated by PhpScoper
 
                 $loader = require_once __DIR__.'/autoload.php';
+                require_once __DIR__.'/composer/InstalledVersions.php';
 
                 // Exposed classes. For more information see:
                 // https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#exposing-classes
@@ -207,6 +212,7 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 namespace {
                     $loader = require_once __DIR__.'/autoload.php';
+                    require_once __DIR__.'/composer/InstalledVersions.php';
                 }
 
                 // Exposed classes. For more information see:
@@ -276,6 +282,7 @@ class ScoperAutoloadGeneratorTest extends TestCase
                 // scoper-autoload.php @generated by PhpScoper
 
                 $loader = require_once __DIR__.'/autoload.php';
+                require_once __DIR__.'/composer/InstalledVersions.php';
 
                 // Exposed functions. For more information see:
                 // https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#exposing-functions
@@ -306,6 +313,7 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 namespace {
                     $loader = require_once __DIR__.'/autoload.php';
+                    require_once __DIR__.'/composer/InstalledVersions.php';
                 }
 
                 // Exposed functions. For more information see: