PHPackages                             elazhari/sulu-admin-bar-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Admin Panels](/categories/admin)
4. /
5. elazhari/sulu-admin-bar-bundle

ActiveSymfony-bundle[Admin Panels](/categories/admin)

elazhari/sulu-admin-bar-bundle
==============================

Frontend admin bar for the Sulu CMS: edit the current page or custom entity, add new content and log out, directly from the website.

v1.0.0(1mo ago)01MITPHP ^7.2 || ^8.0

Since Jul 2Compare

[ Source](https://github.com/Melazhari1/sulu-admin-bar-bundle)[ Packagist](https://packagist.org/packages/elazhari/sulu-admin-bar-bundle)[ Docs](https://github.com/elazhari/sulu-admin-bar-bundle)[ RSS](/packages/elazhari-sulu-admin-bar-bundle/feed)WikiDiscussions Synced 1mo ago

READMEChangelogDependencies (12)Versions (2)Used By (0)

AdminBarBundle
==============

[](#adminbarbundle)

[![CI](https://github.com/elazhari/sulu-admin-bar-bundle/actions/workflows/ci.yml/badge.svg)](https://github.com/elazhari/sulu-admin-bar-bundle/actions/workflows/ci.yml)[![Latest Version](https://camo.githubusercontent.com/6f915e6087d6e1cd5decbda3fb15b8bb6c174bf9301fb23fbab33af0d7ea0822/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f656c617a686172692f73756c752d61646d696e2d6261722d62756e646c652e737667)](https://packagist.org/packages/elazhari/sulu-admin-bar-bundle)[![License](https://camo.githubusercontent.com/127cb075a02f4ab9d8d253d59cb7fa976832cb056909b9c3ce77f7d8da34e1e9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f656c617a686172692f73756c752d61646d696e2d6261722d62756e646c652e737667)](LICENSE)

A frontend admin bar for **Sulu CMS**. Backend users who are logged into the Sulu admin see a slim toolbar on top of the website with direct links to edit the content they are looking at. Anonymous visitors see nothing — and the page HTML stays fully HTTP cacheable.

```
┌──────────────────────────────────────────────────────────────────┐
│ [S] Sulu                        John Doe | Edit | Add new | Logout │
└──────────────────────────────────────────────────────────────────┘

```

Features
--------

[](#features)

- **Edit** the current page — or any custom entity (Formation, Article, …) detected automatically, without per-entity code.
- **Add new** content of the same type as the current page.
- **Permission-aware**: links are resolved server-side from Sulu's view registry, so users only ever see links they are allowed to use.
- **Cache-safe**: no user-specific markup in the page HTML.
- **Silent for visitors**: anonymous visitors trigger no extra request at all (session marker cookie).
- **Sulu 2 and Sulu 3** compatible, PHP &gt;= 7.2.
- **One-command installer.**

Installation
------------

[](#installation)

### Quick install (recommended)

[](#quick-install-recommended)

Install the package and run the installer with the PHP binary your project uses (the installer needs PHP &gt;= 7.3):

```
composer require elazhari/sulu-admin-bar-bundle
php vendor/elazhari/sulu-admin-bar-bundle/install.php
```

Alternatively, copy the bundle into your Sulu project (e.g. to `bundles/AdminBarBundle`) and run:

```
php bundles/AdminBarBundle/install.php
```

It performs every manual step listed below — composer autoload entry, bundle registration, route import, default configuration, the security `access_control` rule, `{{ sulu_admin_bar() }}` in `templates/base.html.twig`, `composer dump-autoload`, `assets:install` and cache clearing.

The installer is idempotent (running it twice is safe), reports a `[WARN]`with manual instructions for anything it cannot patch automatically (e.g. a heavily customized security config), and accepts `--skip-commands` if you only want the file changes without running composer/console commands.

### Manual installation

[](#manual-installation)

**1. Register the code** — as a composer package:

```
composer require elazhari/sulu-admin-bar-bundle
```

Or, as a local bundle copied to `bundles/AdminBarBundle`, add the namespace to your project's `composer.json` and dump the autoloader:

```
"autoload": {
    "psr-4": {
        "App\\": "src/",
        "Elazhari\\SuluAdminBarBundle\\": "bundles/AdminBarBundle/src/"
    }
}
```

```
composer dump-autoload
```

**2. Enable the bundle:**

```
// config/bundles.php
return [
    // ...
    Elazhari\SuluAdminBarBundle\AdminBarBundle::class => ['all' => true],
];
```

**3. Import the route:**

```
# config/routes/admin_bar.yaml
admin_bar:
    resource: '@AdminBarBundle/config/routes.yaml'
```

**4. Allow anonymous access to the endpoint.** It must stay inside the admin firewall but must not trigger the admin login — it answers `401` itself. Add this rule **above** the admin catch-all, using your admin base path (`/admin` in a stock Sulu project, `/_private`, `/backend`, … in customized ones):

```
# config/packages/security.yaml
# (or security_admin.yaml in projects with kernel specific security configs)
access_control:
    # ...
    - { path: ^/admin/admin-bar$, roles: PUBLIC_ACCESS }
    - { path: ^/admin, roles: ROLE_USER }
```

On Symfony versions without the `PUBLIC_ACCESS` attribute use `IS_AUTHENTICATED_ANONYMOUSLY` instead (the installer picks whichever the file already uses).

**5. Install the assets:**

```
php bin/console assets:install public
```

**6. Add the bar to your base layout**, right before ``:

```
{# templates/base.html.twig #}
        {{ sulu_admin_bar() }}

```

Finally clear the caches:

```
php bin/console cache:clear
php bin/websiteconsole cache:clear
```

Log into the admin once, then open the website: the bar appears.

How it works
------------

[](#how-it-works)

In a standard Sulu setup only the admin (`/admin` by default — the bundle adapts to any custom prefix, see below) is behind a firewall and website responses are cached by the HTTP cache. Rendering a user-specific bar directly into the page HTML would therefore either never see the admin session or leak the bar into cached responses. This bundle avoids both:

1. `{{ sulu_admin_bar() }}` renders a tiny, **visitor-independent** loader `` carrying the current page context (webspace, locale, page uuid or entity id) as data attributes — safe to cache.
2. While using the admin, a response listener sets a JS-readable session marker cookie (`sulu_admin_bar`) and removes it again on logout. The cookie carries no data; it only tells the loader that an admin session exists, so **anonymous visitors never call the endpoint at all**.
3. When the marker is present, the script calls `GET /admin-bar`(e.g. `/admin/admin-bar`), which runs through the **admin firewall**, so the Sulu admin session is available there.
4. If the user is authenticated, the endpoint returns their name and the permission-checked admin URLs; the script injects the stylesheet and the bar. Otherwise it returns `401`, the stale marker is dropped and nothing is rendered.

What the bar shows
------------------

[](#what-the-bar-shows)

ElementBehaviourSulu logoLinks to the Sulu admin.User nameFull name of the logged-in Sulu user (falls back to the username).EditOpens the current page or entity in its Sulu admin edit form.Add newOpens the creation form for the current content type; outside of any content context it opens the page list of the webspace.LogoutCalls the Sulu admin logout route.Permissions are checked server-side with Sulu's `SecurityChecker` — against the `sulu.webspaces.` security context for pages and against the entity's admin views (plus the optional configured `security_context`) for custom entities — so links the user is not allowed to use are never rendered.

Configuration
-------------

[](#configuration)

Everything works without configuration. The full reference:

```
# config/packages/admin_bar.yaml
admin_bar:
    enabled: true   # set to false to remove the loader snippet entirely

    # Base path of the Sulu admin — see "Custom admin URL" below.
    # Auto-detected when omitted; falls back to /admin.
    #admin_base_path: /admin

    # Texts of the toolbar links — override them to localize the bar.
    labels:
        edit: Edit
        add: Add new
        logout: Logout

    # Optional per-entity extras — see "Custom entities" below.
    entities:
        formation:                                        # request attribute
            resource_key: formations                      # Sulu resource key
            security_context: sulu.formations.formation   # optional extra gate
            routes: [formation]                           # optional route names
```

Custom admin URL
----------------

[](#custom-admin-url)

Nothing about the admin URL is hardcoded. The endpoint route is registered as `/admin-bar`, and the base path is resolved per kernel:

1. `admin_bar.admin_base_path`, when configured explicitly;
2. otherwise **auto-detected** from the Sulu admin firewall pattern in your `security` configuration (`^/admin(\/|$)`, `^/_private`, `^/backend`, …);
3. otherwise Sulu's default `/admin`.

So `/admin`, `/_private`, `/backend`, `/cms` or any other prefix works out of the box as long as the security configuration is visible to both Sulu kernels (the standard skeleton's single `security.yaml`).

Set `admin_base_path` explicitly in one case: your project uses **kernel specific security configs** (`security_admin.yaml` / `security_website.yaml`). The website kernel then has no admin firewall to inspect, and the loader would point to the default `/admin`. Since `config/packages/admin_bar.yaml`is shared by both kernels, one line fixes it:

```
admin_bar:
    admin_base_path: /_private
```

(The installer detects your admin path and writes this line for you.)

Custom entities
---------------

[](#custom-entities)

Sulu projects often route Doctrine entities through the RouteBundle with a `RouteDefaultsProviderInterface` implementation. When such a provider exposes the entity as a request attribute in its route defaults:

```
public function getByEntity($entityClass, $id, $locale, $object = null)
{
    return [
        '_controller' => '...',
        'id' => $formation->getId(),
        'formation' => $formation,   //
