\documentclass{article}
\usepackage{ulem}
\usepackage{graphicx}
\usepackage{hyperref}
\pagestyle{headings}
\begin{document}
\part{The .horde.yml File Format}
This document describes the .horde.yml file format used by Horde Framework 6 components. The .horde.yml file serves as the canonical source of component metadata and is used by the horde-components tool to generate composer.json files and manage releases. For older versions of this format, see <a href="https://wiki.horde.org/Doc/Dev/HordeYmlFormat">Doc/Dev/HordeYmlFormat</a>

\section{Overview}
The .horde.yml format has evolved from Horde Framework 5.2 through the git split and into Horde 6.<br />
It provides a unified way to declare component metadata, dependencies, autoloading rules and other configuration that can be transformed into various package management formats.

Key characteristics:

\begin{itemize}
\item YAML 1.2 format


\item Single source of truth for component metadata


\item Generates composer.json automatically via horde-components tool


\item Supports both composer-native and legacy PEAR dependencies


\item Provides autoloading configuration for PSR-0, PSR-4 and classmap strategies


\end{itemize}
\section{Meta Data Section}
These fields appear at the top level of the .horde.yml file and define the component's identity and basic properties.

\subsection{Required Fields}
<u>id</u> (string, mandatory)

\begin{itemize}
\item Component identifier


\item For libraries: uppercase without Horde\_ prefix (e.g., Autoloader, Exception, Browser)


\item For applications: lowercase (e.g., horde, turba, ansel)<br />
<u>name</u> (string, mandatory)


\item Display name with proper capitalization (e.g., Horde, Turba, Autoloader, Exception)<br />
<u>full</u> (string, mandatory)


\item One-line description of the component


\item Should be concise and descriptive<br />
<u>description</u> (string, mandatory)


\item Multi-line description of the component


\item Can use YAML multi-line string syntax (>- for folded strings)


\item Provides detailed information about component functionality<br />
<u>list</u> (string, mandatory)


\item Mailing list appropriate for the component


\item Common values: dev, horde, or application-specific list names


\item May be empty string if no specific list applies<br />
<u>type</u> (string, mandatory)


\item Component type indicator


\item Classic values: application, library - these work for regular composer packages.


\item Modern Horde 6 values: horde-application, horde-library, horde-theme, component - these trigger special handling by the horde/horde-composer-plugin installer for components which need it.


\item Used to determine composer package type<br />
<u>authors</u> (list, mandatory)


\item List of contributor information


\item Each entry has the following attributes:<br />
**<u>name</u> (string): Full name of the contributor<br />
** <u>user</u> (string): Horde username or identifier<br />
**<u>email</u> (string): Email address<br />
** <u>active</u> (boolean): true if currently active, false if inactive<br />
**<u>role</u> (string): Contributor role (lead, developer, contributor)


\end{itemize}
<u>version</u> (object, mandatory)<br />
* Contains two sub-keys:<br />
** <u>release</u> (string): Current release version in semantic versioning format (e.g., 3.0.0-alpha10)<br />
**<u>api</u> (string): Current API version (e.g., 3.0.0alpha1)<br />
* Version numbers follow semantic versioning with optional stability suffixes<br />
* Pre-release versions use formats like: 1.0.0-alpha1, 2.0.0-beta3

<u>state</u> (object, mandatory)<br />
* Contains two sub-keys:<br />
** <u>release</u> (string): Release stability (stable, beta, alpha)<br />
**<u>api</u> (string): API stability (stable, beta, alpha)<br />
* API stability can differ from release stability

<u>license</u> (object, mandatory)<br />
* Contains two sub-keys:<br />
** <u>identifier</u> (string): SPDX license identifier (e.g., LGPL-2.1-only, BSD-2-Clause, GPL-2.0-only)<br />
** <u>uri</u> (string): Link to full license text (e.g., <a href="http://www.horde.org/licenses/lgpl21\">http://www.horde.org/licenses/lgpl21\textbackslash\{\}</a>)

\subsection{Optional Fields}
<u>homepage</u> (string)

\begin{itemize}
\item URL to component's homepage or documentation


\item Typically <a href="https://www.horde.org/libraries/Horde\_ComponentName">https://www.horde.org/libraries/Horde\textbackslash\{\}\_ComponentName</a> or <a href="https://www.horde.org/apps/appname">https://www.horde.org/apps/appname</a><br />
<u>vendor</u> (string)


\item Composer vendor name


\item Defaults to "horde" if not specified


\item Used to generate composer package name (vendor/id)


\end{itemize}
!++ Example Meta Data

\section{\^{}}
\section{id: Browser<br />
name: Browser<br />
full: Browser detection library<br />
description: >-<br />
A library for getting information about the current user's browser and its<br />
capabilities.<br />
list: dev<br />
type: library<br />
homepage: <a href="https://www.horde.org/libraries/Horde\_Browser">https://www.horde.org/libraries/Horde\textbackslash\{\}\_Browser</a><br />
authors:}
<pre><code>name: Chuck Hagenbuch
user: chuck
email: chuck@horde.org
active: false
role: lead
</code></pre>
\begin{itemize}
\item name: Michael Slusarz<br />
user: slusarz<br />
email: <a href="https://wiki.horde.org/mailto:slusarz@horde.org">slusarz@horde.org</a><br />
active: false<br />
role: developer<br />
version:<br />
release: 3.0.0-alpha10<br />
api: 3.0.0alpha1<br />
state:<br />
release: alpha<br />
api: alpha<br />
license:<br />
identifier: LGPL-2.1-only<br />
uri: <a href="http://www.horde.org/licenses/lgpl21">http://www.horde.org/licenses/lgpl21</a><br />
vendor: horde<br />
\^{}


\end{itemize}
\section{Dependencies Section}
The dependencies section declares required, optional and development dependencies. It supports PHP version constraints, PHP extensions, composer packages and legacy PEAR packages.

Don't use PEAR packages anymore. It's strictly for Backwards Compatibility.

!++ Structure

\^{}<br />
dependencies:<br />
uses: readonly-parameters           \# Optional: special feature flags<br />
required:<br />
php: version-constraint           \# PHP version requirement<br />
ext:                              \# PHP binary extensions<br />
extension-name: version-constraint<br />
composer:                         \# Composer packages<br />
vendor/package: version-constraint<br />
pear:                             \# Legacy PEAR packages<br />
channel/package: version-constraint<br />
optional:<br />
composer:                         \# Optional composer packages<br />
vendor/package: version-constraint<br />
ext:                              \# Optional PHP extensions<br />
extension-name: version-constraint<br />
pear:                             \# Optional PEAR packages<br />
channel/package: version-constraint<br />
dev:<br />
composer:                         \# Development-only composer packages<br />
vendor/package: version-constraint<br />
\^{}

!++ Required Dependencies

<u>dependencies: required: php</u> (string)

\begin{itemize}
\item PHP version constraint using composer syntax


\item Examples: \^{}7.4 || \^{}8, \^{}8, \^{}8.2


\item Determines minimum PHP version<br />
<u>dependencies: required: ext</u> (object)


\item Map of PHP extension names to version constraints


\item Version constraint can be '*' for any version or a specific version


\item Common extensions: hash, pdo, gettext, gd, imagick<br />
<u>dependencies: required: composer</u> (object)


\item Map of composer package names to version constraints


\item Package names in vendor/package format


\item For Horde packages: horde/package-name (lowercase)


\item Version constraints use composer syntax: \^{}3, \^{}3.0, \textasciitilde{}2.0.0, >=1.0<br />
<u>dependencies: required: pear</u> (object)


\item Map of PEAR package names to version constraints


\item Package names in channel/package format (e.g., pear.horde.org/Horde\_Date)


\item Primarily for legacy compatibility


\item Horde 6 components prefer composer dependencies


\end{itemize}
!++ Optional Dependencies

<u>dependencies: optional</u> (object)

\begin{itemize}
\item Same structure as required section


\item Declares suggested packages that enhance functionality


\item Can contain composer, ext and pear sub-keys


\item Used for feature-specific dependencies


\end{itemize}
!++ Development Dependencies

<u>dependencies: dev: composer</u> (object)

\begin{itemize}
\item Development-only composer dependencies


\item Typically includes testing tools and code quality tools


\item Examples: horde/test, phpunit/phpunit, phpstan/phpstan


\item Generates composer.json require-dev section


\end{itemize}
!++ Special Features

<u>dependencies: uses</u> (string)

\begin{itemize}
\item Declares special language or framework features in use


\item Currently known value: readonly-parameters


\item Used for compatibility checking and code analysis


\end{itemize}
!++ Example Dependencies

\^{}<br />
dependencies:<br />
uses: readonly-parameters<br />
required:<br />
php: \^{}8.2<br />
ext:<br />
hash: '*'<br />
gettext: '*'<br />
composer:<br />
horde/exception: \^{}3<br />
horde/translation: \^{}3<br />
horde/util: \^{}3<br />
optional:<br />
ext:<br />
gd: '*'<br />
imagick: '*'<br />
composer:<br />
horde/cache: \^{}3<br />
horde/log: \^{}3<br />
dev:<br />
composer:<br />
horde/test: \^{}3<br />
phpunit/phpunit: \^{}12 || \^{}11<br />
phpstan/phpstan: \^{}2<br />
\^{}

\section{Autoload Section}
The autoload section defines how PHP classes should be found within the component. It supports PSR-0, PSR-4 and classmap strategies.

!++ Structure

\^{}<br />
autoload:<br />
psr-0:                              \# PSR-0 autoloading<br />
Class\_Prefix: lib/<br />
psr-4:                              \# PSR-4 autoloading<br />
Vendor\textbackslash\{\}Namespace\textbackslash\{\}: src/<br />
classmap:                           \# Classmap autoloading<br />
- lib/<br />
- other-dir/<br />
\^{}

The horde-components tool auto-senses some common autoloading patterns and sets up defaults if no autoload section is present.

!++ Autoload Strategies

<u>autoload: psr-0</u> (object)

\begin{itemize}
\item Map of class name prefixes to directories


\item Legacy autoloading standard using underscores as directory separators


\item Example: Horde\_Http in lib/ directory


\item Directory is relative to component root


\item Using PSR-0 autoloader with "" namespace should be avoided. Use the classmap instead.<br />
<u>autoload: psr-4</u> (object)


\item Map of namespaces to directories


\item Modern autoloading standard using namespace separators


\item Namespace must end with backslash


\item Example: Horde\textbackslash\{\}Browser\textbackslash\{\} maps to src/


\item Directory is relative to component root<br />
<u>autoload: classmap</u> (array)


\item List of directories to recursively scan for PHP files


\item Each PHP file is scanned for class definitions


\item Useful for legacy code without consistent naming


\item Example: ['lib/'] scans all PHP files in lib/ directory


\end{itemize}
!++ Autoload-Dev Section

<u>autoload-dev</u> (object)

\begin{itemize}
\item Same structure as autoload section


\item Applied only in development context


\item Typically used for test namespaces


\item If test directory exists, PSR-4 rule is auto-generated for Vendor\textbackslash\{\}Package\textbackslash\{\}Test\textbackslash\{\} namespace


\end{itemize}
!++ Default Behavior

If no autoload section is present, horde-components will auto-detect:

\begin{itemize}
\item If lib/ directory exists: generates PSR-0 rule from package name


\item If src/ directory exists: generates PSR-4 rule from package name


\item If test/ directory exists: generates PSR-4 autoload-dev rule for Test namespace


\end{itemize}
!++ Example Autoload

\^{}<br />
autoload:<br />
psr-0:<br />
Horde\_Browser: lib/<br />
psr-4:<br />
Horde\textbackslash\{\}Browser\textbackslash\{\}: src/<br />
classmap:<br />
- lib/legacy/<br />
\^{}

\^{}<br />
autoload:<br />
classmap:<br />
- lib/<br />
psr-4:<br />
Horde\textbackslash\{\}Ansel\textbackslash\{\}: src/<br />
\^{}

\section{Composer Integration}
Several additional sections support composer-specific features.

!++ Commands Section

<u>commands</u> (array, optional)

\begin{itemize}
\item List of paths relative to package root offered as vendor binaries


\item If provided, no automatic search in bin/ directory occurs


\item Each path should point to an executable file


\item These become composer bin entries<br />
<u>nocommands</u> (array, optional)


\item List of paths relative to package root excluded from vendor binaries


\item Takes precedence over commands list or implicitly found bin/ executables


\item Used to exclude non-binary files from bin/ directory


\end{itemize}
Example:<br />
\^{}<br />
nocommands:

\begin{itemize}
\item bin/horde-bootstrap


\item bin/horde-components-prototype-transpile<br />
\^{}


\end{itemize}
!++ Conflicts Section

<u>conflicts</u> (object, optional)

\begin{itemize}
\item Declares package conflicts in composer format


\item Directly transformed into composer.json conflict section


\item No composer or pear sub-keys (flat structure)


\item Used to prevent incompatible versions from coexisting


\end{itemize}
Example:<br />
\^{}<br />
conflicts:<br />
horde/base: <= 5.9.9<br />
horde/horde: <= 5.9.9<br />
\^{}

Use conflicts when already-released packages have overly liberal constraints that allow problematic combinations.

!++ Provides Section

<u>provides</u> (object, optional)

\begin{itemize}
\item Declares virtual packages or capabilities provided


\item Directly transformed into composer.json provide section


\item No composer or pear sub-keys (flat structure)


\item Used for interface compliance or successor relationships


\end{itemize}
Example:<br />
\^{}<br />
provides:<br />
horde/base: 6.1.1<br />
horde/user-management-api-implementation: 1.0<br />
\^{}

Use provides when:

\begin{itemize}
\item Multiple packages can satisfy the same capability


\item Package is successor to another package (e.g., ingo succeeds forwards and vacation modules)


\item Package provides an interface that others can depend on


\end{itemize}
!++ Allow-Plugins Section

<u>allow-plugins</u> (mixed, optional)

\begin{itemize}
\item Controls which composer plugins are allowed to run


\item Can be tilde (\textasciitilde{}) to allow all plugins


\item Can be object mapping plugin names to boolean values


\item Prevents composer from prompting about plugin permissions


\end{itemize}
Example:<br />
\^{}<br />
allow-plugins: \textasciitilde{}<br />
\^{}

Example:<br />
\^{}<br />
allow-plugins:<br />
horde/horde-installer-plugin: true<br />
composer/installers: true<br />
\^{}

\section{Quality Section}
The quality section configures code quality tools.

!++ Structure

\^{}<br />
quality:<br />
phpstan:<br />
level: 9<br />
php-cs-fixer:<br />
enabled: true<br />
\^{}

!++ PHPStan Configuration

<u>quality: phpstan: level</u> (integer)

\begin{itemize}
\item Sets PHPStan analysis level (0-9)


\item Higher levels are more strict


\item Level 9 is the maximum strictness


\end{itemize}
This setting instructs the horde-components qc and ci to FAIL if a previous water mark was no longer achieved.

\section{Complete Examples}
!++ Modern Horde 6 Library

\section{\^{}}
id: Browser<br />
name: Browser<br />
full: Browser detection library<br />
description: >-<br />
A library for getting information about the current user's browser and its<br />
capabilities.<br />
list: dev

\begin{itemize}
\item use horde-library if you need integration with the horde/horde-installer-plugin, i.e. javascript files which need to be exposed to web/ directory or horde database migrations in the migration/ directory. Otherwise use "library"<br />
type: library<br />
homepage: <a href="https://www.horde.org/libraries/Horde\_Browser">https://www.horde.org/libraries/Horde\textbackslash\{\}\_Browser</a><br />
authors:


\end{itemize}
\begin{itemize}
\item name: Chuck Hagenbuch<br />
user: chuck<br />
email: <a href="https://wiki.horde.org/mailto:chuck@horde.org">chuck@horde.org</a><br />
active: false<br />
role: lead<br />
version:<br />
release: 3.0.0-alpha10<br />
api: 3.0.0alpha1<br />
state:<br />
release: alpha<br />
api: alpha<br />
license:<br />
identifier: LGPL-2.1-only<br />
uri: <a href="http://www.horde.org/licenses/lgpl21">http://www.horde.org/licenses/lgpl21</a><br />
dependencies:<br />
required:<br />
php: \^{}7.4 || \^{}8<br />
composer:<br />
horde/exception: \^{}3<br />
horde/translation: \^{}3<br />
horde/util: \^{}3<br />
vendor: horde<br />
\^{}


\end{itemize}
!++ Application with Mixed Dependencies

\section{\^{}}
\section{id: ansel<br />
name: Ansel<br />
full: Photo gallery application<br />
description: Ansel is a full featured photo gallery application.<br />
list: ansel<br />
type: application<br />
homepage: <a href="https://www.horde.org/apps/ansel">https://www.horde.org/apps/ansel</a><br />
authors:}
<pre><code>name: Michael J Rubinsky
user: mrubinsk
email: mrubinsk@horde.org
active: true
role: lead
</code></pre>
version:<br />
release: 4.0.0-alpha6<br />
api: 4.0.0alpha1<br />
state:<br />
release: alpha<br />
api: beta<br />
license:<br />
identifier: GPL-2.0-only<br />
uri: <a href="http://www.horde.org/licenses/gpl">http://www.horde.org/licenses/gpl</a><br />
dependencies:<br />
required:<br />
php: \^{}7.4 || \^{}8<br />
composer:<br />
horde/horde: \^{}6<br />
horde/core: \^{}3<br />
horde/form: \^{}3<br />
horde/image: \^{}3<br />
ext:<br />
gettext: '*'<br />
hash: '*'<br />
optional:<br />
composer:<br />
horde/service\_twitter: \^{}3<br />
horde/service\_facebook: \^{}3<br />
ext:<br />
gd: '*'<br />
imagick: '*'<br />
autoload:<br />
classmap:<br />
- lib/<br />
psr-4:<br />
Horde\textbackslash\{\}Ansel\textbackslash\{\}: src/<br />
vendor: horde<br />
\^{}

!++ Component with Quality Tools

\section{\^{}}
\section{id: components<br />
name: Components<br />
full: Developer tool for managing Horde components<br />
description: >-<br />
The package provides utility methods required when preparing a new component<br />
release for Horde. It also includes quality control checks.<br />
list: horde<br />
type: component<br />
authors:}
<pre><code>name: Jan Schneider
user: jan
email: jan@horde.org
active: true
role: lead
</code></pre>
version:<br />
release: 1.0.0-alpha39<br />
api: 1.0.0alpha1<br />
state:<br />
release: alpha<br />
api: alpha<br />
license:<br />
identifier: LGPL-2.1-only<br />
uri: <a href="http://www.horde.org/licenses/lgpl21">http://www.horde.org/licenses/lgpl21</a><br />
dependencies:<br />
required:<br />
php: \^{}8.2<br />
composer:<br />
horde/cli: \^{}3<br />
horde/argv: '*'<br />
horde/util: '*'<br />
optional:<br />
composer:<br />
horde/test: \^{}3<br />
phpunit/phpunit: \^{}9<br />
dev:<br />
composer:<br />
horde/test: \^{}3<br />
phpunit/phpunit: \^{}12 || \^{}11 || \^{}10 || \^{}9<br />
nocommands:

\begin{itemize}
\item bin/horde-bootstrap


\item bin/horde-components-prototype-transpile<br />
allow-plugins: \textasciitilde{}<br />
quality:<br />
phpstan:<br />
level: 9<br />
vendor: horde<br />
\^{}


\end{itemize}
\section{Related Tools}
The .horde.yml file is primarily managed by the <a href="https://wiki.horde.org/horde-components">horde-components</a> tool:

\begin{itemize}
\item Validates .horde.yml syntax and completeness


\item Generates composer.json from .horde.yml


\item Updates version numbers during releases


\item Transforms PEAR dependencies to composer equivalents


\item Manages release workflow


\end{itemize}
For more information on release management, see <a href="https://wiki.horde.org/Doc/Dev/ReleaseProcess">Doc/Dev/ReleaseProcess</a>.

\section{Migration from Horde 5}
When migrating from Horde 5 to Horde 6:

\begin{itemize}
\item Update type from "library" or "application" to "horde-library" or "horde-application" if applicable - if default composer behaviour is sufficient, keep the default types.


\item Convert pear dependencies under dependencies:required:pear to composer dependencies


\item Add vendor: horde if not present (automatic update by some horde-components operations)


\item Update PHP version constraints. Horde 6.0 targets php 8.1-8.5 but if you really support older versions, say so.


\item Review and update license identifiers to use most recent edition of SPDX format


\item Only add autoload section if auto-sensing doesn't get it right.


\item Consider adding quality section for static analysis (can be done by horde-components qc --fix command)


\end{itemize}
\section{See Also}
\begin{itemize}
\item <a href="https://wiki.horde.org/Doc/Dev/ReleaseProcess">Doc/Dev/ReleaseProcess</a> - Component release workflow


\item <a href="https://wiki.horde.org/Doc/Dev/ComposerIntegration">Doc/Dev/ComposerIntegration</a> - Composer integration details


\item <a href="https://wiki.horde.org/horde-components">horde-components</a> - Component management tool


\end{itemize}
\end{document}
