citomni / demo-provider
Reference provider package for the CitOmni PHP framework: site notices with a Registry, a service, routes, templates, translations, CLI commands and an Operation. Shows each layer the canonical way, with a README per folder.
Requires
- php: ^8.5
- ext-mbstring: *
- citomni/infrastructure: ^1.0.1.2
Requires (Dev)
None
Suggests
- citomni/cli: Runs the notice:schedule, notice:expire and notice:list commands.
- citomni/http: Serves /notices.json, the management pages and the $site_notices template variable.
Provides
None
Conflicts
- citomni/cli: <1.0.0.9
- citomni/http: <1.0.5.4
Replaces
None
This package is auto-updated.
Last update: 2026-10-27 19:30:49 UTC
README
A reference provider package for the CitOmni PHP framework, and the guide tree that developers and AI assistants read before they write a file in a CitOmni provider package.
- Framework: CitOmni
- Kernel: citomni/kernel
- The app side: citomni/demo-app
What this repository is
- A guide tree. Every folder that holds a kind of file has a
README.mdwith the rules for that kind of file in a provider package. The tree mirrors a provider package, so the path of the file you are about to write is also the path of its guide. - A reference package. Everything under
src/is written the way production code should be written, and is meant to be copied. A site notices feature runs through Registry, Service, Controller, Command, Operation, Policy, Repository, Support, Enum and Exception, with its templates, texts, schema and tests. The other guides and the variant files still show patterns with placeholder names.
A provider package is installed with Composer and enabled in an app's config/providers.php. Its Boot\Registry contributes services, cfg baselines, routes and commands, which the app can override. Code that only one app needs stays in that app. A new package starts from citomni/provider-skeleton and follows the guides here. Apps have their own guide tree in citomni/demo-app, which also installs this package and shows the host app's side.
Guides
| Writing | Read |
|---|---|
Any PHP file in src/ |
src/README.md, then the guide of its folder |
| Registry | src/Boot/ |
| Controller | src/Controller/, with admin and member variants |
| CLI command | src/Command/, with a test command variant |
| Operation | src/Operation/ |
| Repository | src/Repository/ |
| Service | src/Service/ |
| Support, Policy, State | src/Support/, src/Policy/, src/State/ |
| Util, Enum, Exception | src/Util/, src/Enum/, src/Exception/ |
| Constant, Contract | src/Constant/, src/Contract/ |
| Job handler | src/JobRunner/, with token/push and trusted/pull jobs |
| Findability provider | src/Findability/ |
| Template | templates/ |
| Language file | language/ |
| Database schema | sql/ |
| Test suite | tests/ |
composer.json |
Package metadata below |
Looking up a guide
- Take the path of the file you will write, relative to the package root.
- Read the
README.mdof every folder from the top folder down to the file's folder. Forsrc/Service/Mailer.phpthat issrc/README.mdandsrc/Service/README.md. A folder without a README adds no rules. - Variants are separate files, linked from the folder README.
- When a guide links example files of this package, read them too. They are the pattern for a new file of that kind.
Precedence
- The guides are binding for new code.
- When you change an existing file, keep that file's style unless the task is to align it.
- When a guide and the framework source disagree, the source shows what happens today. Report the conflict so one of them gets fixed.
For AI assistants
Give the assistant read access to this repository and add this to its instructions:
Before writing or changing a file in a CitOmni provider package, read the README.md guides for its path in citomni/demo-provider, from the top folder down to the file's folder, in one batch (for src/Service/Mailer.php: src/README.md and src/Service/README.md). The Registry: src/Boot/README.md. composer.json: the Package metadata section of README.md. A missing README adds no rules. When a guide links example files, read them too. The guides are binding for new code. Never assume an existing contract, such as an API, a service, a cfg key, a route, a table or the template syntax: read it from its source, and stop and ask when it cannot be read. When changing an existing file, keep its style. Report a conflict between a guide and the source instead of silently picking one. Code in an app follows citomni/demo-app instead.
The site notices feature
A site notice is a short message at the top of every page, such as planned maintenance, from its start until its end. Notices are scheduled and ended from the CLI, or from a management page that the host app enables where every visitor may use it. Pages, scripts and other code read the current notices.
| Part | Files |
|---|---|
| Boot | src/Boot/Registry.php: the service, the cfg baseline, the template layer, the $site_notices template variable, the routes and the commands |
| HTTP | src/Controller/NoticeController.php (/notices.json) and src/Controller/NoticeManagementController.php (the management page and its two forms) |
| CLI | src/Command/ScheduleNoticeCommand.php, ExpireNoticeCommand.php and ListNoticesCommand.php |
| Read API | src/Service/Notices.php, the notices service |
| Workflow | src/Operation/ScheduleNotice.php, src/Policy/SchedulingPolicy.php |
| Persistence | src/Repository/NoticeRepository.php, sql/citomni_demo-provider.sql |
| Values and helpers | src/Enum/NoticeLevel.php, src/Support/LocalTime.php, src/Exception/NoticeConfigException.php |
| Presentation | templates/partials/ for host layouts, templates/public/ for the package's own page, language/da/notices.php, language/en/notices.php |
| Tests | tests/notices/ |
Scheduling shows the layers working together. ScheduleNotice asks SchedulingPolicy for refusal reasons and stores the notice through NoticeRepository. The command and the management page both call it and turn its result into their own output: a line of text, JSON and an exit code, or flash messages, field errors and a redirect. Ending a notice is one guarded update, so both adapters call NoticeRepository::expire() directly.
Reading goes through the notices service. view.vars in the Registry calls active() for every rendered page, so a template shows $site_notices with one include, and /notices.json serves the same list.
Requirements
- PHP, its extensions and the CitOmni packages, with their versions:
require,suggestandconflictincomposer.json. - MySQL 8.0.16+ or MariaDB 10.6+, with the session time zone that the Db service derives from PHP's timezone. An app that sets cfg
db.timezonesets it to the zone oflocale.timezone.
Use it in an app
citomni/demo-app has every step below in place.
-
Install the package:
composer require citomni/demo-provider
-
Enable the Registry in
config/providers.php:\CitOmni\DemoProvider\Boot\Registry::class,
-
Import the schema into the app's database:
mysql -u root -p citomni < vendor/citomni/demo-provider/sql/citomni_demo-provider.sqlA database that has the schema of an earlier release takes the newer files in
vendor/citomni/demo-provider/sql/migrations/in name order instead. -
Show the notices in the app's layout, and style the classes
demoprov-notices,demoprov-noticeanddemoprov-notice-<level>:{% include "partials/notices.html@citomni/demo-provider" %} -
Schedule a notice:
php bin/citomni notice:schedule "Planned maintenance tonight 22-23." --level=warning php bin/citomni notice:listThe notice shows until it is ended.
--endssets an end, as a local time in the formYYYY-MM-DD HH:MM.
Optional:
The management page at /notices/manage.html schedules and ends notices without a login. Enable it only where every visitor may change the notices, such as a local dev machine, in config/citomni_http_cfg.dev.php:
'demo_provider' => [ 'notices' => [ 'management_enabled' => true, ], ],
To show the management page in the app's layout, override the route's template in config/citomni_http_routes.php with an app page that includes partials/manage_notices.html@citomni/demo-provider. The entry merges into the package's route, so only the template changes:
'/notices/manage.html' => [ 'template_file' => 'public/notices.html', 'template_layer' => 'app', ],
Any cfg key of the baseline in src/Boot/Registry.php, such as demo_provider.notices.max_visible, can be overridden in the app's cfg files. Lists replace lists, so an app that shows notices on some pages only sets its own view.vars.site_notices.include.
Develop the package
Install the dependencies in the package root and run the suites. The database suite connects as root to 127.0.0.1:3306 over TCP with the password in CITOMNI_TEST_PASSWORD, and creates and drops its own database, so use a local development server. tests/README.md has the rules.
composer install
composer test
To try a change in an app before it is released, point the app at the working copy with a Composer path repository, such as "repositories": [{"type": "path", "url": "../demo-provider"}], and require the branch: composer require "citomni/demo-provider:dev-main".
Package metadata
"type": "library","license"matchingLICENSE, and PSR-4 autoloading of the package namespace fromsrc/and of its tests fromtests/(autoload-dev).requireholds PHP, the extensions and the packages that the code needs in every mode, directly or through another required package. A runtime package that only one mode needs, such as citomni/http or citomni/cli, goes insuggest, with its minimum version inconflict, so an app without that mode does not have to install it.- Constraints with a caret on the lowest release that has what the code uses.
scripts.testrunstests/run.php. The branch alias ofmainnames the next release line.- No
composer.lock: the app that installs the package locks its dependencies. - Tests and repository metadata are
export-ignorein.gitattributes, so they stay out of the installed package.
Copyright
© 2026-present Lars Grove Mortensen.
The underlying CitOmni Framework is © 2012-present Lars Grove Mortensen, licensed under the MIT License.
Trademark notice
See TRADEMARKS.md for the CitOmni trademark notice applicable to this package.
License
citomni/demo-provider is released under the MIT License. See LICENSE and NOTICE.