\documentclass{article}
\usepackage{ulem}
\usepackage{graphicx}
\usepackage{hyperref}
\pagestyle{headings}
\begin{document}
\part{No More Pear: Move to composer}
Remove any hard runtime or installation dependency on pear and pearisms

\section{Bugs}
List any tickets on <a href="http://bugs.horde.org/">http://bugs.horde.org/</a> that cover this issue or are relevant to it.

\section{People}
Ralf Lang

\section{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.

\subsection{Runtime dependencies}
\subsubsection{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.<br />
<a href="https://github.com/horde/Core/pull/2">https://github.com/horde/Core/pull/2</a>

\subsubsection{l10n/translation tools?}
\subsection{Document .horde.yml format and how it relates to composer json and pear xml}
See <a href="https://wiki.horde.org/Doc/Dev/HordeYmlFormat">Developer Doc on .horde.yml format</a> for both original format and proposed additions.

\subsection{Installation}
\subsubsection{Generate composer json file from .horde.yml}
<a href="https://wiki.horde.org/DONE">DONE</a> components/lib/Helper/Composer.php currently depends on conductor and gets its data from package.xml<br />
anything handling package.xml is broken without pear though. Always need to register the horde channel

<a href="https://wiki.horde.org/DONE">DONE</a> rewrite all pear.horde.org dependencies to vcs type dependencies github/horde/

<a href="https://github.com/horde/components/pull/3">https://github.com/horde/components/pull/3</a>

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

\subsubsection{Composer plugin: install apps below base rather than vendor/}
(we don't want /vendor/ web-readable)<br />
<a href="https://wiki.horde.org/DONE">DONE</a> horde apps are type "horde-application" and get installed to /\$appname or base/appname<br />
Installing/updating an app should clear cache and autoloader cache<br />
<a href="https://wiki.horde.org/DONE">DONE</a> Check if the app provides a registry snippet in /doc/registry.d/<br />
<a href="https://wiki.horde.org/DONE">DONE</a> write horde.local.php if necessary<br />
<a href="https://wiki.horde.org/WONTDO">SEE BELOW</a> installing base should provide some initialization<br />
<a href="https://wiki.horde.org/DONE">DONE</a> The installer allows the deployment/bundle to provide pre-made configs for horde and apps

\subsubsection{Composer plugin: copy, move or link js content from libraries to horde/js}
<a href="https://wiki.horde.org/DONE">DONE</a> horde libs are type "horde-library" and get installed to /vendor/Horde/Foo<br />
<a href="https://wiki.horde.org/DONE">DONE</a> js/ dir content of horde-library packages and the horde base app are copied or linked to web/js/<br />
<a href="https://wiki.horde.org/DONE">DONE</a> automatically rewrite registry path of hordeJs fileroot and webroot to web/js/

\subsection{Packagist}
Add tool chain to create and update packages on packagist for easier consumption.

\subsection{Autoloading and fixed loading}
\subsubsection{Examining horde base bootstrapping:}
<a href="https://wiki.horde.org/NO">TODO</a> horde/horde/index.php require\_once lib/Application<br />
<a href="https://wiki.horde.org/NO">TODO</a>Horde/Application.php require\_once core.php<br />
<a href="https://wiki.horde.org/DONE">DONE</a> core.php checks for horde.local.php  -- composer installer will write necessary autoloading instructions there.<br />
<a href="https://wiki.horde.org/DONE">DONE</a> Either include\_once Horde/Autoloader/Cache.php or require\_once Horde/Autoloader/Default.php - fixed by adding a search path

\subsubsection{Examining nag bootstrapping:}
horde/nag/index.php and other client pages require\_once nag/lib/Application.php<br />
nag probes for horde\_dir (either info from horde.local.php or directory above nag dir)<br />
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

\subsubsection{Issues with Horde\_Autoloader\_Default and Horde\_Autoloader\_Cache}
Horde\_Autoloader\_Default has unconditional require\_onces<br />
Horde\_Autoloader\_Default registers unconditionally when loaded<br />
Horde\_Autoloader\_Cache requires/registers Horde\_Autoloader\_Default unconditionally

<a href="https://wiki.horde.org/DONE">DONE</a> Fixed by providing suitable search paths in horde.local.php

\subsubsection{Examining git-tools as a composer-native app:}
git-tools binary detects the composer autoloader entrypoint vendor/autoload.php and require\_once it.<br />
the composer autoloader is configured to provide a psr-4 autoloader for the \textbackslash\{\}\textbackslash\{\}Horde\textbackslash\{\}\textbackslash\{\}<a href="https://wiki.horde.org/GitTools">GitTools</a> namespace to ./lib

\subsubsection{PSR-0, db migrations, classmaps and packages}
Most horde library packages are simple to map to the psr-0 autoloader.<br />
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<br />
Horde\_Core has Horde\_ErrorHandler \& friends<br />
Horde\_Form has multiple classes in one file<br />
Horde\_Util has Horde\_String

These either need to be scanned for additional mappings or need "classmap" style autoload hints.<br />
<a href="https://wiki.horde.org/UNSURE">UNSURE</a> Unit tests should be marked as autoload-dev (root package only autoloads)<br />
<a href="https://wiki.horde.org/DONE">DONE</a> migrations should be autodetected by the composer writer.<br />
<a href="https://wiki.horde.org/DONE">DONE</a> special case classmaps should be hinted by .horde.yml

\subsubsection{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 <a href="https://github.com/horde/Test/pull/1">https://github.com/horde/Test/pull/1</a><br />
This should hopefully work for PEAR installs, composer installs and full git checkouts just the same.

<a href="https://wiki.horde.org/DONE">DONE</a> Running the unit tests via the components app, when installed into a composer deployment, is also possible without fixing <a href="https://wiki.horde.org/AllTests">AllTests</a> \& friends.

\section{Proof of concept}
There is a proof of concept in <a href="https://github.com/maintaina-com">https://github.com/maintaina-com</a><br />
This proof of concept includes all software patches which are part of this effort

\subsection{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<br />
rather than package.xml

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

<pre><code>
composer exec -v horde-components web/\$app/ composer
</code></pre>
To generate a new composer.json file for a library, run

<pre><code>
composer exec -v horde-components vendor/horde/\$lib composer
</code></pre>
Mind providing a useful config for horde-components first

config options govern

\begin{itemize}
\item if we want to build against dev-master dependencies or dependencies using the horde.yml version constraints


\item if we assume all packages live on packagist, in a shared satis repo or a per-library git location


\item how to translate non-horde pear dependencies into packagist dependencies (otherwise, pear channels will be used)


\end{itemize}
\subsubsection{components release command}
The components release command needs some additions to make this practical

\begin{itemize}
\item <a href="https://wiki.horde.org/TODO">TODO</a> 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


\item <a href="https://wiki.horde.org/TODO">TODO</a> There should be configureable hooks to either trigger a satis rewrite or a packagist upload


\item <a href="https://wiki.horde.org/TODO">TODO</a> 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.


\end{itemize}
\subsubsection{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.<br />
<a href="https://github.com/composer/composer/issues/5632">https://github.com/composer/composer/issues/5632</a>

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

\subsection{Core, Base and Autoloader}
Several patches were needed in places where horde just assumed files to always be in a certain location.<br />
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<br />
lib/Horde/Core/Controller/<a href="https://wiki.horde.org/RequestMapper">RequestMapper</a>.php

\subsection{Test}
The Horde\_Test suite had some hardcoded requires which were made condidional.

\subsection{Other libraries}
Unmentioned libraries SHOULD only have been modified by replacing the master branch composer file

\subsection{}
\section{Resources}
<a href="https://getcomposer.org/doc/articles/custom-installers.md">https://getcomposer.org/doc/articles/custom-installers.md</a> composer notes on custom installers and plugins<br />
<a href="https://github.com/composer/installers">https://github.com/composer/installers</a> multi-framework collection of installers<br />
<a href="https://github.com/maglnet/[ComposerRequireChecker](ComposerRequireChecker)">https://github.com/maglnet/[ComposerRequireChecker](ComposerRequireChecker)</a> Tool to find direct usage of indirect dependencies (Ensure you directly require all dependencies whose classes are referenced in own code)


\noindent\rule{\textwidth}{1pt}
Back to the <a href="https://wiki.horde.org/Project">Project List</a>

\end{document}
