Skip to content

Map the PSR-4 autoloader to the OpenMage\ComposerPlugin namespace - #13

Open
kasper-agg wants to merge 1 commit into
OpenMage:mainfrom
kasper-agg:fix/psr4-namespace-prefix
Open

kasper-agg wants to merge 1 commit into
OpenMage:mainfrom
kasper-agg:fix/psr4-namespace-prefix

Conversation

@kasper-agg

Copy link
Copy Markdown

Description

composer.json maps the empty PSR-4 prefix to src/:

"psr-4": {
    "": "src/"
}

An empty prefix is a fallback for every class. Unless a project uses an authoritative classmap (classmap-authoritative), Composer's autoloader therefore checks vendor/openmage/composer-plugin/src/<Class>.php for every class it doesn't find in its classmap. In OpenMage that's every Magento class (app/code, lib/Varien, zf1), on every request. Composer's autoloader is registered before Varien_Autoload, so this lookup happens first, for each class.

Traced on a stock OpenMage install (strace -e trace=%file, loading five classes):

access(".../vendor/openmage/composer-plugin/src/Mage_Core_Model_App.php", F_OK) = -1 ENOENT
access(".../vendor/openmage/composer-plugin/src/Varien_Object.php", F_OK) = -1 ENOENT
access(".../vendor/openmage/composer-plugin/src/Mage_Catalog_Model_Product.php", F_OK) = -1 ENOENT
access(".../vendor/openmage/composer-plugin/src/Zend_Db_Select.php", F_OK) = -1 ENOENT
access(".../vendor/openmage/composer-plugin/src/Foo_Missing_Class.php", F_OK) = -1 ENOENT

One failed file lookup per class. PHP doesn't cache paths that don't exist, so each one reaches the filesystem.

All classes in src/ are in the OpenMage\ComposerPlugin namespace, so this PR maps only that prefix:

"psr-4": {
    "OpenMage\\ComposerPlugin\\": "src/OpenMage/ComposerPlugin/"
}

Effect

  • With this mapping, the same trace shows 0 lookups in vendor/openmage/composer-plugin/src/.
  • The plugin's own classes load as before. Checked on a stock OpenMage install with the mapping applied: class_exists() finds OpenMage\ComposerPlugin\Plugin and the copy plugins, and Composer still loads the plugin (composer -vvv shows "Loading plugin OpenMage\ComposerPlugin\Plugin").
  • No code changes. Plugin::getPlugins() derives class names from the files' namespace lines, and those are unchanged.
  • Shops that already use classmap-authoritative see no difference.

OpenMage gets the benefit after a release of this package and a composer update openmage/composer-plugin.

Checks

  • composer phpunit:test: OK (50 tests, 50 assertions).
  • composer phpstan: no errors.
  • composer validate: valid. It only warns about the existing unbound * constraints for symfony/filesystem and symfony/finder.
  • composer rector:test fails with Unknown named parameter $strictBooleans, also without this change. .rector.php uses a parameter that newer Rector versions (allowed by ^2.1.2) no longer accept. This is unrelated to this PR, so I've left it alone.

Context

Found while looking into failed file lookups in OpenMage's autoloading, see OpenMage/magento-lts#5722 and OpenMage/magento-lts#5787.

The empty PSR-4 prefix ("": "src/") is a fallback for every class.
Without an authoritative classmap, Composer's autoloader then checks
vendor/openmage/composer-plugin/src/<Class>.php for every class it
doesn't know, which in OpenMage is every Magento class, on every request.

All classes in src/ are in the OpenMage\ComposerPlugin namespace, so map
only that prefix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant