netgen/admin-ui-bundle
Netgen Admin UI Bundle is a Symfony bundle that provides a responsive, Bootstrap-based admin interface with reusable Twig templates, UI components, layouts, forms, and navigation for building consistent back-office screens faster.
What this package is. netgen/admin-ui-bundle layers the classic eZ Publish Legacy administration interface on top of an eZ Platform (2.x) install. It does not reimplement an admin UI in Symfony — it boots the legacy kernel alongside the Platform kernel and routes admin requests into it, so editors get the familiar content tree, class editor, and legacy modules while content actually lives in the Platform repository.
Prerequisites you need before touching the bundle:
AppKernel).ezpublish_legacy/ or a configured legacy root.Minimal steps:
composer require netgen/admin-ui-bundle
Register the bundle (and any Netgen dependencies it pulls in) in app/AppKernel.php:
$bundles = [
// ...
new Netgen\Bundle\AdminUIBundle\NetgenAdminUIBundle(),
];
Import its routing so the legacy admin is reachable at a known prefix:
# app/config/routing.yml
netgen_admin_ui:
resource: "@NetgenAdminUIBundle/Resources/config/routing.yml"
prefix: /adminui
Point the bundle at your legacy installation (legacy root, admin siteaccess, legacy URI prefix) per the README's config block, then:
php bin/console cache:clear
php bin/console assets:install --symlink web
# legacy assets, typically via the legacy bundle's own command
php bin/console ezpublish:legacy:assets_install --symlink web
Log in at your configured admin path and confirm you see the legacy admin chrome backed by Platform content.
Where to look first. Read DependencyInjection/Configuration.php for the real config keys (don't guess from blog posts — this bundle's options have changed across releases), then Resources/config/routing.yml to see exactly which URLs are captured. Resources/views and the legacy design/template overrides tell you what is themeable versus hardcoded.
First use case. The one that sells this bundle: a client migrating from eZ Publish 4/5 who cannot retrain 40 editors on the Platform Studio UI. You keep their editing workflow byte-for-byte identical while the content model moves to the Platform repository.
Route partition: admin vs. front end. The usual layout is a legacy siteaccess for /adminui and a Platform siteaccess for everything else. Keep the prefixes strictly separated — the legacy kernel is dispatched as a sub-request, and overlapping matchers are the number-one source of "why is my Symfony controller returning legacy HTML" bugs. Verify with bin/console debug:router.
Theme customisation via design overrides, not vendor edits. Legacy admin templates are overridden through the legacy design system (design/ezdemo/override/templates/... or a custom design extension), not by editing files inside vendor/netgen. Register your design in the legacy design.ini override and add template rules in override.ini. This is the only path that survives a composer update.
Custom admin modules. New screens are legacy extensions with a module/view, registered in module.ini.append.php and menu.ini.append.php so they appear in the admin navigation. Build them as a standalone legacy extension (e.g. extension/myadmin/) rather than dropping PHP into the legacy root — the extension is deployable and reviewable, the root is not.
Content events belong on the Platform side. If you need to react to publishing (indexing, notifications, syncing), subscribe to eZ\Publish\API\Repository\Events / the ContentService in Symfony, not to legacy publish hooks. Legacy-side hooks fire for legacy-originated edits only and will silently miss anything published through the Platform API or migrations.
Permissions split across two systems. Legacy policies (role.ini / legacy role management) and Platform roles are two separate stores over one content tree. The practical pattern is to treat the legacy role model as the single source of truth for editors and grant the corresponding Platform role programmatically, or to run editors entirely through the legacy UI so Platform roles never need to be touched by humans. Never leave a human maintaining both.
Multi-site. One legacy siteaccess per Platform siteaccess, matched by host/URL. Configure the legacy siteaccess mapping to mirror your Platform mapping exactly; a mismatch means editors see the wrong content tree root and file it as a bug against your front end.
Deployment integration. Your deploy script now has two caches and two asset pipelines. A working sequence looks like:
composer install --no-dev --optimize-autoloader
php bin/console cache:clear --env=prod
php bin/console assets:install web --symlink --relative
# legacy cache + assets via the legacy commands you already use
Add legacy var/ and the web/var symlink target to your writable-paths list (shared between releases, permissions owned by the web user).
It is effectively unmaintained. Last tagged release July 2019, 33 stars, zero dependents. It targets eZ Platform 2.x on Symfony 3.4/4.x; it will not work on Ibexa 3/4 without porting. Budget for pinning the whole stack, or treat this as a stopgap with an explicit exit plan. Treat the GPL-2.0 licence as real: copyleft obligations apply to anything you distribute, and internal-only use is fine but forks stay GPL.
Two kernels, two log files, two cache problems. When something breaks you get to guess which stack failed. First debugging move: check var/logs/ (Platform) and the legacy var/log/ (often storage/logs/) in the same minute. Second move: clear both caches — clearing only the Symfony cache after a legacy template edit explains most "my change didn't apply" reports.
Sessions and login. Legacy has its own session handling and cookie name. If it isn't configured to share with the Symfony session, editors get double-login prompts and randomly dropped sessions when they cross between admin and front end. Test this on a real browser, not curl, and test it behind your actual reverse proxy.
Asset symlinks and permissions. The legacy design needs its own web/var symlink; missing or root-owned symlinks produce a blank admin page with no PHP error. After every deploy, load the admin UI as a non-admin user and confirm CSS/images load — the failure mode is silent.
Content type drift is the sneakiest failure. Editing a class through the legacy UI and through Platform migrations against the same repository can produce schema that neither side fully understands. Pick one authoring path for class definitions and forbid the other by policy.
Do not patch vendor code, even "temporarily." Extend via legacy extensions, design overrides, and Symfony event subscribers. The bundle's DependencyInjection compiler passes and services are the documented extension points; direct file edits get wiped on the next deploy and take a week to rediscover.
Legacy stack on modern PHP. The bundled zf1/ezc libraries throw deprecations and hard errors past PHP 7.4. Pin PHP explicitly in composer.json (config.platform) so CI doesn't resolve a combination that boots in tests but not in production.
Watch route order. Because the bundle registers a catch-all-ish legacy route, place it after your Platform routes in routing.yml and scope it tightly by prefix. A wrongly ordered import can swallow /api or /admin Platform endpoints, and the resulting 404s look like a Platform bug.
Set expectations with the client. This bundle buys migration time; it doesn't modernise the editor experience. If the actual goal is "a nicer admin UI," look at extending the Platform admin instead — this bundle is the right tool only when the requirement is literally "keep the old screen."
How can I help you explore Laravel packages today?