kunstmaan/adminnode-bundle
Kunstmaan AdminNodeBundle supplies the abstract admin node base classes and helpers for building backend sections in the Kunstmaan CMS, giving Symfony developers a consistent structure for admin modules, menus, and page management.
This bundle is the admin-UI layer for Kunstmaan's NodeBundle: it wires the CMS node tree into Symfony2's admin (historically Sonata Admin) so editors can browse, create, reorder, and publish pages. Treat it as glue, not a standalone package — it assumes a Kunstmaan CMS 2.x stack.
sensio/framework-extra-bundle, Sonata Admin ~2.x). If you're on Symfony 3+ or Flex, stop here — see Gotchas.composer require kunstmaan/adminnode-bundle kunstmaan/node-bundle kunstmaan/admin-bundle
Pin to a tag or commit; there are effectively no releases to lean on.app/AppKernel.php:
new Kunstmaan\AdminNodeBundle\KunstmaanAdminNodeBundle(),
It must come after KunstmaanNodeBundle and KunstmaanAdminBundle, and after Sonata Admin is configured.Resources/config/routing.yml in the bundle and include it from app/config/routing.yml after kunstmaan_node and Sonata's _sonata_admin routes.app/console assets:install --symlink
app/console assetic:dump --env=prod
app/console cache:clear) after any service or admin-class change — Symfony2 does not hot-reload definitions.Where to look first, in this order:
Admin/ — the Sonata Admin subclasses (configureListFields, configureFormFields, getBatchActions). This is where 80% of real customization happens.Resources/config/services.yml — service IDs and the admin service tags; you'll be overriding or decorating these.Resources/views/ — Twig templates for the tree, list, and form; these are your override targets.Controller/ — the AJAX endpoints backing drag-and-drop reorder and node actions.First use case that earns its keep: expose your custom page type in the editor's node tree — create a Page entity extending the node model, register an admin service extending the bundle's node admin, and verify the page appears in the tree with working move/publish actions. That validates routing, assets, ACLs, and Sonata registration in one pass.
Subclass the bundled admin rather than configuring it. The intended extension point is inheritance:
namespace Acme\SiteBundle\Admin;
use Kunstmaan\AdminNodeBundle\Admin\NodeAdmin as BaseNodeAdmin;
class ArticlePageAdmin extends BaseNodeAdmin
{
protected $baseRouteName = 'acme_admin_articlepage';
protected $baseRoutePattern = 'article-page';
protected function configureListFields(ListMapper $list)
{
parent::configureListFields($list);
$list->add('_action', 'actions', ['actions' => ['edit' => [], 'delete' => []]]);
}
}
Register it as a service tagged sonata.admin with the node manager injected, and set setSubClasses() / setClass() to your entity. Match the service-ID convention (kunstmaan_adminnode.admin.*) so menu and route conventions keep working.
Wire the entity into the tree, not just the admin. A page type is only usable once it's a node subclass and has its page-part configuration. The typical flow: entity → admin service → Sonata AdminExtension/menu entry → tree visibility. Skipping the node-subclass step is the classic reason a page type "exists but can't be created."
Template overrides as the primary customization surface. Rather than forking, override in your app bundle:
app/Resources/KunstmaanAdminNodeBundle/views/...
Symfony2's bundle inheritance picks these up automatically. Extend the parent template with {{ parent() }} and add blocks — never copy-paste wholesale; you'll lose upstream fixes (such as they are).
Reorder / AJAX actions. The drag-and-drop handler posts to a controller action in this bundle. If you add custom tree behavior, follow the same contract: JSON response, route name referenced from the list template's JS, CSRF token where the parent action requires one. Debug by watching the network tab — a silent no-op is almost always a 403 from CSRF or a mismatched route.
Batch and lifecycle operations. Publish/unpublish/delete of nodes is a multi-step operation (create a NodeVersion, flip the node's public state, invalidate caches). If you add a custom batch action, delegate to the node service rather than manipulating the entity directly; otherwise versions and the tree position get out of sync.
ACL integration. Permissions are enforced per node. Configure your voter/ACL mappings so editors see only their subtrees. This is also a good place to add a custom Voter if your roles differ from Kunstmaan's defaults — hook it in via security.yml and validate against the admin list, which hides unauthorized nodes rather than throwing.
Integration tips.
sonata_admin options (templates, security_handler) in one config file; the bundle inherits them.Platform lock-in is the headline risk. This is Symfony2 / PHP 5.x code with a Sonata Admin 2.x dependency. It will not run on Symfony 4+, and the adminnode piece is superseded by the monolithic kunstmaan/bundles-cms (and the kunstmaan/admin-bundle/node-bundle split) in later CMS versions. With 2 stars and zero dependents, treat this repo as archival: pin an exact commit, and if you're starting greenfield, use the maintained monorepo instead.
The tree silently does nothing without assets. If drag-and-drop renders but doesn't respond, run assets:install and assetic:dump for the correct environment. Also check that jQuery/whatever JS the list template expects is actually loaded — Sonata's layout changes between minor versions break this quietly.
Sonata Admin version drift. Even within Symfony2, a Sonata minor bump can change template blocks or Admin method signatures and break overrides. Pin sonata-project/admin-bundle alongside this package and upgrade the two together.
Route and menu conflicts. Duplicate baseRouteName values or two admin services on the same entity cause "route already exists" or a missing menu entry. Grep your services.yml for the route name before adding a new admin class.
ACLs fail closed, confusingly. An empty tree or a 403 on node edit usually means ACL entries were never initialized after adding a new node type, not a routing bug. Re-run your ACL init command for existing nodes.
Container cache is your enemy. Symfony2 caches compiled containers aggressively. After editing services.yml, always cache:clear — and for a service-decorating change, clear both dev and prod caches, since the prod container is compiled separately.
Debugging order when something looks broken:
app/console debug:container | grep adminnode — is the service registered?app/console debug:router | grep <baseRouteName> — is routing live?app/logs/dev.log — Sonata swallows exceptions in list rendering; the real error is only in the log.Extension points, in order of preference: (1) template overrides in app/Resources, (2) subclass the bundled admin, (3) decorate a service via services.yml, (4) fork — last resort, and only if you accept maintaining a dead branch.
How can I help you explore Laravel packages today?