Diff for Project/NoMorePear between 15 and 16


+ No More Pear: Move to composer

Remove any hard runtime or installation dependency on pear and pearisms

++ Bugs

List any tickets on http://bugs.horde.org/ that cover this issue or are relevant to it.

++ People

Ralf Lang

++ Description

The PHP ecosystem has increasingly moved from pear to composer as the default installer. The changed paradigm (global versus local dependency management) attracts many users and developers.

+++ Runtime dependencies

++++ horde-db-migrate and web migrator

horde-db-migrate "forgets" to migrate or even acknowledge libraries in git checkouts where the pear channel is not present. 

++++ l10n/translation tools?

+++ Document .horde.yml format and how it relates to composer json and pear xml

See ((Doc/Dev/HordeYmlFormat|Developer Doc on .horde.yml format)) for both original format and proposed additions.

+++ Installation

++++ Generate composer json file from .horde.yml

[DONE] components/lib/Helper/Composer.php currently depends on conductor and gets its data from package.xml
anything handling package.xml is broken without pear though. Always need to register the horde channel

[DONE] rewrite all pear.horde.org dependencies to vcs type dependencies github/horde/ 


Other resources
Do we want to keep a whitelist of other channels/packages which should be pulled from packagist or github rather than pear?

++++ Composer plugin: install apps below base rather than vendor/

(we don't want /vendor/ web-readable)
[DONE] horde apps are type "horde-application" and get installed to /$appname or base/appname
Installing/updating an app should clear cache and autoloader cache
[DONE] Check if the app provides a registry snippet in /doc/registry.d/
[DONE] write horde.local.php if necessary
[WONTDO SEE BELOW] installing base should provide some initialization
[DONE] The installer allows the deployment/bundle to provide pre-made configs for horde and apps

++++ Composer plugin: copy, move or link js content from libraries to horde/js
[DONE] horde libs are type "horde-library" and get installed to /vendor/Horde/Foo
[DONE] js/ dir content of horde-library packages and the horde base app are copied or linked to web/js/
[DONE] automatically rewrite registry path of hordeJs fileroot and webroot to web/js/

+++ Packagist

Add tool chain to create and update packages on packagist for easier consumption.

+++ Autoloading and fixed loading
++++ Examining horde base bootstrapping:

[NO TODO] horde/horde/index.php require_once lib/Application
[NO TODO]Horde/Application.php require_once core.php
[DONE] core.php checks for horde.local.php  -- composer installer will write necessary autoloading instructions there.
[DONE] Either include_once Horde/Autoloader/Cache.php or require_once Horde/Autoloader/Default.php - fixed by adding a search path

++++ Examining nag bootstrapping:
horde/nag/index.php and other client pages require_once nag/lib/Application.php
nag probes for horde_dir (either info from horde.local.php or directory above nag dir)
finally load (hordedir)/lib/core.php

-> both in base and apps, we can edit horde.local.php for hinting and autoloader ultimately comes from horde/lib/core.php

++++ Issues with Horde_Autoloader_Default and Horde_Autoloader_Cache

Horde_Autoloader_Default has unconditional require_onces
Horde_Autoloader_Default registers unconditionally when loaded
Horde_Autoloader_Cache requires/registers Horde_Autoloader_Default unconditionally

[DONE] Fixed by providing suitable search paths in horde.local.php

++++ Examining git-tools as a composer-native app:

git-tools binary detects the composer autoloader entrypoint vendor/autoload.php and require_once it.
the composer autoloader is configured to provide a psr-4 autoloader for the \\Horde\\GitTools namespace to ./lib

++++ PSR-0, db migrations, classmaps and packages

Most horde library packages are simple to map to the psr-0 autoloader.
Package Horde_Foo would have all its classes in lib/Horde/Foo. 

Some packages though have class names you would not expect from the package name
Horde_Core has Horde_ErrorHandler & friends
Horde_Form has multiple classes in one file
Horde_Util has Horde_String

These either need to be scanned for additional mappings or need "classmap" style autoload hints.
[UNSURE] Unit tests should be marked as autoload-dev (root package only autoloads)
[DONE] migrations should be autodetected by the composer writer.
[DONE] special case classmaps should be hinted by .horde.yml

++++ Horde_Test
Horde_Test bundles phpunit. A Horde Library uses a copy of boilerplate code from horde_test to initialize autoloading. This boilerplate makes some PEARish assumptions (universal include hierarchy)

This pull request offers a new template and fixes other unconditional require_once instances https://github.com/horde/Test/pull/1
This should hopefully work for PEAR installs, composer installs and full git checkouts just the same.

[DONE] Running the unit tests via the components app, when installed into a composer deployment, is also possible without fixing AllTests & friends.

++ Proof of concept

There is a proof of concept in https://github.com/maintaina-com
This proof of concept includes all software patches which are part of this effort

+++ components and git-tools
In this project, the components tool is used via git-tools as a frontend or as an installed app via composer exec horde-components.

Various patches have been applied. Most relevant is a rewrite of the Components_Helper_Composer class.

This class now writes a thoroughly different composer file than before and it takes its data from .horde.yml
rather than package.xml

To generate a new composer.json file for an app, run

composer exec -v horde-components web/$app/ composer

To generate a new composer.json file for a library, run

composer exec -v horde-components vendor/horde/$lib composer

Mind providing a useful config for horde-components first

config options govern 
- if we want to build against dev-master dependencies or dependencies using the horde.yml version constraints
- if we assume all packages live on packagist, in a shared satis repo or a per-library git location
- how to translate non-horde pear dependencies into packagist dependencies (otherwise, pear channels will be used)

++++ components release command

The components release command needs some additions to make this practical

* [TODO] The composer file needs to be written with different options twice: It should use dev-master requirements in the master branch, but use versioned requirements as stated in the composer yaml file when writing a tagges release
* [TODO] There should be configureable hooks to either trigger a satis rewrite or a packagist upload
* [TODO] An easy way to perform downstream/inhouse releases omitting PEAR related stuff or upstream horde specific steps like updating the bug tracker. This should not involve lenghty command lines.

++++ Known issues

There is currently a problem with discerning commandline options (-X and --something) for the composer exec command from those for the components cli.

If your use case depends on using these switches (most notoriously, --depend), run the command instead using ./vendor/bin/horde-components ...

+++ Core, Base and Autoloader
Several patches were needed in places where horde just assumed files to always be in a certain location.
Most of these patches SHOULD NOT break git dev installs or pear installs - testing was very limited

Other relevant changes were detection of migration files in Horde_Core_Db_Migration and handling of Horde_Controller routes in 

+++ Test

The Horde_Test suite had some hardcoded requires which were made condidional.

+++ Other libraries

Unmentioned libraries SHOULD only have been modified by replacing the master branch composer file


++ Resources

https://getcomposer.org/doc/articles/custom-installers.md composer notes on custom installers and plugins
https://github.com/composer/installers multi-framework collection of installers
https://github.com/maglnet/ComposerRequireChecker Tool to find direct usage of indirect dependencies (Ensure you directly require all dependencies whose classes are referenced in own code)

Back to the ((Project|Project List))