Notes on converting apps from Horde 5 to Horde 6
These are by far not complete. Last updated: 2026-03-04
| Package | Strategy | Unit Tests | PHPStan | PHP 8 | Comments/Upgrade path |
|---|---|---|---|---|---|
| horde/alarm | Legacy | 9.5 | Yes | Yes | Tests for unnamespaced modernized. Actual PSR-4 upgrade postponed, should use PSR-3 logger and modernized SQL when available |
| horde/argv | Parallel | 9.5, 447 tests | Yes | Yes | Modern API complete with contextual option groups. See argv-contextual-option-groups-implementation-complete.md |
| horde/components | Wrapper | 9.4, Story tests broken | Yes | Yes | Lots of new features related to git, composer and workflows. Still maintains package.xml and requires it in some places. 219 src/, 5 lib/ |
| horde/horde-installer-plugin | Modern | 9.5, very limited | Yes | Yes | Handles all the horde setup stuff, symlinks, workaround configs etc. 33 src/, 0 lib/ |
| horde/horde-deployment | Modern | n/a | n/a | Yes | The base project for a horde installation with default dir tree - Branches reflect bundles |
| horde/hordectl | Modern | 9.5 | No | Yes | CLI management tool. 41 src/, 0 lib/ |
| horde/http_server | Modern | 9.5, only stub of a test framework | Yes | yes | Successor to horde/controller. 13 src/, 0 lib/ |
| horde/http | Parallel | 9.4 | No | yes | Major BC breaks. Implementation based on PSR-7, PSR-18. 28 src/, 17 lib/ |
| horde/injector | Wrapper | 9.5 | Yes | yes | Carefully added signatures, limited BC breaks for child injectors. Now PSR-11. 11 src/, 11 lib/ |
| horde/crypt_blowfish | Legacy | 9.5 | No | yes | works with openssl 3 |
| horde/controller | Keep | 9.4 | No | Yes | Only added namespaced wrapper code for interop with horde/http_server and PSR-7. 2 src/, 22 lib/ |
| horde/stream_wrapper | Parallel | 9.4 | No | yes | Class names have Wrapper appended to make sense when USEd. 8 src/, 7 lib/ |
| horde/util | Parallel | 9.5 | No | yes | Slightly renamed classes and typing upgrades. 9 src/, 7 lib/ |
| horde/text_diff | Parallel | 9.5 | No | yes, 8.2beta | Renamed classes, typing upgrades. 20 src/, 19 lib/ |
| horde/support | Parallel | 9.4 | No | yes | Slightly renamed classes and typing upgrades. 10 src/, 15 lib/ |
| horde/compress_fast | Parallel | 9.4 | No | yes | Straight. 8 src/, 7 lib/ |
| horde/mongo | Parallel | 9.4 | No | yes | Removed support for the older extension - Still using the compat library. 7 src/, 6 lib/ |
| horde/cli | Parallel | 9.4 | No | yes | straight. 10 src/, 3 lib/ |
| horde/memcache | Parallel | 9.4, started minimal test suite | No | yes | straight. 15 src/, 22 lib/ |
| horde/cache | Parallel | 9.4, started minimal test suite | No | yes | Dropped some dead in-memory caches. 16 src/, 17 lib/ |
| horde/test | Parallel | 9.4, started minimal test suite | No | yes | straight. 14 src/, 8 lib/ |
| horde/routes | Parallel | 9.4 | No | yes | straight. 11 src/, 10 lib/ |
| horde/db | Parallel | 9.4 | No | yes | src/ Still a WIP mess. Dropped support for classic mysql extension. 42 src/, 41 lib/ |
| horde/log | Parallel | 9.4 | No | yes | Incompatible new design based on PSR-3, See Doc/Dev/HordeLog. 17 src/, 8 lib/ |
| horde/thrift | Keep | n/a | n/a | yes | Only nominally released as a leaf dependency, may be deprecated |
| horde/scribe | Keep | n/a | n/a | yes | Only nominally released as a leaf dependency, may be deprecated |
| horde/translation | Parallel | 9.5, covers only lib/ | No | yes | Slightly renamed classes and typing upgrades. 6 src/, 5 lib/ |
| horde/exception | Parallel | 9.5 | No | yes | Slightly renamed classes and typing upgrades, better support for 3rd argument. 12 src/, 7 lib/ |
| horde/eventdispatcher | Modern | 9.5, Stub only | Yes | yes | PSR-14 replacement for PubSub, See Doc/Dev/HordeEventDispatcher. 2 src/, 0 lib/ |
| horde/skeleton | Modern | 9.5, Stub Only | No | testing | Example app. 11 src/, 0 lib/ |
| horde/share | Legacy | 9.5, covers only /lib | No | yes, wip | Tests are not really run for the DB specific drivers yet but signatures check out. 0 src/, 44 lib/ |
| horde/kolab_format | Legacy | 9.5, covers only /lib | No | yes, wip | Little interest beyond making test suites for other libs work. 0 src/, 79 lib/ |
| horde/kolab_storage | Legacy | 9.5, covers only /lib | No | yes, wip | Little interest beyond making test suites for other libs work. 0 src/, 119 lib/ |
| horde/cli_modular | Parallel | 9.5, covers only /lib | No | yes, wip | Lib/ needs some minor fixes for PHP 8.1 compat. src/ is a major rewrite to account for modern autoloading, dependency injection, much more typing and lessons learned from cli_modular applications. 8 src/, 6 lib/ |
| horde/form | Parallel | 9.5 | Yes | Yes | Major modernization with typed code and PSR compliance. 61 src/, 14 lib/ |
| horde/constraint | Parallel | 9.5 | No | Yes | PSR-4 conversion complete. 14 src/, 11 lib/ |
| horde/secret | Modern | 9.5 | Yes | Yes | New implementation. 10 src/, 0 lib/ |
| horde/token | Modern | 9.5 | Yes | Yes | New implementation. 13 src/, 0 lib/ |
| horde/url | Parallel | 9.5 | No | Yes | PSR-4 conversion. 4 src/, 3 lib/ |
| horde/version | Modern | 9.5 | Yes | Yes | New semver implementation. 18 src/, 0 lib/ |
| horde/composer | Modern | 9.5 | Yes | Yes | Composer utilities. 13 src/, 0 lib/ |
| horde/githubapiclient | Modern | 9.5 | Yes | Yes | GitHub API v3 client. 68 src/, 0 lib/ |
| horde/hordeymlfile | Modern | 9.5 | Yes | Yes | .horde.yml parser. 8 src/, 0 lib/ |
| App | Strategy | PHPUnit | Status |
|---|---|---|---|
| horde/base | Parallel | Yes | 4 src/, 44 lib/ |
| horde/imp | Parallel | Yes | 1 src/, 318 lib/ - Major work needed |
| horde/ingo | Legacy | Yes | 0 src/, 118 lib/ |
| horde/kronolith | Parallel | Yes | 11 src/, 109 lib/ |
| horde/turba | Legacy | Yes | 0 src/, 52 lib/ |
| horde/nag | Parallel | Yes | 1 src/, 46 lib/ |
| horde/mnemo | Legacy | Yes | 0 src/, 26 lib/ |
| horde/ansel | Parallel | Yes | 1 src/, 93 lib/ |
| horde/whups | Parallel | No | 4 src/, 99 lib/ |
| horde/wicked | Parallel | Yes | 13 src/, 27 lib/ |
| horde/passwd | Parallel | Yes | 1 src/, 27 lib/ |
| horde/gollem | Parallel | No | 1 src/, 14 lib/ |
| horde/jonah | Parallel | Yes | 1 src/, 29 lib/ |
| horde/sesha | Legacy | Yes | 0 src/, 27 lib/ |
| horde/trean | Parallel | No | 1 src/, 21 lib/ |
Parallel strategy means double maint. burden but high freedom for due improvements and necessary BC breaks.
Example: horde/test, horde/cache, horde/cli
Current Count: ~40 libraries using Parallel strategy
Wrapper strategy allows both old and new calling code to leverage the same slightly modernized code base. However, BC breaks must be prevented.
Example: horde/components, horde/injector
Current Count: ~3 libraries using Wrapper strategy (components, injector, cli_application)
Newly developed code should only focus on the composer use case
Example: horde/horde-installer-plugin, horde/http_server, horde/hordectl, horde/skeleton
Current Count: ~15 libraries using Modern strategy (new implementations)
Libraries which are essentially deprecated but kept around for H6, or not yet converted
Example: horde/controller (Keep), horde/alarm (Legacy but functional)
Current Count: ~90 libraries still in Legacy mode (0 src/ files)
The home namespace for a library is $Vendor\$Name\, e.g. Horde\View
The home namespace for a subtype library is $Vendor\$Parent\$Name e.g. Horde\Xml\Element rather than Horde\Xml_Element
The Home Namespace for an app in $Horde\$Name, e.g. Horde\Turba
The Horde Base app is Horde\Base
If a library has an interface or base class Horde_$Name, promote it to either:
Horde:: is Horde\Core\Horde:: though I think we should re-think using it at all
Un-namespaced controllers go to app\controllers\ dir, namespaced controllers just go anywhere under src/, i.e. src/Middleware, src/Handler, src/Controller with no magic attached.
Un-namespaced library code goes to lib/
New or converted namespaced library code goes to src/.
Remember Liskov:
For $injector:
For $_GET, $_POST, $_REQUEST
for $config:
for $page_output:
for $__autoload
As Horde has evolved over the years, we have different types of classes, sometimes even mixed.
// Use a factory to get an implementation
// In case the factory cannot be autowired itself, you need to register how to get it first.
$injector->bindFactory(Horde\Kronolith\Calendar\Resource::class, Horde\Kronolith\Calendar\Factory::class, 'create')
// In case you want a specific implementation and it can be autowired, just bind it.
$injector->bindImplementation(Horde\Kronolith\Renderer::class, Horde\Kronolith\Renderer\Default::class);
use Horde\Kronolith\Calendar\Resource;
use Horde\Kronolith\Calendar\Factory as CalendarFactory;
use Horde\Kronolith\Renderer;
use Horde\Kronolith\Renderer\Default as RendererDefault;
// Use a factory to get an implementation
// In case the factory cannot be autowired itself, you need to register how to get it first.
$injector->bindFactory(Resource::class, CalendarFactory::class, 'create')
// In case you want a specific implementation and it can be autowired, just bind it.
$injector->bindImplementation(Renderer::class, RendererDefault::class);
$injector->bindImplementation('Forms', '\Horde_Forms_Base');
Mandatory:
Optional:
Mandatory:
Apart from mandatory changes, we should not currently port all horde to the new standard quickly.