elephentity / codegen-wordpress
The WordPress builder for Elephentity: compiles the IR into the physical schema WordPress needs. Build-time only.
Package info
github.com/hsimah-services/elephentity-codegen-wordpress
pkg:composer/elephentity/codegen-wordpress
Requires
- php: >=8.3
- symfony/yaml: ^7.0 || ^8.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0 || ^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-20 23:08:51 UTC
README
The WordPress builder for Elephentity.
Implemented in Rust. Build a checkout with cargo build --release --locked, or install
the executable on PATH with cargo install --path . --locked. The bin/eleph-gen-wordpress
checkout launcher uses target/release/eleph-gen-wordpress (or a debug build during development).
It never falls back to PHP. Installed Cargo binaries need neither PHP nor Cargo to run.
It reads one JSON request on stdin — the compiled spec, plus the target's configuration — and writes one JSON response on stdout: a path and a body per file. It never touches the filesystem. Signing and writing happen in elephentity-codegen, after this exits.
echo '{"elephentity":1,"irVersion":"1.1","target":"wordpress","config":{}, "outputDirectory":"out","schema":{}}' | ./bin/eleph-gen-wordpress
That fails on the empty schema, which is the point: it should be obvious how.
Installing it
# From this repository: cargo install --path . --locked # Or, when using the Composer distribution: composer require --dev elephentity/codegen-wordpress cargo build --release --locked --manifest-path vendor/elephentity/codegen-wordpress/Cargo.toml
Use "builder": "eleph-gen-wordpress" for a Cargo installation, or the Composer
launcher as shown below. Then name it in eleph.json:
{
"targets": {
"wordpress": {
"builder": "vendor/bin/eleph-gen-wordpress",
"output": "generated/wordpress"
}
}
}
Only where the project's project.yml names driver: wordpress — configuring this
target for another driver is a response with an error, not a file.
What it provides
- The
wordpressdriver, and the rules it imposes onstorage.handle— a 20-character, lowercase-slug limit — so a spec is validated against this driver's own declaration rather than one hardcoded into the compiler. - The
Taxonomypattern (embedded inrust/provides.json): a project mayuse:it with nothing underspec/patterns/. - The physical schema
elephentity/wordpress's adaptor loads at boot: table definitions, edge placements, post type and taxonomy registration arguments.
It depends on nothing of Elephentity's
The builder owns its typed wire IR in rust/ir.rs and emits runtime class names as
strings. Protocol and IR versions are checked before reading the schema. Static
capability declarations are embedded from rust/provides.json; their golden describe
responses ensure the compiler sees the same integration, driver, and pattern contracts.
Working on it
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test --locked
./tools/php composer ci
Rust sources live in rust/. Each builder owns its IR types and version gate; there
is no runtime dependency on the compiler or another builder. PHP in src/ and the
bin/eleph-gen-wordpress-reference executable is retained as a migration oracle for the
existing tests. Production entrypoints run Rust only. PHPStan still checks the reference
and acceptance tests at level max.
The golden fixtures
tests/fixtures/golden/*/ holds a committed request and the exact response it
produces, asserted byte for byte through the real binary. When a deliberate change
moves them, regenerate and read the diff — it is the clearest description available of
what the change did to every project's generated tree.
Admin views and linked posts
Elephentity records own their identity and relationships. The WordPress driver stores records in custom tables. Admin list/detail templates are generated by default; WordPress post linking is off by default. These choices are independent.
Declare project settings in spec/project.yml:
integrations: wordpress: adminTemplates: true linkPosts: false
Override either setting on an entity (the project must declare wordpress first):
entity: Item storage: table: item handle: item integrations: wordpress: linkPosts: true
Omitted or null entity settings inherit the project setting. Without a project
setting, adminTemplates defaults to true and linkPosts defaults to false.
showInAdmin: false still suppresses admin pages. Account and taxonomy entities
retain their native WordPress storage and do not get these templates or linked posts.
| Admin templates | Linked posts | Generated behavior |
|---|---|---|
| true | false | Elephentity list/detail pages; no post type or post-link column |
| true | true | Elephentity list/detail pages; linked post type with native post UI hidden |
| false | true | Native WordPress post UI; no generated entity templates |
| false | false | Storage only; no admin pages or post type |
The builder emits admin-pages.php and admin/<Entity>/{list,detail}.php.
Register Eleph\WordPress\Admin\Pages::fromManifest($path, $runtime)->register()
on admin_menu, alongside the existing post-type registration on init. Both
list/detail files must exist to register an admin page. Templates render through the
runtime, use entity IDs, enforce read policies, escape output, and require the
manage_options capability. Views are read-only and lists are paginated.
When post linking is enabled, an entity's storage.handle names its post type.
The builder adds a nullable, unique wp_post_id column and a posts mapping to
storage-manifest.php. The adaptor creates a draft post on each entity insertion,
using title, name, or the entity name as its initial title. A WordPress creation
failure fails the entity insertion. No post ID field belongs in the domain spec;
wp_post_id is storage-owned and cannot also be declared by a field or edge.
Entity foreign keys continue to reference entity id, never wp_post_id or
WordPress post_parent. Post content and subsequent title changes are not synced.
OrphanGuard, hooked on before_delete_post, now clears the link when a post is
deleted. It preserves the record so external WordPress deletion cannot bypass
Elephentity's relationship rules. Legacy hand-declared postId fields are ordinary
fields and should be removed from specs when adopting the integration. Existing
records are not backfilled with posts. Existing database columns are not dropped
by disabling generation; review the migration plan when changing these settings.
Deploy the updated WordPress runtime with the generated files: older runtimes do not support the new manifest argument or admin classes. Clog demonstrates default unlinked records and an Item entity that opts into linked posts.