Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ node_modules/
# files generated by Codeception
/tests/_output/
/tests/Support/_generated/

# AI
.claude
.mcp.json
153 changes: 153 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Admin Bundle — Claude Instructions

## Project Overview

OpenDXP Admin Bundle provides the backend UI for OpenDXP. It is built on [ExtJS](https://www.sencha.com/products/extjs/) and depends heavily on the **opendxp core** (`../opendxp`).

**Dependency on opendxp core:** This bundle depends heavily on opendxp core (models, base controllers, test infrastructure). The core location depends on the developer's setup — when you need to read core source files, check these paths in order and use the first one that exists:

1. `../opendxp/` — sibling directory (monorepo / symlinked workspace)
2. `../../vendor/open-dxp/opendxp/` — project root one level up
3. `../../../vendor/open-dxp/opendxp/` — project root two levels up

When Claude is started from **opendxp core**, admin-specific topics (UI extension, admin events, perspectives, permissions) are documented in **this** bundle — see `docs/`.

## Source Structure

```
src/
├── Command/ # CLI commands
├── Controller/Admin/ # Admin controllers (Document, Asset, DataObject, GDPR)
│ └── Document/ # Incl. DocumentController (site panel, document tree)
├── Controller/Traits/ # Shared controller traits
├── DependencyInjection/ # Bundle configuration + compiler passes
├── Enum/ # PHP enums (e.g. SiteCustomConfigNodeType)
├── Event/ # Event classes + AdminEvents constants
├── EventListener/ # Symfony event subscribers
├── Helper/ # Service helpers (e.g. GridHelperService)
├── Model/ # Admin-specific models (GridConfig, etc.)
├── Perspective/ # Perspective service logic
├── Security/ # Auth, authenticators, security tokens
├── Service/ # Grid data, workflow, etc.
├── System/ # System-level services
├── Translation/ # Translation handling
└── Twig/ # Twig extensions
```

**Key reference files:**
- `src/Event/AdminEvents.php` — all event name constants exposed by this bundle
- `src/Event/SiteCustomSettingsEvent.php` — example of an admin event class
- `src/Enum/SiteCustomConfigNodeType.php` — example enum for config nodes
- `src/Controller/Admin/Document/DocumentController.php` — main document/site controller

## Documentation

All documentation lives in `docs/`. See `docs/README.md` for the full index.

### Structure

```
docs/
├── README.md ← master index (update when adding sections)
├── 00_Architecture/
│ └── README.md ← bundle overview, core dependency explained
├── 10_Extension_Points/
│ ├── README.md ← what other bundles can extend
│ ├── 01_Events.md ← AdminEvents reference + subscription examples
│ ├── 02_Admin_UI_Assets.md ← loading JS/CSS into the admin UI
│ ├── 03_Admin_UI_JavaScript.md ← ExtJS event system, menus, key bindings
│ ├── 04_Perspectives.md ← backend UI perspectives configuration
│ ├── 05_Permissions.md ← adding custom permissions
│ ├── 06_Deeplinks.md ← deeplinks into admin interface
│ └── 07_Custom_Admin_Login.md ← custom login entry point
├── 20_Documents/
│ ├── README.md
│ └── 01_Site_Custom_Settings.md ← site-specific custom settings via events
└── 90_Testing/
└── README.md ← test conventions and how to run tests
```

### Naming conventions
- Folders: `NN_FunctionalArea/` — 10-step numbering leaves room for inserts
- Files: `NN_TopicName.md` — numbered within folder (01, 02, …)
- Each folder has a `README.md` as section index

### When to document

Document every **extension point** exposed to other bundles or applications:
- New event constant in `AdminEvents` → update `docs/10_Extension_Points/01_Events.md`
- New event class → add a doc in the relevant feature section with a full subscriber example
- New enum for config nodes → document available values and their meaning
- New controller endpoint used externally → document in the relevant feature section

### opendxp/doc/ vs. admin-bundle/docs/

Content belongs in **admin-bundle/docs/** when it is about:
- Admin UI extension (JS events, menus, assets)
- AdminEvents and event subscribers
- Backend-only features (perspectives, custom login, deeplinks, permissions)
- Site/document admin panel customization

Content belongs in **opendxp/doc/** when it is about:
- Core models and PHP API (Documents, Assets, DataObjects)
- Core events (non-admin: DocumentEvents, AssetEvents, etc.)
- Routing, MVC, deployment, infrastructure

When opendxp/doc/ contained content that belongs here, the opendxp file becomes a redirect stub pointing to admin-bundle docs.

### Document template

# Feature Name

One-line description: what it does and why it exists.

## Overview

Brief explanation of the feature, when to use it.

## API Reference

| Class / Constant | Description |
|------------------------------|-----------------------|
| `AdminEvents::CONSTANT_NAME` | When this event fires |
| `SomeEvent::addNode()` | What the method does |

## Example

```php
<?php

namespace App\EventListener;

use OpenDxp\Bundle\AdminBundle\Event\AdminEvents;
use OpenDxp\Bundle\AdminBundle\Event\SomeEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MyListener implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
AdminEvents::CONSTANT_NAME => 'onEvent',
];
}

public function onEvent(SomeEvent $event): void
{
// ...
}
}
```

## Stored Data / Result

Where and how the data is persisted or used downstream.

## See Also

- [Related opendxp/doc page](https://github.com/open-dxp/opendxp/blob/1.x/doc/...)
- [AdminEvents source](https://github.com/open-dxp/admin-bundle/blob/1.x/src/Event/AdminEvents.php)


## Tests
See `tests/CLAUDE.md` for full test conventions, base classes, and examples.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,18 @@ And much more ...

Following topics are short-cuts into the documentation for admin interface:

### Starting with OpenDXP Core
- [Getting Started](https://github.com/open-dxp/opendxp/blob/1.x/doc/01_Getting_Started/06_Create_a_First_Project.md)
- [User & Roles](https://github.com/open-dxp/opendxp/blob/1.x/doc/22_Administration_of_OpenDxp/07_Users_and_Roles.md)
- [Deeplinks](https://github.com/open-dxp/opendxp/blob/1.x/doc/20_Extending_OpenDxp/23_Deeplinks_into_Admin_Interface.md)
- [Admin Translations](https://github.com/open-dxp/opendxp/blob/1.x/doc/06_Multi_Language_i18n/07_Admin_Translations.md)
- [Extending Admin UI](https://github.com/open-dxp/opendxp/blob/1.x/doc/20_Extending_OpenDxp/13_Bundle_Developers_Guide/06_Event_Listener_UI.md)

### Admin Documentation
- [Architecture](docs/00_Architecture/README.md)
- [Extension_Points](docs/10_Extension_Points)
- [Deeplinks](docs/10_Extension_Points/06_Deeplinks.md)
- 🤖 [Testing with AI (Claude)](https://github.com/open-dxp/opendxp/doc/19_Development_Tools_and_Details/50_Testing_with_AI.md) - Write, run and fix tests with Claude Code

=> [Full Documentation](docs/README.md)

***

Expand Down
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@
"cbschuld/browser.php": "^1.9.6",
"endroid/qr-code": "^4 || ^5.1",
"phpoffice/phpspreadsheet": "^2.2 || ^3.3",
"open-dxp/opendxp": "^1.2.0",
"open-dxp/opendxp": "^1.3.0",
"symfony/webpack-encore-bundle": "^2.1.1"
},
"require-dev": {
"codeception/codeception": "5.2.2",
"codeception/module-symfony": "^3.1",
"codeception/codeception": "^5.3.5",
"codeception/stub": "^4.3",
"codeception/module-asserts": "^3.2",
"codeception/phpunit-wrapper": "^9",
"codeception/module-symfony": "^3.8",
"phpstan/phpstan": "2.1.33",
"phpstan/phpstan-symfony": "^2.0.9",
"phpunit/phpunit": "^9.3",
"phpunit/phpunit": "^10.5",
"symfony/dotenv": "^7.4",
"symfony/runtime": "^7.4"
},
Expand Down
71 changes: 71 additions & 0 deletions docs/00_Architecture/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Architecture

## What Is This Bundle?

The Admin Bundle provides the **backend UI** for OpenDXP. It renders the document tree,
asset manager, object editor, user management, and all other admin panels using the
[ExtJS](https://www.sencha.com/products/extjs/) framework on the frontend and Symfony
controllers on the backend.

## Relationship to opendxp Core

This bundle depends heavily on the **opendxp core** (`open-dxp/opendxp`). The core provides:

| From core | Used by admin-bundle |
|---------------------------|-------------------------------------------------|
| `OpenDxp\Model\*` | Document, Asset, DataObject, Site models |
| `OpenDxp\Event\*` | Core events (DocumentEvents, AssetEvents, etc.) |
| `OpenDxp\Controller\*` | Base controller classes |
| `OpenDxp\Tests\Support\*` | Base test classes (ModelTestCase) |
| `OpenDxp\Config` | Global configuration |

The admin-bundle adds its **own** event layer on top (`src/Event/AdminEvents.php`) for
events that are specific to the admin UI lifecycle.

## Source Layout

```
src/
├── Command/ # CLI commands (e.g. cache warm-up, admin user management)
├── Controller/
│ ├── Admin/ # Admin controllers, one subfolder per element type
│ │ ├── Asset/
│ │ ├── DataObject/
│ │ ├── Document/ # DocumentController — tree, site panel, site custom settings
│ │ └── ...
│ └── Traits/ # Shared controller traits
├── DependencyInjection/ # Bundle extension + compiler passes
├── Enum/ # PHP enums for typed config values
├── Event/ # Admin event classes + AdminEvents constants
├── EventListener/ # Symfony event subscribers (internal)
├── Helper/ # Stateless service helpers (e.g. GridHelperService)
├── Model/ # Admin-only models (GridConfig, GridConfigShare, etc.)
├── Perspective/ # Perspective resolution and serialization
├── Security/ # Admin authentication, authenticators, security tokens
├── Service/ # Application services (grid data, workflow)
├── System/ # System-level services
├── Translation/ # Admin translation handling
└── Twig/ # Twig extensions for admin templates
```

## Frontend Assets

JavaScript and CSS live in `public/js/` and `public/css/`. The bundle uses
[Webpack Encore](https://symfony.com/doc/current/frontend/encore/simple-example.html)
(`webpack.config.js`) for asset compilation.

Key JS entry points:
- `public/js/opendxp/events.js` — all frontend event constants
- `public/js/opendxp/document/tree.js` — document tree rendering

## Configuration Namespace

The bundle registers its configuration under `opendxp_admin`:

```yaml
opendxp_admin:
custom_admin_path_identifier: ~
custom_admin_route_name: ~
user:
default_key_bindings: ~
```
95 changes: 95 additions & 0 deletions docs/10_Extension_Points/01_Events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Admin Events

All event constants for the admin-bundle are defined in
[`src/Event/AdminEvents.php`](https://github.com/open-dxp/admin-bundle/blob/1.x/src/Event/AdminEvents.php).

## How to Subscribe

Implement `EventSubscriberInterface` in your bundle and return the event constant(s) you want to handle:

```php
<?php

namespace MyBundle\EventListener;

use OpenDxp\Bundle\AdminBundle\Event\AdminEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MyAdminListener implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
AdminEvents::DOCUMENT_GET_PRE_SEND_DATA => 'onPreSendData',
];
}

public function onPreSendData(ElementAdminStyleEvent $event): void
{
// ...
}
}
```

Symfony autoconfiguration registers the subscriber automatically when `EventSubscriberInterface` is implemented.

## Event Categories

### Document Events

| Constant | Event Class | Description |
|----------------------------------|-------------|----------------------------------------------|
| `DOCUMENT_GET_PRE_SEND_DATA` | — | Before document data is sent to the frontend |
| `DOCUMENT_LIST_BEFORE_LIST_LOAD` | — | Before document listing is loaded |
| `DOCUMENT_LIST_AFTER_LIST_LOAD` | — | After document listing is loaded |

### Asset Events

| Constant | Event Class | Description |
|-------------------------------|-------------|-------------------------------------------|
| `ASSET_GET_PRE_SEND_DATA` | — | Before asset data is sent to the frontend |
| `ASSET_LIST_BEFORE_LIST_LOAD` | — | Before asset listing is loaded |
| `ASSET_LIST_AFTER_LIST_LOAD` | — | After asset listing is loaded |

### Object Events

| Constant | Event Class | Description |
|--------------------------------|-------------|-------------------------------------------------|
| `OBJECT_GET_PRE_SEND_DATA` | — | Before data object data is sent to the frontend |
| `OBJECT_LIST_BEFORE_LIST_LOAD` | — | Before object listing is loaded |
| `OBJECT_LIST_AFTER_LIST_LOAD` | — | After object listing is loaded |

### Element Style Events

| Constant | Event Class | Description |
|----------------------------------------|--------------------------|--------------------------------------------------------|
| `ELEMENT_ADMIN_STYLE_GET_FOR_DOCUMENT` | `ElementAdminStyleEvent` | Customize admin style (icon, CSS class) for a document |
| `ELEMENT_ADMIN_STYLE_GET_FOR_ASSET` | `ElementAdminStyleEvent` | Customize admin style for an asset |
| `ELEMENT_ADMIN_STYLE_GET_FOR_OBJECT` | `ElementAdminStyleEvent` | Customize admin style for a data object |

### Login Events

| Constant | Event Class | Description |
|---------------------|-------------------------------|---------------------------------------|
| `LOGIN_CREDENTIALS` | `Login\LoginCredentialsEvent` | After login credentials are submitted |
| `LOGIN_FAILED` | `Login\LoginFailedEvent` | After a failed login attempt |

### Perspective Events

| Constant | Event Class | Description |
|--------------------------------|-------------|----------------------------------------------|
| `PERSPECTIVE_PRE_GET_RUNTIME` | — | Before perspective runtime data is assembled |
| `PERSPECTIVE_POST_GET_RUNTIME` | — | After perspective runtime data is assembled |

### Site Events

| Constant | Event Class | Description |
|------------------------|---------------------------|-----------------------------------------------------------------------------------|
| `SITE_CUSTOM_SETTINGS` | `SiteCustomSettingsEvent` | Fired when the site panel renders or saves, allows injecting custom config fields |

See [Site Custom Settings](../20_Documents/01_Site_Custom_Settings.md) for a full example.

## See Also

- [AdminEvents source](https://github.com/open-dxp/admin-bundle/blob/1.x/src/Event/AdminEvents.php)
- [Core events (non-admin)](https://github.com/open-dxp/opendxp/blob/1.x/doc/20_Extending_OpenDxp/11_Event_API_and_Event_Manager.md)
Loading