Skip to content

Package Development

QUIQQER extensions are Composer packages with QUIQQER-specific package types and optional XML configuration files.

For normal feature work, create or extend a package. Do not change the base system unless you are explicitly working on the platform itself.

Extension Model

A QUIQQER package can add PHP code, templates, JavaScript, CSS, images, console commands, backend entries, settings, permissions, events, widgets, and database changes. The exact behavior is declared through Composer metadata, PHP classes, assets, and optional XML files.

Package-level building blocks:

  • composer.json defines the package name, type, dependencies, autoloading, and developer scripts.
  • package.xml describes package metadata, support links, images, languages, and providers.
  • src/ contains package PHP classes loaded through Composer autoloading.
  • bin/ contains browser-accessible package assets such as JavaScript, CSS, images, and administration components.
  • XML files register optional behavior such as events, console commands, menus, settings, permissions, widgets, and database changes.

Providers

A provider is a PHP class that a package registers for a named extension point. QUIQQER or another package reads that provider declaration and calls the class through the API expected by that extension point.

Providers are declared in package.xml:

xml
<quiqqer>
    <package>
        <provider>
            <desktopSearch src="\Vendor\Package\Search\Provider"/>
            <installationWizard src="\Vendor\Package\Setup\Wizard"/>
        </provider>
    </package>
</quiqqer>

The XML node name is the provider type. The src attribute points to an autoloadable PHP class. The required interface or base class depends on the provider type.

Core provider types include auth, desktopSearch, installationWizard, rest, and mcp. Packages can also define their own provider APIs. For example, a package can read provider declarations from installed packages and load classes registered for its own provider type.

Declare a provider only when the package implements the corresponding API. If a package only uses events, XML files, templates, or console commands, it does not need a provider declaration.

Package Structure

A package starts with Composer metadata and adds only the files it needs for its feature set.

Typical structure:

text
my-package/
├─ composer.json
├─ package.xml
├─ locale.xml
├─ permissions.xml
├─ events.xml
├─ database.xml
├─ menu.xml
├─ site.xml
├─ src/
│  └─ Vendor/
│     └─ Package/
└─ bin/
   ├─ images/
   ├─ css/
   └─ js/

Not every package needs every XML file. A package that only provides reusable PHP functionality may only need composer.json and PHP classes. A package that adds backend functionality may add menu.xml, permissions.xml, locale.xml, and events.xml. A template package usually focuses on presentation files, settings, and frontend assets.

Composer Metadata

Every QUIQQER package needs a valid composer.json. Use the package type that matches the package's purpose.

Composer typeMeaning
quiqqer-moduleDefault type for extension packages.
quiqqer-templateProject presentation package.
quiqqer-assetBrowser asset package generated from selected npm packages for QUIQQER.

quiqqer-asset packages are not normal extension packages. They wrap selected browser libraries for Composer-based installation and are provided through the QUIQQER asset repository.

Use quiqqer-module for new extension packages unless the package is clearly a template package. In public documentation, use "package" as the umbrella term. The Composer type is implementation metadata and should only be discussed when it affects setup or installation.

Existing packages can use additional package types for historical or specialized reasons. New extension documentation should use quiqqer-module as the default type.

Minimal composer.json

Use Composer's standard fields plus a QUIQQER package type and dependencies. Modern packages should depend on quiqqer/core instead of the older quiqqer/quiqqer package name.

json
{
  "name": "vendor/package-name",
  "type": "quiqqer-module",
  "description": "Short package description.",
  "license": "GPL-3.0-or-later",
  "require": {
    "php": "^8.1",
    "quiqqer/core": "^2"
  },
  "autoload": {
    "psr-4": {
      "Vendor\\Package\\": "src/Vendor/Package"
    }
  }
}

Real packages often add support information, authors, development scripts, suggested packages, and additional QUIQQER or asset dependencies.

Current free packages such as quiqqer/bricks, quiqqer/cron, and quiqqer/cache are useful orientation points for real package layout: they use QUIQQER package types, depend on quiqqer/core, define PSR-4 namespaces under src/, and keep repository checks in Composer scripts.

Autoloading

QUIQQER packages use Composer autoloading. Current package examples commonly use PSR-4 namespaces that point into src/.

Example shape:

json
{
  "autoload": {
    "psr-4": {
      "Vendor\\Package\\": "src/Vendor/Package"
    }
  }
}

package.xml

Use package.xml when the package should expose package metadata to QUIQQER. Typical metadata includes:

  • localized title and description
  • package logo
  • preview images
  • support links
  • copyright and license information
  • provider declarations

Example shape:

xml
<quiqqer>
    <package>
        <title>
            <locale group="vendor/package-name" var="package.title"/>
        </title>

        <description>
            <locale group="vendor/package-name" var="package.description"/>
        </description>

        <image src="URL_OPT_DIR/vendor/package-name/bin/images/logo.jpg"/>

        <support>
            <email>support@example.com</email>
            <source>https://dev.example.com/vendor/package-name</source>
            <issues>https://dev.example.com/vendor/package-name/-/issues</issues>
        </support>
    </package>
</quiqqer>

XML Files By Use Case

Add XML files only for the behavior your package provides:

Use caseFile
Register console toolsconsole.xml
Create or update database tablesdatabase.xml
Listen to eventsevents.xml
Provide translationslocale.xml
Add backend menu entriesmenu.xml
Add media attributesmedia.xml
Add permissionspermissions.xml
Add package or project settingssettings.xml
Add site-related behaviorsite.xml
Add user-related behavioruser.xml
Add desktop widgetswidgets.xml

See XML configuration files for the current XML overview.

See composer.json for detailed package metadata and Development Installs for installing Git repositories or development branches into a QUIQQER system.

Runtime Paths

QUIQQER exposes installation paths through PHP constants. Package code, templates, and frontend scripts use them when they need filesystem paths or public URLs for packages, projects, assets, runtime data, and templates.

ConstantPurpose
CMS_DIRRoot path of the installed QUIQQER system.
LIB_DIRPlatform library path.
BIN_DIRBinary and asset path.
USR_DIRProject path.
VAR_DIRRuntime data path for logs, sessions, cache, lock files, temporary files, and similar data.
OPT_DIRPackage path.
SYS_DIRAdmin/system configuration path.

URL constants such as URL_OPT_DIR, URL_USR_DIR, and URL_VAR_DIR are used when package assets need to be referenced publicly.

Frontend Assets

Place package assets under bin/ when they must be available to the browser. Package metadata and templates commonly reference assets through URL_OPT_DIR.

Current packages use quiqqer-asset/* dependencies for browser libraries. Older wiki pages mention npm-asset/* and bower-asset/*; do not use those examples as the default for new documentation.

Development Scripts

Many current packages expose package-local checks through Composer scripts:

json
{
  "scripts": {
    "test": [
      "@dev:lint",
      "@dev:phpunit"
    ],
    "dev:phpunit": "./tools/phpunit",
    "dev:lint": [
      "@dev:lint:phpstan",
      "@dev:lint:style"
    ],
    "dev:lint:phpstan": "./tools/phpstan",
    "dev:lint:style": "./tools/phpcs",
    "dev:lint:style:fix": "./tools/phpcbf"
  }
}

Use these scripts when the package has the corresponding tools installed. Otherwise, document the package-specific test and lint workflow in its README.

Practical Checklist

Before publishing a package:

  • Validate composer.json.
  • Choose the correct quiqqer-* package type.
  • Add package.xml if the package needs visible metadata or providers.
  • Add only the XML files the package actually needs.
  • Keep translations in locale.xml.
  • Put browser-accessible assets in bin/.
  • Configure Composer autoloading for PHP classes.
  • Run package linting and tests if developer tooling is available.

Released under GPL-3.0-or-later.