Skip to content

Repository files navigation

portadesign/element-tree-restrictions

Per-path restrictions for Pimcore Studio Element Tree widgets. Restricts which data-object classes can be created, moved, or pasted under matching parent paths. Frontend-only enforcement (intended for editor comfort, not as a security boundary).

Scope: data-object only. Assets and Documents are intentionally out of scope. For the equivalent feature in classic admin UI (Ext.JS), see your portadesign/starter-pimcore-admin-ui fork — both UIs can run in parallel and use independent configuration.

Requirements

  • Pimcore 12.3+
  • Studio UI Bundle 2025.4+
  • PHP 8.3 / 8.4

Installation

composer require portadesign/element-tree-restrictions

Activate the bundle in config/bundles.php if not auto-discovered:

Portadesign\Bundle\ElementTreeRestrictionsBundle\PortadesignElementTreeRestrictionsBundle::class => ['all' => true],

Pre-built JS assets are committed to the repo, so consumers don't need Node/npm. After install run:

bin/console assets:install

Configuration

Definitions live in var/config/element_tree_restrictions/<slug>.yaml — one file per logical group (typically one per legacy customview). The bundle scans that directory at container build time and merges rules from every file.

Each file uses the standard Symfony root key portadesign_element_tree_restrictions with a flat rules list:

# var/config/element_tree_restrictions/faculty.yaml
portadesign_element_tree_restrictions:
    rules:
        - path: /fakulta
          allowed_classes: ['4', '17', '12', '20', '21', '24', '25', '40', '42']

        - path: /fakulta/lide
          conditionally_allowed_classes:
              folder: ['12']

See Resources/config/element_tree_restrictions.example.yaml for a fully commented example.

Rule keys

Key Type Notes
path string (regex) Required. PCRE without delimiters; substring-matched against the target element's fullPath (legacy customview style — no anchors required, but ^/... works if you want stricter matching).
restrict_folder bool Default false. If true, "Add Folder" is hidden under matching paths.
allowed_classes list<string> Class IDs (numeric or slug) allowed under matching paths, regardless of parent class.
conditionally_allowed_classes map<string, list<string>> Per parent class name (CamelCase PHP class name) or folder for plain folders → list of class IDs allowed when that is the parent.
perspective string | null Optional. Forward-compat field for binding to one Studio perspective; v1 client doesn't use it.
widget string | null Optional. Forward-compat for binding to one element-tree widget id; v1 client doesn't use it.

Semantics: intersection across matching rules

Rules combine via intersection of positive allowlists. For each matching rule that has allowed_classes or conditionally_allowed_classes, compute its per-rule allowed set at the candidate parent class C:

per-rule set = allowed_classes ∪ conditionally_allowed_classes[C]

A class X is then allowed iff:

  • No matching rule has either field (no restriction at all), or
  • X is in the intersection of all per-rule sets.

This lets you express the legacy "parent forbids broadly, child re-allows specifics" pattern as positive allowlists:

# At /fakulta and descendants, only these 9 classes are even considered.
- path: /fakulta
  allowed_classes: ['4', '17', '12', '20', '21', '24', '25', '40', '42']

# Under /fakulta/lide with parent=folder, narrow further to only class 12.
- path: /fakulta/lide
  conditionally_allowed_classes:
      folder: ['12']

At /fakulta/lide with a folder parent, both rules match. The intersection of {4,17,12,…,42} and {12} is {12} — only class 12 can be added there.

Migration from classic customviews

bin/console portadesign:element-tree-restrictions:migrate-from-customviews

Reads legacy customviews from every backend Pimcore is configured to read them from (YAML in var/config/custom_views/*.yaml, SettingsStore, etc.) and writes one file per customview into var/config/element_tree_restrictions/. The filename slug is derived from the customview's name (lowercase, non-alphanumeric → _, e.g. News(pl)news_pl.yaml).

Mapping:

Legacy customview field New rule field
Top-level classes (CSV string) Root rule's allowed_classes
extension.elementRestrictions[i].forbiddenClasses Dropped (redundant — root allowed_classes is the allowlist)
extension.elementRestrictions[i].conditionallyAllowedClasses (JSON) conditionally_allowed_classes
extension.elementRestrictions[i].restrictFolder restrict_folder: true

Flags:

  • -o, --output=<dir> — override the output directory (default: PIMCORE_CONFIGURATION_DIRECTORY/element_tree_restrictions).
  • -f, --force — overwrite existing files. Without it, existing files are skipped with a warning so manual edits are preserved.

Asset / document keys (restrictPage, restrictImage, …) are listed as warnings — Studio scope is data-object only.

If pimcore/admin-ui-classic-bundle is installed, the command delegates to its canonical Config::get(). Otherwise it falls back to LocationAwareConfigRepository directly — works even on Studio-only projects with classic admin removed.

REST endpoint

GET /api/porta-element-tree-restrictions/active

Returns the merged active rule set. Consumed automatically by the bundle's Studio plugin.

Limitations

  • Not a security boundary. The bundle ships no backend PATCH/clone guard; restrictions are enforced client-side for editor comfort only. A user with API access can bypass them.
  • Data-object only. Assets and documents are not covered.
  • Drag & drop not intercepted in v1. The data-object tree's with-droppable HOC has no public extension point, and the SDK does not export TreeNode / withDroppable. Restrictions are enforced only via context menu (Add Object, Add Folder, Paste, Cut). Drag-and-drop into a restricted target will succeed; the user can still undo or rely on context-menu workflows.

About

Pimcore Studio plugin that hides forbidden data-object classes and the Add Folder / Paste / Cut entries in the data-object tree context

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages