Install
Works with Drupal: ^11.1 || ^12Using Composer to manage Drupal site dependencies
Alternative installation files
Release notes
Shortcode 3.0.0 — Drupal 12 compatibility and modernization
This is a **breaking release** for anyone maintaining a custom Shortcode plugin (their own `Plugin\Shortcode` class). It does not affect site builders who only use the bundled tags — enabling the module and existing content both continue to work unchanged. See "Breaking changes" below, and the module's `UPGRADING.md` for the full conversion guide (including a prompt you can hand to an AI coding assistant to do the conversion for you).
Requires PHP 8.3+ and Drupal 11.1 or 12.x (`core_version_requirement: ^11.1 || ^12`).
Breaking changes (custom plugins only)
- `ShortcodeBase::__construct()` no longer takes a file URL generator argument.
- `getMediaFileUrl()`, `getMediaField()`, and `getImageProperties()` have been
removed from `ShortcodeBase`. Use the new `MediaUrlResolver` service instead
(inject `Drupal\shortcode\MediaUrlResolverInterface`).
- `getUrlFromPath()` / `getMidFromPath()` moved out of `ShortcodeBase` into
`Drupal\shortcode\Plugin\MediaUrlResolverTrait`.
A plugin that only declares `#[Shortcode(...)]` / `@Shortcode(...)` and overrides
`process()`/`tips()`, with no constructor of its own and none of the methods above,
needs no changes at all.
Added
- PHP attribute-based plugin discovery (`#[Shortcode(...)]`, `#[Filter(...)]`) —
annotation-based plugins (`@Shortcode(...)`) keep working side by side.
- New `MediaUrlResolver` service and `MediaUrlResolverTrait`, consolidating media
file URL, image property, and image style lookups behind one injectable service.
- Unit test coverage for the shortcode parser (`ShortcodeService::process()`).
- `#[\Override]` attributes on every overriding/implementing method, for clearer
static analysis and IDE support.
Changed
- Object-oriented `#[Hook]` implementations replace procedural hooks throughout.
- Constructor property promotion and container autowiring everywhere; hand-written
`create()` methods removed wherever autowiring already covers every dependency.
- `declare(strict_types=1)` and full parameter/return type hints added across the
module.
- `ShortcodeService`'s internal caching switched from `drupal_static()` to instance
properties.
- `ShortcodeService::process()` decomposed into smaller, named private methods
(behavior-preserving, covered by the new unit test).
- `core_version_requirement` raised to `^11.1 || ^12` on all three sub-modules.
Removed
- Legacy procedural hook shims in `shortcode.module` and
`shortcode_basic_tags.module` — superseded by the OOP `#[Hook]` methods.
- Dead code and stray debug leftovers.
- Deprecated `Drupal\Core\Language\Language` usage, replaced with
`LanguageInterface`.
Fixed
- A `Markup`-vs-`string` return type mismatch in `ShortcodeBase::render()`.
- A `NULL` passed as a shortcode's text for self-closing tags.
- An unguarded `TypeError` risk when resolving a deleted media entity's file URL.
Full details: `CHANGELOG.md`. Plugin migration guide: `UPGRADING.md`.