This file contains essential information for AI coding agents working on the LibreBooking repository. Following these guidelines will help you work efficiently and maintain code quality.
LibreBooking is an open-source resource scheduling and booking system written in PHP. It's a fork of Booked Scheduler that has evolved significantly since 2020.
- Primary Language: PHP (>=8.2)
- Database: MySQL (>=5.5)
- Architecture: Model-View-Presenter (MVP) pattern
- Template Engine: Smarty (version 5.8+)
- Frontend: Bootstrap 5, jQuery
- Main Branch:
develop(notmainormaster) - License: GPL-3.0
/config Application configuration files
/Controls Reusable page control objects
/database_schema SQL scripts for database setup and upgrades
/Domain Domain entities, repositories, services
/Access Database abstraction layer
/Events Domain events
/Values Value objects
/Jobs Scheduled tasks (cron jobs)
/lang Translation files (30+ languages)
/lib Application supporting objects
/Application Application logic (admin, auth, reservations, etc.)
/Common Shared utilities (dates, localization, etc.)
/Database Database access and abstractions
/Email Email services
/external Third-party libraries (DO NOT MODIFY)
/Pages Page binding and workflow logic
/Presenters Application logic and page population
/plugins Plugin architecture (various types)
/tests PHPUnit test suite
/tpl Smarty templates
/tpl_c Template cache (auto-generated, not tracked)
/Web User-facing pages and assets
/scripts JavaScript files
/css Stylesheets
/WebServices REST API implementation
- PHP >= 8.2 with extensions: ctype, curl, fileinfo, json, ldap, mbstring, mysqli, openssl, pdo, pdo_mysql, tokenizer, xml
- Optional PHP extensions: bcmath, gd
- Composer for dependency management
- MySQL >= 5.5 for database
- Git for version control
-
Clone the repository:
git clone https://github.com/LibreBooking/librebooking.git cd librebooking -
Install dependencies:
composer install
⚠️ Known Issue - Composer Authentication Error: If you encounterCould not authenticate against github.comduringcomposer install, this is a known issue in certain CI/sandboxed environments.Workarounds:
- The error typically occurs when Composer tries to download packages from GitHub without proper authentication
- If in a CI environment, ensure GitHub tokens are properly configured
- In some cases, packages may already be cached and installation can proceed despite the error
- If the error persists and blocks progress, note this limitation and proceed with tasks that don't require vendor dependencies
-
Configure the application:
cp config/config.dist.php config/config.php # Edit config.php with your database settings -
Set up the database (if needed):
- Use Phing tasks:
composer build(requires MySQL credentials) - Or manually run SQL scripts in
/database_schema/
- Use Phing tasks:
Run the preflight checker to validate your environment:
composer preflight
# Or: php lib/preflight.phpThis script checks PHP version, required extensions, permissions, and optional database connectivity.
PHP Syntax Check:
./ci/ci-phplintThis uses parallel processing to lint all PHP files (excluding vendor, tmp, node_modules).
PHP-CS-Fixer (PSR-12 compliance):
# Check code style (dry-run, no changes)
composer phpcsfixer:lint
# Fix code style issues automatically
composer phpcsfixer:fixConfiguration: .php-cs-fixer.dist.php
- Follows PSR-12 standards
- Uses short array syntax
- Enforces single quotes
- Cache:
var/cache/.php-cs-fixer.cache
PHPStan (level 2):
# Run base analysis
composer phpstan
# Run with stricter rules
composer phpstan_nextConfiguration files:
phpstan.neon- Base configuration (level 2)phpstan_next.neon- Stricter analysis for progressive improvements
Output format: prettyJson
Cache directory: var/cache/phpstan/
PHPUnit (version 11.5+):
# Run all tests (excludes integration tests)
composer phpunit
# Or: ./vendor/bin/phpunit
# Run specific test suite
composer phpunit -- --testsuite domain
composer phpunit -- --testsuite application
# Run integration tests (requires database)
composer test:integrationConfiguration: phpunit.xml.dist
Test suites available:
all- All tests except integration (default)application- Application layer testsdomain- Domain layer testsplugins- Plugin testspresenters- Presenter testswebservice/webservices- API testsintegration- Integration tests (requires database setup)
Important: Integration tests require a configured database. Set up config.php before running.
Run both tests and linting:
composer testGenerate API documentation with PHPDocumentor:
# Install phive tools first
composer install-tools
# Generate docs (output: .phpdoc/build/)
./tools/phpdocConfiguration: phpdoc.dist.xml
Build a distributable release package:
composer build
# Uses Phing, output: build/librebooking.zipConfiguration: build.xml
- Follow PSR-12 - The codebase strictly follows PSR-12 standards
- Use PHP 8.2+ features where appropriate (enums, readonly properties, constructor property promotion, etc.)
- Type hints - Use strict typing where possible
- Documentation - Add PHPDoc blocks for classes and complex methods
- No trailing whitespace - EditorConfig enforces this
- LF line endings - Unix-style line endings (see
.editorconfig) - 4-space indentation for PHP, 2-space for YAML files
- Single quotes for strings (unless interpolation is needed)
- Short array syntax - Use
[]notarray() - No magic numbers - Use named constants, enums, or class constants instead of raw numeric literals. For example, use
CustomAttributeTypes::CHECKBOXinstead of4. Code reviews should flag any unexplained numeric literals as magic numbers
Model-View-Presenter (MVP):
- Pages (
/Pages/*.php) - Thin abstraction to template engine, minimal logic - Presenters (
/Presenters/*.php) - Orchestrate interactions, fetch/transform data - Domain (
/Domain/) - Business logic, entities, repositories
File Organization:
- Each page should have a corresponding template in
/tpl - Each page should have a class in
/Pages - Each page class should have a presenter in
/Presenters - Related code grouped in directories with
namespace.phpfor easy inclusion
- Classes: PascalCase (e.g.,
ReservationService,UserRepository) - Methods: camelCase (e.g.,
getUserById,validateReservation) - Variables: camelCase
- Constants: UPPER_SNAKE_CASE
- Files: Match class names (e.g.,
ReservationService.php)
- Uses MySQL/MariaDB
- Entity Relationship Diagram:
docs/source/ERD.svg - Schema management via Phing tasks or manual SQL scripts
- Migration scripts in
/database_schema/upgrades/
Important: The main development branch is develop, NOT main or master.
- develop - Active development, latest beta code
- master - Stable releases only
- Feature branches:
feature/description-of-feature - Bugfix branches:
bugfix/issue-number-description
Follow conventional commits format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat- New featurefix- Bug fixdocs- Documentation changesstyle- Code style changes (formatting, no logic change)refactor- Code refactoringperf- Performance improvementstest- Test additions/correctionsbuild- Build system/CI changesci- CI configuration changeschore- Other changes
Scopes (optional but recommended):
API- API changes- Or describe the affected module/area
Rules:
- Header max 72 characters
- Use imperative, present tense ("change" not "changed")
- Reference GitHub issues in footer (e.g.,
Closes: #123) - Breaking changes: Start footer with
BREAKING CHANGE:
Example:
feat(API): Add new schedules endpoint
Add a new schedules endpoint which allows getting the resources of a schedule.
Closes: #2222
- Target branch: PRs should target
develop(not main/master) - No merge commits: PRs must not contain merge commits (use rebase)
- Linear history: Maintainers will use "Rebase and merge" or "Squash and merge"
- PR title: Follow commit message header format
- Update docs: If changing interfaces, update README.md and relevant docs
- Tests required: Add tests for new features/bug fixes when applicable
- CI must pass: All lint, analysis, and test checks must pass
The repository uses several CI workflows:
-
Linters (
lint-and-analyse-php.yml) - Runs on PRs todevelop:- Commitizen (commit message validation)
- Config checks
- doc8 (RST documentation)
- Markdown linting
- PHP lint (syntax check) on PHP 8.2, 8.3, 8.4, 8.5
- php-cs-fixer (code style) on PHP 8.2
- PHPStan analysis on PHP 8.5 (both base and next configs)
- Validates no merge commits in PR
-
PHPUnit (
phpunit.yml) - Runs on PRs todevelop:- Unit tests on PHP 8.2, 8.3, 8.4, 8.5
- Creates config.php from config.dist.php
- Validates test summary output
-
Integration Tests (
integration-tests.yml) - Database integration tests -
Documentation (
docs.yml) - Builds Sphinx documentation -
Release (
release.yml,release-dry-run.yml) - Automated releases with semantic-release
Before pushing, validate your changes locally:
# 1. Lint PHP syntax
./ci/ci-phplint
# 2. Check code style
composer phpcsfixer:lint
# 3. Run static analysis
composer phpstan
# 4. Run tests
composer phpunit
# 5. Preflight check
composer preflight-
Create feature branch from
develop:git checkout develop git pull git checkout -b feature/your-feature-name
-
Implement following MVP pattern:
- Create/update page in
/Web/ - Create page class in
/Pages/ - Create presenter in
/Presenters/ - Create template in
/tpl/ - Add domain logic in
/Domain/or/lib/Application/
- Create/update page in
-
Add tests in
/tests/matching the directory structure -
Update documentation if needed
-
Validate locally:
composer phpcsfixer:fix # Fix style issues composer phpstan # Check static analysis composer phpunit # Run tests
-
Commit with conventional commit message
-
Push and create PR to
develop
Plugins are located in /plugins/ with subdirectories by type:
Authentication/- Authentication providersAuthorization/- Authorization handlersPreReservation/- Pre-reservation logicPostReservation/- Post-reservation logic
Each plugin typically has a *.config.dist.php file for configuration.
Templates use Smarty syntax:
- Variables:
{$variableName} - Conditionals:
{if $condition}...{/if} - Loops:
{foreach $items as $item}...{/foreach} - Functions:
{translate key="some.key"}
Templates are cached in /tpl_c/ - this directory is auto-generated.
- Never modify
/database_schema/create-schema.sqldirectly - Create upgrade scripts in
/database_schema/upgrades/ - Follow naming convention:
X.Y.Z.sql(version number) - Use Phing tasks to apply upgrades:
composer buildor phing targets
- Translation files in
/lang/{language_code}/ - Each language has separate files for different sections
- Use
translatefunction in templates - Keys use dot notation:
section.subsection.key
Issue: When running composer install, you may encounter:
Could not authenticate against github.com
Cause: Composer tries to download packages from GitHub without proper authentication tokens in certain environments.
Workarounds:
- Ensure
COMPOSER_AUTHor GitHub tokens are configured in CI - Try
composer install --prefer-distto use cached packages - Check if
composer.lockis up to date and committed - In some cases, the error is intermittent; retry may succeed
- If working on tasks that don't require vendor dependencies, note this limitation and proceed
Prevention: Always commit both composer.json and composer.lock together.
Issue: Template changes not appearing.
Workaround: Clear template cache:
rm -rf tpl_c/*Prevention: In development, ensure proper permissions on tpl_c/ directory.
Issue: PHPStan may run out of memory on large codebases.
Workaround: Increase memory limit:
composer phpstan -- --memory-limit=2GThe CI workflow already uses --memory-limit 2G and has debug fallback.
Issue: Application errors related to file permissions.
Required Permissions:
/tpl_c/- Must be writable by web server/tpl/- Must be writable by web server/uploads/- Must be writable by web server- Configured log directory - Must be writable
Fix:
chmod 755 tpl_c tpl uploads
# Ensure web server user owns these directoriesIssue: Application won't work if PHP session.auto_start is enabled.
Fix: Ensure session.auto_start = 0 in php.ini.
Important: Never modify code in /lib/external/ - these are third-party libraries maintained separately.
- Focus on domain logic and business rules
- Mock dependencies using PHPUnit mocks
- Keep tests fast and isolated
- Test file location should mirror source file structure
- Name test files and test classes after the class under test with a
Testsuffix (for example,Pages/Admin/ManageUsersPage.php->tests/Pages/Admin/ManageUsersPageTest.php) - Prefer one primary test file per source class; add extra files only when a clear separation is needed
- Require database setup
- Test actual database interactions
- Located in
/tests/Integration/ - Run separately with
composer test:integration
For integration tests:
- Copy config template:
cp config/config.dist.php config/config.php - Configure test database credentials in config.php
- Run database setup scripts or use Phing
Generate coverage reports:
./vendor/bin/phpunit --coverage-html ./var/Output goes to ./var/ directory.
- Main docs:
/docs/source/(reStructuredText format) - DEVELOPER-README.rst - Developer guide
- API.rst - REST API documentation
- INSTALLATION.rst - Installation instructions
- CONFIGURATION.rst - Configuration guide
- CONTRIBUTING.md - Contributing guidelines
Documentation uses Sphinx and is hosted on ReadTheDocs.
Build locally:
pip install -r requirements-docs.txt
cd docs
sphinx-build -n -W --keep-going -b html source build/htmlOr use tox:
pip install tox
tox -e docsOutput: docs/build/html/
- Markdown (
.md) - Used for: README, CHANGELOG, CONTRIBUTING - reStructuredText (
.rst) - Used for: Technical documentation in/docs/source/
- Never commit secrets - Use config files (ignored in git) for credentials
- SQL injection - Use prepared statements (PDO/mysqli)
- XSS prevention - Escape output in templates
- CSRF protection - Use built-in token system
- Input validation - Validate all user input
- File uploads - Validate file types and sizes
- Template caching - Smarty templates are compiled and cached in
/tpl_c/ - Database queries - Use proper indexing, avoid N+1 queries
- Session management - Configured in
config.php - Asset optimization - Minify CSS/JS for production
The REST API is in /WebServices/:
- RESTful design principles
- Authentication via API keys or tokens
- Version-aware endpoints
- JSON responses
- See
docs/source/API.rstfor detailed API documentation
Plugins extend LibreBooking functionality:
- Create plugin directory in
/plugins/{PluginType}/ - Implement required interface for plugin type
- Add configuration file:
{PluginName}.config.dist.php - Document plugin usage
- Register plugin in application configuration
- Main Repository: https://github.com/LibreBooking/librebooking
- Live Demo: https://librebooking-demo.fly.dev/
- Discord Community: https://discord.gg/4TGThPtmX8
- Wiki: https://github.com/LibreBooking/librebooking/wiki
- Docker Image: https://github.com/LibreBooking/docker
- Issue Tracker: https://github.com/LibreBooking/librebooking/issues
# Setup
composer install # Install dependencies
cp config/config.dist.php config/config.php # Create config
composer preflight # Validate environment
# Development
composer phpcsfixer:fix # Auto-fix code style
composer phpstan # Static analysis
composer phpunit # Run tests
composer test # Run tests + lint
./ci/ci-phplint # PHP syntax check
# Building
composer build # Package release (Phing)
# Documentation
tox -e docs # Build Sphinx docs
./tools/phpdoc # Generate API docs
# Database
composer build -- baseline.db # Create database
composer build -- upgrade.db # Apply upgrades- Unclear requirements - Ask user for clarification
- Breaking existing tests - Investigate why before modifying tests
- Security concerns - Consult before implementing security-sensitive features
- Large architectural changes - Discuss design before implementing
- Database schema changes - Review upgrade process requirements
- Third-party dependencies - Check if really needed before adding
- Read CONTRIBUTING.md before submitting PRs
- Check existing issues before reporting new ones
- Test thoroughly - Both unit and integration tests
- Document changes - Update relevant documentation
- Follow conventions - Consistency is key for maintainability
- Ask questions - Community is helpful on Discord
Version: 1.0 Last Updated: 2026-02-16 Maintainers: LibreBooking Community