Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
I'm having a hell of a time trying to get X Autoload to pull in Mockery via hook_libraries_info() leveraging its composer.json.
I've tried this:
/**
* Implements hook_libraries_info().
*/
function hammock_libraries_info() {
$libraries = array();
$libraries['mockery'] = array(
'name' => 'Mockery',
'vendor url' => 'http://docs.mockery.io/',
'download url' => 'https://github.com/padraic/mockery/releases',
'download file url' => 'https://github.com/padraic/mockery/archive/master.zip',
'version arguments' => array(
'file' => 'CHANGELOG.md',
'pattern' => '@##\s+([0-9a-zA-Z\.-]+)\s+\([0-9X]{4}-[0-9X]{2}-[0-9X]{2}\)@',
'lines' => 5,
'cols' => 64,
),
'xautoload' => function($adapter) {
/** @var \Drupal\xautoload\Adapter\LocalDirectoryAdapter $adapter */
$adapter->composerJson('composer.json');
},
);
This works for everything inside the \Mockery
namespace (library/Mockery/*
), but causes the Mockery
class that exists outside a namespace, at the root (library/Mockery.php
), to be missed by the auto-loader. It strikes me as odd that the root class is just chilling outside a namespace like that.
How do I reconcile this? Is this an error with Mockery itself, or just natural ambiguity from PSR-0?
Comments
Comment #2
GuyPaddock CreditAttribution: GuyPaddock at RedBottle Design, LLC for Inveniem commentedComment #3
GuyPaddock CreditAttribution: GuyPaddock at RedBottle Design, LLC for Inveniem commentedChanging the
xautoload
to this seems to have worked, but seems like a hack:Is there a better approach?
Comment #4
GuyPaddock CreditAttribution: GuyPaddock at RedBottle Design, LLC for Inveniem commentedFor anyone coming across this ticket for reference, though I still haven't found a way, the complete module is here:
https://www.drupal.org/sandbox/guypaddock/2870229
Comment #5
donquixote CreditAttribution: donquixote as a volunteer commentedYes, your quick solution works.
But we should also fix this in xautoload.
From https://github.com/composer/composer/blob/master/src/Composer/Autoload/C... I conclude:
-
"Mockery": "library/"
does make library/Mockery.php autoloadable.-
"Mockery\\": "library/"
does NOT make library/Mockery.php autoloadable, but is otherwise equivalent.In xautoload, the behavior is currently the same in both cases. Mockery.php is never autoloadable, unless it is explicitly added.
The correct behavior needs to be implemented in ClassFinderAdapter::add() and ClassFinderAdapter::addMultiplePsr0().
We need to:
- Detect if the prefix/namespace ends with a separator.
- If yes, remove the separator and register the prefix/namespace directory mapping.
- If no, register the refix/namespace directory mapping AND register the toplevel class file in the classmap. I would expect this to be fine even if the class file does not exist, because the xautoload class loader does contain a file_exists() when loading classes from the classmap.
If you are interested in producing a patch, please consider
- first confirm that Composer actually works as described above!
- add test cases to cover this edge case.
Comment #6
donquixote CreditAttribution: donquixote as a volunteer commentedBtw, the main reason I added this composer.json functionality was "because I can".
At the time nobody did ask for it, and I did not have an actual use case.
There are alternative to deal with Composer libraries in Drupal, e.g. composer_manager.
But still, any existing functionality in xautoload should behave according to expectations!
Just saying if this is confirmed then this can be elevated to "bug".
But make it "minor" because it is not more like a "bonus" functionality.