From adc94bb9031321a40f37d923b6768d82aef8551e Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Wed, 13 May 2026 07:09:15 +0200 Subject: [PATCH] fix(autoload): don't PSR-4-map OCA\OpenRegister\ in autoload-dev (shadows real OR) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `composer.json` mapped `OCA\\OpenRegister\\ → tests/Stubs/` in `autoload-dev`, and `tests/Stubs/Db/ObjectEntity.php` is an abstract stub. When SoftwareCatalog's `vendor/` is built with a plain `composer install` (i.e. *with* dev deps — which is what happens on dev installs / wherever the deployed vendor isn't `--no-dev`), the dev autoloader is active, so `vendor/composer/autoload_psr4.php` and the classmap map `OCA\OpenRegister\Db\ObjectEntity` → `tests/Stubs/Db/ObjectEntity.php`. Each enabled app's `vendor/autoload.php` is registered globally, and Composer's class loader prepends — so SoftwareCatalog's mapping shadows the **real** `OCA\OpenRegister\Db\ObjectEntity` for *all* apps. OpenRegister's own `MagicSearchHandler::convertRowToObjectEntity()` then does `new ObjectEntity()` and PHP fatals with "Cannot instantiate abstract class". That takes down OR's entire object-read path (and therefore every OR-backed app — OpenBuilt, DocuDesk, OpenCatalogi, …) on any dev install that has SoftwareCatalog enabled. Drop the `autoload-dev` PSR-4 mapping (and the now-empty `autoload-dev` block). Load the stubs from `tests/bootstrap.php` instead — conditionally, only when the real `OCA\OpenRegister\Db\ObjectEntity` isn't autoloadable (i.e. running unit tests without a live OpenRegister installed). Production deployments now never see the stub regardless of how `vendor/` was built, and the unit tests keep their explicit getter/setter surface for the magic-`__call` mock surface they need. Closes #230. --- composer.json | 5 ----- tests/bootstrap.php | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 12d74c6d..b538ce8a 100644 --- a/composer.json +++ b/composer.json @@ -14,11 +14,6 @@ "OCA\\SoftwareCatalog\\": "lib/" } }, - "autoload-dev": { - "psr-4": { - "OCA\\OpenRegister\\": "tests/Stubs/" - } - }, "scripts": { "post-install-cmd": [ "@composer bin all install --ansi" diff --git a/tests/bootstrap.php b/tests/bootstrap.php index fd6806ed..31f7ba7c 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -36,10 +36,23 @@ // Load all enabled apps \OC_App::loadApps(); - + // Load our specific app \OC_App::loadApp('softwarecatalog'); - + // Clear hooks for testing OC_Hook::clear(); } + +// OpenRegister test stubs. The real OCA\OpenRegister\Db\ObjectEntity has +// __call magic getters that PHPUnit can't configure on a mock, so the unit +// tests use the explicit stub in tests/Stubs/. It is loaded HERE — not via a +// composer `autoload-dev` PSR-4 mapping of the foreign `OCA\OpenRegister\` +// namespace, which would shadow the real OpenRegister classes in any +// deployment whose vendor/ includes dev autoload entries (breaking every +// OR-backed app). Only loaded when OpenRegister isn't actually installed. +if (!class_exists('OCA\\OpenRegister\\Db\\ObjectEntity')) { + foreach (glob(__DIR__ . '/Stubs/{,**/}*.php', GLOB_BRACE) ?: [] as $stub) { + require_once $stub; + } +}