Repository: humbug/php-scoper (php)

Issue:
Fatal error: Cannot redeclare humbug_phpscoper_expose_class()
## Bug report

| Question    | Answer
| ------------| ---------------
| PHP-Scoper version | 0.18.1 |
| PHP version | 8.1 |
| Platform with version | MacOS 13 |
| Github Repo | https://github.com/leoloso/PoP |


I'm using PHP-Scoper to scope 2 WordPress plugins. When I install both of them on the same site, I get the following error:

```
Fatal error: Cannot redeclare humbug_phpscoper_expose_class() (previously declared in /app/wordpress/wp-content/plugins/graphql-api/vendor/scoper-autoload.php:23) in /app/wordpress/wp-content/plugins/graphql-api-pro/vendor/scoper-autoload.php on line 27
```

The reason is clear: both plugins define function `humbug_phpscoper_expose_class` in the global space.

Maybe we can append `if(!function_exists('humbug_phpscoper_expose_class')) { ...` when [declaring the function](https://github.com/humbug/php-scoper/blob/f7bd92f2459f1d9a643313f6d324476b0e23e087/src/Autoload/ScoperAutoloadGenerator.php#L44-L50)?

For reference, this is [one of my `scoper.inc.php`](https://github.com/leoloso/PoP/blob/1a7cda04a30e4426fd34516788f8155c7f16849f/ci/scoping/scoper-graphql-api.inc.php).




Pull request:
Check if function `humbug_phpscoper_expose_class` exists
Fixes #809

@theofidry I can't run the tests locally, as `composer update` is failing (am I doing something wrong?):

```
  Problem 1
    - humbug/box[4.0.0, ..., 4.2.0] require composer-plugin-api ^2.2 -> found composer-plugin-api[2.1.0] but it does not match the constraint.
    - Root composer.json requires humbug/box ^4.0 -> satisfiable by humbug/box[4.0.0, ..., 4.2.0].
```

But I can see the tests are passing here on GitHub

Patch:
diff --git a/src/Autoload/ScoperAutoloadGenerator.php b/src/Autoload/ScoperAutoloadGenerator.php
index e522737..7afab5c 100644
--- a/src/Autoload/ScoperAutoloadGenerator.php
+++ b/src/Autoload/ScoperAutoloadGenerator.php
@@ -42,9 +42,11 @@ final class ScoperAutoloadGenerator
         EOF;
 
     private const EXPOSE_CLASS_DECLARATION = <<<'PHP'
-        function humbug_phpscoper_expose_class(string $exposed, string $prefixed): void {
-            if (!class_exists($exposed, false) && !interface_exists($exposed, false) && !trait_exists($exposed, false)) {
-                spl_autoload_call($prefixed);
+        if (!function_exists('humbug_phpscoper_expose_class')) {
+            function humbug_phpscoper_expose_class(string $exposed, string $prefixed): void {
+                if (!class_exists($exposed, false) && !interface_exists($exposed, false) && !trait_exists($exposed, false)) {
+                    spl_autoload_call($prefixed);
+                }
             }
         }
         PHP;


Test patch:
diff --git a/tests/Autoload/ScoperAutoloadGeneratorTest.php b/tests/Autoload/ScoperAutoloadGeneratorTest.php
index 789754e..346f079 100644
--- a/tests/Autoload/ScoperAutoloadGeneratorTest.php
+++ b/tests/Autoload/ScoperAutoloadGeneratorTest.php
@@ -279,9 +279,11 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 // Class aliases. For more information see:
                 // https://github.com/humbug/php-scoper/blob/master/docs/further-reading.md#class-aliases
-                function humbug_phpscoper_expose_class(string $exposed, string $prefixed): void {
-                    if (!class_exists($exposed, false) && !interface_exists($exposed, false) && !trait_exists($exposed, false)) {
-                        spl_autoload_call($prefixed);
+                if (!function_exists('humbug_phpscoper_expose_class')) {
+                    function humbug_phpscoper_expose_class(string $exposed, string $prefixed): void {
+                        if (!class_exists($exposed, false) && !interface_exists($exposed, false) && !trait_exists($exposed, false)) {
+                            spl_autoload_call($prefixed);
+                        }
                     }
                 }
                 humbug_phpscoper_expose_class('A\Foo', 'Humbug\A\Foo');
@@ -323,9 +325,11 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 // Class aliases. For more information see:
                 // https://github.com/humbug/php-scoper/blob/master/docs/further-reading.md#class-aliases
-                function humbug_phpscoper_expose_class(string $exposed, string $prefixed): void {
-                    if (!class_exists($exposed, false) && !interface_exists($exposed, false) && !trait_exists($exposed, false)) {
-                        spl_autoload_call($prefixed);
+                if (!function_exists('humbug_phpscoper_expose_class')) {
+                    function humbug_phpscoper_expose_class(string $exposed, string $prefixed): void {
+                        if (!class_exists($exposed, false) && !interface_exists($exposed, false) && !trait_exists($exposed, false)) {
+                            spl_autoload_call($prefixed);
+                        }
                     }
                 }
                 humbug_phpscoper_expose_class('Foo', 'Humbug\Foo');
@@ -376,9 +380,11 @@ class ScoperAutoloadGeneratorTest extends TestCase
                 // Class aliases. For more information see:
                 // https://github.com/humbug/php-scoper/blob/master/docs/further-reading.md#class-aliases
                 namespace {
-                    function humbug_phpscoper_expose_class(string $exposed, string $prefixed): void {
-                        if (!class_exists($exposed, false) && !interface_exists($exposed, false) && !trait_exists($exposed, false)) {
-                            spl_autoload_call($prefixed);
+                    if (!function_exists('humbug_phpscoper_expose_class')) {
+                        function humbug_phpscoper_expose_class(string $exposed, string $prefixed): void {
+                            if (!class_exists($exposed, false) && !interface_exists($exposed, false) && !trait_exists($exposed, false)) {
+                                spl_autoload_call($prefixed);
+                            }
                         }
                     }
                     humbug_phpscoper_expose_class('A\Foo', 'Humbug\A\Foo');