I've been using Composer for other PHP projects (as well as NPM for Node.js), and find the feature set very compelling. One nicety of these systems is their ability to manage requirements at the level of the top-layer application. Unfortunately, though, Drupal doesn't do this yet. But thinking about it, we might be able to create something like this even while Core isn't yet moving this way.

What if we build a module (as part of this Composer project) with the following featureset:

  • The module scans all of the other installed modules for composer.json files, and can manage dependencies for all of the modules.
  • The module provides the specific location for placing the vendor/ directory. All dependencies can then go in this module's vendor directory. Centralizing the repo has the dual advantage of being easier for humans to work with, and much easier on autoloaders and utilities.
  • The module provides both composer autoloader support and utility functions for manually including files in the vendor directory
  • The drush script would continue to play the crucial role of executing composer.phar to install and update packages.

I would envision the workflow to be something like this:

A module maintainer declares external library dependencies with a composer.json file.

A module maintainer writes code that loads these libraries with a function like composer_include() or something similar. (Or the maintainer can rely upon an autoloader).

A system admin uses the drush script to execute something like drush composer-update to update all dependencies, or (with a subsequent argument specifying the module) just the libraries required by a certain module.

Comments

mbutcher’s picture

And in case it wasn't already clear -- I'm volunteering to help with that.

robloach’s picture

Very interesting! Very curious as to how it would be implemented.

robloach’s picture

What about having that as a "vendor" module instead?

robloach’s picture

Maybe something like this? #1452984: drush composer-mass install

robloach’s picture

Over at #1316322: Add PSR-0 autoloader to drush, I put together a small function that facilitates Composer upgrades of a given composer.json file into a provided directory. We might be able to use this to allow Drupal Composer dependencies to install themselves into the files directory.

robloach’s picture

jbeckers’s picture

patcon’s picture

Thanks for the heads up @jbeckers!

openbees’s picture

Category: feature » task
Priority: Normal » Minor

Hello mbutcher . I am working for same functionality in SilverStripe CMS as GSOC 2012 Project . Its good to see that drupal is also going to include this feature. Please let me know if i can help you in this project .

patcon’s picture

@openbees I'd definitely submit a pull request for SilverStripe here:
https://github.com/composer/installers/tree/master/src/Composer/Installers

I love this. Perfect example of why implementing a full-fledged package manager into the Drupal ecosystem is full of so much win -- we're working on totally different CMS's, but we can contribute code to a common project :)

donquixote’s picture

Priority: Minor » Normal

Here is how it can work:
#542940-53: [meta] Support for downloading libraries via Composer

Idea:

  • Introduce a new key in modulename.info, to declare composer dependencies. (e.g. "composer[] = .." or "composer.require[] = ..")
  • sites/all/composer directory (or similar) for composer-provided libraries. D8 can have a different place, because sites/all/ is on longer the place-for-everything.
  • Libraries module will report problems or refuse modules from being enabled, if essential composer libraries are missing.
  • Libraries module makes sure that some class loading solution is in place. Either it includes the composer-provided autoload.php, or it registers the namespaces in xautoload or classloader, whatever is currently available.
  • drush composer-install-all to scan for missing libraries site-wide (using information from info files and more) and install them.
donquixote’s picture

And ...
#542940-55: [meta] Support for downloading libraries via Composer

Rethinking this:
Actually there is no reason why this all has to be parts of libraries module.

There are several reasons to make this a separate module:
1. There is very little in current libraries module, which this composer stuff could build on.
2. Composer libraries should live outside of sites/all/libraries (imo)
3. It is easier to specify a dependency for a new module (e.g. "composer_libraries") than for a specific version of libraries module.
4. The new module can have its own issue queue, versioning etc.
5. Libraries can continue to do the job for non-composer libraries.

The little problem: The most logical name for this module ("composer") is already taken by a drush extension. What we need is a regular module which can be installed on-site. I don't know whether it is feasible to turn composer from a drush extension project to a regular module, and what would be the implications of that.

donquixote’s picture

@Rob Loach:
It would be great if we could come to some conclusion here.
We need one module on D7 which can be installed (so it's more than just a drush command), and manage composer libraries.
This can be either
- the composer module itself (but then it has to give up its drush-only status), or
- the libraries module (concerns in #14)
- a separate module. I can only think of stupid names, aka "composine" or "compositor" or "compositionitor" etc.

I would much prefer the first option, because "composer" is the only reasonable module name for this. Would that be realistic?

robloach’s picture

Jimmy Berry put together the Composer Autoload module that will load dependencies installed via Composer. Is that what you meant? I've made a note of that on the Drush Composer project page, but I think it should be highlighted more clearly. What are your thoughts on an Integration doc with a list of modules that use Composer?

donquixote’s picture

I wish I wouldn't write so much, now I have to read it all ..

I think class loading is just one part of the problem.
The other is dependency management, e.g. refusing to enable a module if the composer library is missing. This can only be achieved by a real module, because people can enable modules without drush.
And having a default location for the composer libraries, e.g. sites/all/composer.
Another might be e.g. to recognize modules shipped with composer packages, and register them with hook_system_info_alter(), even though they are outside of the regular module directories.

I'm not sure atm what else we need that cannot be provided by a drush command.
We could just say that everything that doesn't fit in drush should go into composer_autoload, even if that is not strictly autoload related.
I would not be completely happy with the name, as autoload suggests that it's really only about class loading. But whatever.

-----

Ok, so now we should agree on a few standards for composer in D7.
- composer libraries to go into sites/all/composer by default? I think it would really help to have a default location.
- how can modules declare composer dependencies? For D7 I would still suggest the info file. A module is not a package, it can only be seen as "part of a package", if anything. And a module depending on a package is not the same as a package depending on a package. The module's dependency only activates when the module is enabled, not when it is downloaded.

mile23’s picture

Drupal 8 has /core/vendor, which I think isn't the greatest idea (since it implies that it's only vendors for core, not anyone else). But I understand why.

For Drupal 7, /sites/vendor (or I suppose /sites/composer) would be reasonable.

Mostly, right now I need a place to put behat for site-wide, non-Drupal-dependent tests, but which nevertheless test the Drupal site. Currently it's /[top-level]/tests/vendor alongside /[top-level]/drupal/[drupal-stuff]. It seems really lopsided and inelegant to not be able to integrate such tests into the Drupal file structure.

See also the behat integration module: #1377382: module feature roadmap Also 'scenario,' which is a drush extension to run behat tests: http://drupal.org/sandbox/rz/1703180

I have a feeling this topic of composer integration needs more brains on the matter. For instance: #1852512: Directory structure is fail, part 1: Composer

Thanks for the effort, folks.

Haehnchen’s picture

we can also provide our custom packagist service for the composer. i have created a simple parser for drupal projects. So currently modules, themes, ... are available for the composer.

#1886820: Packagist for Drupal Projects

_wdm_’s picture

Needing something that would work for D7 I have created the following module:
http://drupal.org/project/composer_vendor
Not sure how relevant this is to this issue.

donquixote’s picture

#20
sites/all/vendor seems like an ok default directory, for D7 at least.
sites/all/composer.json - yep.
It would be great if drush_composer could generate the composer.json from module-provided information.
To do that, it would have to determine not just which modules exist in the filesystem, but which of them have been enabled.

Because sites/all/ is across multisite, the composer.json needs to have combined information from all sites. This could be a challenge.
And if we have version requirement conflicts between the different sites of a multisite, then some composer packages might have to go into sites/modulename/vendor.

_wdm_’s picture

I did a little messing about with that before I created the composer_vendor module. The problem was that you could only have one composer autoload otherwise you got a duplicate class error.

I believe composer is being worked on currently to try and fix the problem.

donquixote’s picture

Can't we just read the autoload information directly from autoload_namespaces.php and autoload_classmap.php, and register to our own class loader?

@_wdm_, can you test this patch on xautoload?
This should do the same that you achieve with your composer_vendor module, but also allows sites/$sitename/vendor, without the duplicate class error.
#1923724-1: Composer support for sites/all/vendor and sites/$sitename/vendor

donquixote’s picture

@_wdm_,
I realize your module does also check requirements, that is, detect missing composer libraries. This is something that indeed deserves a dedicated module, and should not just be part of xautoload.

robloach’s picture

Automatically closed -- issue fixed for 2 weeks with no activity.