diff --git a/src/Asset/Elements/Asset.php b/src/Asset/Elements/Asset.php
index a9e599c00be..9d2c44ff758 100644
--- a/src/Asset/Elements/Asset.php
+++ b/src/Asset/Elements/Asset.php
@@ -32,9 +32,6 @@
use craft\errors\FsException;
use craft\errors\ImageTransformException;
use craft\errors\VolumeException;
-use craft\events\AssetEvent;
-use craft\events\DefineAssetUrlEvent;
-use craft\events\GenerateTransformEvent;
use craft\gql\interfaces\elements\Asset as AssetInterface;
use craft\helpers\Assets;
use craft\helpers\Cp;
@@ -56,6 +53,11 @@
use craft\validators\AssetLocationValidator;
use craft\web\twig\AllowedInSandbox;
use CraftCms\Aliases\Aliases;
+use CraftCms\Cms\Asset\Events\AfterGenerateTransform;
+use CraftCms\Cms\Asset\Events\BeforeDefineAssetUrl;
+use CraftCms\Cms\Asset\Events\BeforeGenerateTransform;
+use CraftCms\Cms\Asset\Events\BeforeHandleFile;
+use CraftCms\Cms\Asset\Events\DefineAssetUrl;
use CraftCms\Cms\Asset\Models\Asset as AssetModel;
use CraftCms\Cms\Asset\Validation\AssetRules;
use CraftCms\Cms\Cms;
@@ -128,40 +130,8 @@
* @property-read string|null $mimeType the file’s MIME type, if it can be determined
*/
#[Ruleset(AssetRules::class)]
-final class Asset extends Element
+class Asset extends Element
{
- // Events
- // -------------------------------------------------------------------------
-
- /**
- * @event AssetEvent The event that is triggered before an asset is uploaded to volume.
- */
- public const string EVENT_BEFORE_HANDLE_FILE = 'beforeHandleFile';
-
- /**
- * @event GenerateTransformEvent The event that is triggered before a transform is generated for an asset.
- */
- public const string EVENT_BEFORE_GENERATE_TRANSFORM = 'beforeGenerateTransform';
-
- /**
- * @event GenerateTransformEvent The event that is triggered after a transform is generated for an asset.
- */
- public const string EVENT_AFTER_GENERATE_TRANSFORM = 'afterGenerateTransform';
-
- /**
- * @event DefineAssetUrlEvent The event that is triggered before defining the asset’s URL.
- *
- * @see getUrl()
- */
- public const string EVENT_BEFORE_DEFINE_URL = 'beforeDefineUrl';
-
- /**
- * @event DefineAssetUrlEvent The event that is triggered when defining the asset’s URL.
- *
- * @see getUrl()
- */
- public const string EVENT_DEFINE_URL = 'defineUrl';
-
// Location error codes
// -------------------------------------------------------------------------
@@ -2087,35 +2057,20 @@ public function getUrl(mixed $transform = null, ?bool $immediately = null): ?str
$transform ??= $this->_transform;
- // Fire a 'beforeDefineUrl' event
- if ($this->hasEventHandlers(self::EVENT_BEFORE_DEFINE_URL)) {
- $event = new DefineAssetUrlEvent([
- 'transform' => $transform,
- 'asset' => $this,
- ]);
- $this->trigger(self::EVENT_BEFORE_DEFINE_URL, $event);
- $url = $event->url;
- } else {
- $url = null;
- }
+ event($event = new BeforeDefineAssetUrl($this, $transform));
+
+ $url = $event->url;
- // If DefineAssetUrlEvent::$url is set to null, only respect that if $handled is true
- if ($url === null && ! ($event->handled ?? false)) {
+ // If BeforeDefineAssetUrl::$url is set to null, only respect that if $handled is true
+ if ($event->url === null && ! ($event->handled ?? false)) {
$url = $this->_url($transform, $immediately);
}
- // Fire a 'defineUrl' event
- if ($this->hasEventHandlers(self::EVENT_DEFINE_URL)) {
- $event = new DefineAssetUrlEvent([
- 'url' => $url,
- 'transform' => $transform,
- 'asset' => $this,
- ]);
- $this->trigger(self::EVENT_DEFINE_URL, $event);
- // If DefineAssetUrlEvent::$url is set to null, only respect that if $handled is true
- if ($event->url !== null || $event->handled) {
- $url = $event->url;
- }
+ event($event = new DefineAssetUrl($this, $transform, $url));
+
+ // If DefineAssetUrl::$url is set to null, only respect that if $handled is true
+ if ($event->url !== null || $event->handled) {
+ $url = $event->url;
}
return $url !== null ? Html::encodeSpaces($url) : $url;
@@ -2157,17 +2112,11 @@ private function _url(mixed $transform = null, ?bool $immediately = null): ?stri
$immediately = Cms::config()->generateTransformsBeforePageLoad;
}
- // Fire a 'beforeGenerateTransform' event
- if ($this->hasEventHandlers(self::EVENT_BEFORE_GENERATE_TRANSFORM)) {
- $event = new GenerateTransformEvent([
- 'asset' => $this,
- 'transform' => $transform,
- ]);
- $this->trigger(self::EVENT_BEFORE_GENERATE_TRANSFORM, $event);
- // If a plugin set the url, we'll just use that.
- if ($event->url !== null) {
- return Html::encodeSpaces($event->url);
- }
+ event($event = new BeforeGenerateTransform($this, $transform));
+
+ // If a plugin set the url, we'll just use that.
+ if ($event->url !== null) {
+ return Html::encodeSpaces($event->url);
}
$imageTransformer = $transform->getImageTransformer();
@@ -2183,15 +2132,7 @@ private function _url(mixed $transform = null, ?bool $immediately = null): ?stri
return null;
}
- // Fire an 'afterGenerateTransform' event
- if ($this->hasEventHandlers(self::EVENT_AFTER_GENERATE_TRANSFORM)) {
- $event = new GenerateTransformEvent([
- 'asset' => $this,
- 'transform' => $transform,
- 'url' => $url,
- ]);
- $this->trigger(self::EVENT_AFTER_GENERATE_TRANSFORM, $event);
- }
+ event(new AfterGenerateTransform($this, $transform, $url));
return $url;
}
@@ -3120,14 +3061,8 @@ public function beforeSave(bool $isNew): bool
}
// Fire a 'beforeHandleFile' event if we're going to be doing any file operations in afterSave()
- if (
- (isset($this->newLocation) || isset($this->tempFilePath)) &&
- $this->hasEventHandlers(self::EVENT_BEFORE_HANDLE_FILE)
- ) {
- $this->trigger(self::EVENT_BEFORE_HANDLE_FILE, new AssetEvent([
- 'asset' => $this,
- 'isNew' => ! $this->id,
- ]));
+ if (isset($this->newLocation) || isset($this->tempFilePath)) {
+ event(new BeforeHandleFile($this, isNew: ! $this->id));
}
// Set the kind based on filename
diff --git a/src/Asset/Events/AfterGenerateTransform.php b/src/Asset/Events/AfterGenerateTransform.php
new file mode 100644
index 00000000000..d5aaf2f4867
--- /dev/null
+++ b/src/Asset/Events/AfterGenerateTransform.php
@@ -0,0 +1,20 @@
+navItems[] = [
+ * 'label' => 'Item Label',
+ * 'url' => 'my-module',
+ * 'icon' => '/path/to/icon.svg',
+ * ];
+ * }
+ * );
+ * ```
+ *
+ * [[RegisterCpNavItems::$navItems]] is an array whose values are sub-arrays that define the nav items. Each sub-array can have the following keys:
+ *
+ * - `label` – The item’s label.
+ * - `url` – The URL or path of the control panel page the item should link to.
+ * - `icon` – The path to the SVG icon that should be used for the item.
+ * - `badgeCount` _(optional)_ – The badge count number that should be displayed next to the label.
+ * - `external` _(optional)_ – Set to `true` if the item links to an external URL.
+ * - `id` _(optional)_ – The ID of the `
` element. If not specified, it will default to `nav-`.
+ * - `subnav` _(optional)_ – A nested array of sub-navigation items that should be displayed if the main item is selected.
+ *
+ * The keys of the array should define the items’ IDs, and the values should be nested arrays with `label` and `url` keys, and optionally
+ * `badgeCount` and `external` keys.
+ *
+ * If a subnav is defined, subpages can specify which subnav item should be selected by defining a `selectedSubnavItem` variable that is set to
+ * the selected item’s ID (its key in the `subnav` array).
+ */
+final class RegisterCpNavItems
+{
+ public function __construct(
+ public array $navItems,
+ ) {}
+}
diff --git a/src/Cp/Navigation.php b/src/Cp/Navigation.php
index daac99d9272..a92be45a7c0 100644
--- a/src/Cp/Navigation.php
+++ b/src/Cp/Navigation.php
@@ -7,6 +7,7 @@
use Craft;
use craft\helpers\UrlHelper;
use CraftCms\Cms\Config\GeneralConfig;
+use CraftCms\Cms\Cp\Events\RegisterCpNavItems;
use CraftCms\Cms\Edition;
use CraftCms\Cms\Plugin\Plugins;
use CraftCms\Cms\Support\Facades\Sections;
@@ -162,13 +163,9 @@ public function getItems(): array
];
}
- // Fire a 'registerCpNavItems' event
- // @TODO Bring this back
- // if ($this->hasEventHandlers(self::EVENT_REGISTER_CP_NAV_ITEMS)) {
- // $event = new RegisterCpNavItemsEvent(['navItems' => $navItems]);
- // $this->trigger(self::EVENT_REGISTER_CP_NAV_ITEMS, $event);
- // $navItems = $event->navItems;
- // }
+ event($event = new RegisterCpNavItems($navItems));
+
+ $navItems = $event->navItems;
// Figure out which item is selected, and normalize the items
$path = $this->request->getPathInfo();
diff --git a/src/Element/Concerns/Cacheable.php b/src/Element/Concerns/Cacheable.php
index ebe89315b66..2e0e1d2121e 100644
--- a/src/Element/Concerns/Cacheable.php
+++ b/src/Element/Concerns/Cacheable.php
@@ -4,7 +4,7 @@
namespace CraftCms\Cms\Element\Concerns;
-use craft\events\DefineValueEvent;
+use CraftCms\Cms\Element\Events\DefineCacheTags;
/**
* Cacheable provides cache tag management for elements.
@@ -16,15 +16,6 @@
*/
trait Cacheable
{
- /**
- * @event DefineValueEvent The event that is triggered when defining the cache tags that should be cleared when
- * this element is saved.
- *
- * @see getCacheTags()
- * @since 4.1.0
- */
- public const EVENT_DEFINE_CACHE_TAGS = 'defineCacheTags';
-
/**
* Returns the cache tags that should be cleared when this element is saved.
*
@@ -34,17 +25,9 @@ trait Cacheable
*/
public function getCacheTags(): array
{
- $cacheTags = $this->cacheTags();
-
- // Fire a 'defineCacheTags' event
- if ($this->hasEventHandlers(self::EVENT_DEFINE_CACHE_TAGS)) {
- $event = new DefineValueEvent(['value' => $cacheTags]);
- $this->trigger(self::EVENT_DEFINE_CACHE_TAGS, $event);
-
- return $event->value;
- }
+ event($event = new DefineCacheTags($this, $this->cacheTags()));
- return $cacheTags;
+ return $event->tags;
}
/**
diff --git a/src/Element/Concerns/DisplayedInIndex.php b/src/Element/Concerns/DisplayedInIndex.php
index 80232403284..096bf18f47c 100644
--- a/src/Element/Concerns/DisplayedInIndex.php
+++ b/src/Element/Concerns/DisplayedInIndex.php
@@ -9,18 +9,18 @@
use craft\base\NestedElementInterface;
use craft\db\Connection;
use craft\db\ExcludeDescendantIdsExpression;
-use craft\events\ElementIndexTableAttributeEvent;
-use craft\events\RegisterElementCardAttributesEvent;
-use craft\events\RegisterElementDefaultCardAttributesEvent;
-use craft\events\RegisterElementDefaultTableAttributesEvent;
-use craft\events\RegisterElementSearchableAttributesEvent;
-use craft\events\RegisterElementSortOptionsEvent;
-use craft\events\RegisterElementTableAttributesEvent;
use craft\helpers\ElementHelper;
use craft\models\FieldLayout;
use CraftCms\Cms\Auth\SessionAuth;
use CraftCms\Cms\Element\Element;
use CraftCms\Cms\Element\ElementSources;
+use CraftCms\Cms\Element\Events\PrepQueryForTableAttribute;
+use CraftCms\Cms\Element\Events\RegisterCardAttributes;
+use CraftCms\Cms\Element\Events\RegisterDefaultCardAttributes;
+use CraftCms\Cms\Element\Events\RegisterDefaultTableAttributes;
+use CraftCms\Cms\Element\Events\RegisterSearchableAttributes;
+use CraftCms\Cms\Element\Events\RegisterSortOptions;
+use CraftCms\Cms\Element\Events\RegisterTableAttributes;
use CraftCms\Cms\Element\Queries\Contracts\ElementQueryInterface;
use CraftCms\Cms\Element\Queries\ElementQuery;
use CraftCms\Cms\Support\Arr;
@@ -33,7 +33,6 @@
use Illuminate\Support\Facades\DB;
use Stringable;
use Tpetry\QueryExpressions\Function\Conditional\Coalesce;
-use yii\base\Event;
use yii\db\Expression;
use function CraftCms\Cms\t;
@@ -48,94 +47,6 @@
*/
trait DisplayedInIndex
{
- /**
- * @event RegisterElementSortOptionsEvent The event that is triggered when registering the sort options for the element type.
- */
- public const EVENT_REGISTER_SORT_OPTIONS = 'registerSortOptions';
-
- /**
- * @event RegisterElementTableAttributesEvent The event that is triggered when registering the table attributes for the element type.
- */
- public const EVENT_REGISTER_TABLE_ATTRIBUTES = 'registerTableAttributes';
-
- /**
- * @event RegisterElementTableAttributesEvent The event that is triggered when registering the table attributes for the element type.
- */
- public const EVENT_REGISTER_DEFAULT_TABLE_ATTRIBUTES = 'registerDefaultTableAttributes';
-
- /**
- * @event ElementIndexTableAttributeEvent The event that is triggered when preparing an element query for an element index, for each
- * attribute present in the table.
- *
- * Paired with [[EVENT_REGISTER_TABLE_ATTRIBUTES]] and [[EVENT_DEFINE_ATTRIBUTE_HTML]], this allows optimization of queries on element indexes.
- *
- * ```php
- * use CraftCms\Cms\Element\Element;
- * use CraftCms\Cms\Entry\Elements\Entry;
- * use craft\events\DefineAttributeHtmlEvent;
- * use craft\events\ElementIndexTableAttributeEvent;
- * use craft\events\RegisterElementTableAttributesEvent;
- * use craft\helpers\Cp;
- * use yii\base\Event;
- *
- * Event::on(
- * Entry::class,
- * Element::EVENT_REGISTER_TABLE_ATTRIBUTES,
- * function(RegisterElementTableAttributesEvent $e) {
- * $e->tableAttributes['authorExpertise'] = ['label' => 'Author Expertise'];
- * }
- * );
- *
- * Event::on(
- * Entry::class,
- * Element::EVENT_PREP_QUERY_FOR_TABLE_ATTRIBUTE,
- * function(ElementIndexTableAttributeEvent $e) {
- * $query = $e->query;
- * $attr = $e->attribute;
- *
- * if ($attr === 'authorExpertise') {
- * $query->andWith(['author.areasOfExpertiseCategoryField']);
- * }
- * }
- * );
- *
- * Event::on(
- * Entry::class,
- * Element::EVENT_DEFINE_ATTRIBUTE_HTML,
- * function(DefineAttributeHtmlEvent $e) {
- * $attribute = $e->attribute;
- *
- * if ($attribute !== 'authorExpertise') {
- * return;
- * }
- *
- * // The field data is eager-loaded!
- * $author = $e->sender->getAuthor();
- * $categories = $author->areasOfExpertiseCategoryField;
- *
- * $e->html = Cp::elementPreviewHtml($categories);
- * }
- * );
- * ```
- *
- * @since 3.7.14
- */
- public const EVENT_PREP_QUERY_FOR_TABLE_ATTRIBUTE = 'prepQueryForTableAttribute';
-
- /**
- * @event RegisterElementCardAttributesEvent The event that is triggered when registering the card attributes for the element type.
- *
- * @since 5.5.0
- */
- public const EVENT_REGISTER_CARD_ATTRIBUTES = 'registerCardAttributes';
-
- /**
- * @event RegisterElementCardAttributesEvent The event that is triggered when registering the card attributes for the element type.
- *
- * @since 5.5.0
- */
- public const EVENT_REGISTER_DEFAULT_CARD_ATTRIBUTES = 'registerDefaultCardAttributes';
-
/**
* @var string|null The view mode used to show this element (e.g. `structure`, `table`, `thumbs`, `cards`).
*
@@ -150,17 +61,12 @@ trait DisplayedInIndex
*/
public static function searchableAttributes(): array
{
- $attributes = static::defineSearchableAttributes();
+ event($event = new RegisterSearchableAttributes(
+ elementType: static::class,
+ attributes: static::defineSearchableAttributes(),
+ ));
- // Fire a 'registerSearchableAttributes' event
- if (Event::hasHandlers(static::class, Element::EVENT_REGISTER_SEARCHABLE_ATTRIBUTES)) {
- $event = new RegisterElementSearchableAttributesEvent(['attributes' => $attributes]);
- Event::trigger(static::class, Element::EVENT_REGISTER_SEARCHABLE_ATTRIBUTES, $event);
-
- return $event->attributes;
- }
-
- return $attributes;
+ return $event->attributes;
}
/**
@@ -285,18 +191,15 @@ public static function indexHtml(
);
// Prepare the element query for each of the table attributes
- $hasHandlers = Event::hasHandlers(static::class, Element::EVENT_PREP_QUERY_FOR_TABLE_ATTRIBUTE);
foreach ($variables['attributes'] as $attribute) {
- if ($hasHandlers) {
- // Fire a 'prepQueryForTableAttribute' event
- $event = new ElementIndexTableAttributeEvent([
- 'query' => $elementQuery,
- 'attribute' => $attribute[0],
- ]);
- Event::trigger(static::class, Element::EVENT_PREP_QUERY_FOR_TABLE_ATTRIBUTE, $event);
- if ($event->handled) {
- continue;
- }
+ event($event = new PrepQueryForTableAttribute(
+ elementType: static::class,
+ query: $elementQuery,
+ attribute: $attribute[0],
+ ));
+
+ if ($event->handled) {
+ continue;
}
static::prepElementQueryForTableAttribute($elementQuery, $attribute[0]);
@@ -498,15 +401,12 @@ public static function sortOptions(): array
...Arr::except($sortOptions, 'id'),
];
- // Fire a 'registerSortOptions' event
- if (Event::hasHandlers(static::class, Element::EVENT_REGISTER_SORT_OPTIONS)) {
- $event = new RegisterElementSortOptionsEvent(['sortOptions' => $sortOptions]);
- Event::trigger(static::class, Element::EVENT_REGISTER_SORT_OPTIONS, $event);
+ event($event = new RegisterSortOptions(
+ elementType: static::class,
+ sortOptions: $sortOptions,
+ ));
- return $event->sortOptions;
- }
-
- return $sortOptions;
+ return $event->sortOptions;
}
/**
@@ -536,17 +436,12 @@ protected static function defineSortOptions(): array
*/
public static function tableAttributes(): array
{
- $tableAttributes = static::defineTableAttributes();
-
- // Fire a 'registerTableAttributes' event
- if (Event::hasHandlers(static::class, Element::EVENT_REGISTER_TABLE_ATTRIBUTES)) {
- $event = new RegisterElementTableAttributesEvent(['tableAttributes' => $tableAttributes]);
- Event::trigger(static::class, Element::EVENT_REGISTER_TABLE_ATTRIBUTES, $event);
-
- return $event->tableAttributes;
- }
+ event($event = new RegisterTableAttributes(
+ elementType: static::class,
+ tableAttributes: static::defineTableAttributes(),
+ ));
- return $tableAttributes;
+ return $event->tableAttributes;
}
/**
@@ -588,20 +483,13 @@ protected static function defineTableAttributes(): array
*/
public static function defaultTableAttributes(string $source): array
{
- $tableAttributes = static::defineDefaultTableAttributes($source);
+ event($event = new RegisterDefaultTableAttributes(
+ elementType: static::class,
+ source: $source,
+ tableAttributes: static::defineDefaultTableAttributes($source),
+ ));
- // Fire a 'registerDefaultTableAttributes' event
- if (Event::hasHandlers(static::class, Element::EVENT_REGISTER_DEFAULT_TABLE_ATTRIBUTES)) {
- $event = new RegisterElementDefaultTableAttributesEvent([
- 'source' => $source,
- 'tableAttributes' => $tableAttributes,
- ]);
- Event::trigger(static::class, Element::EVENT_REGISTER_DEFAULT_TABLE_ATTRIBUTES, $event);
-
- return $event->tableAttributes;
- }
-
- return $tableAttributes;
+ return $event->tableAttributes;
}
/**
@@ -631,17 +519,13 @@ protected static function defineDefaultTableAttributes(string $source): array
*/
public static function cardAttributes(?FieldLayout $fieldLayout = null): array
{
- $cardAttributes = static::defineCardAttributes();
-
- // Fire a 'registerCardAttributes' event
- if (Event::hasHandlers(static::class, Element::EVENT_REGISTER_CARD_ATTRIBUTES)) {
- $event = new RegisterElementCardAttributesEvent(['cardAttributes' => $cardAttributes, 'fieldLayout' => $fieldLayout]);
- Event::trigger(static::class, Element::EVENT_REGISTER_CARD_ATTRIBUTES, $event);
+ event($event = new RegisterCardAttributes(
+ elementType: static::class,
+ cardAttributes: static::defineCardAttributes(),
+ fieldLayout: $fieldLayout,
+ ));
- return $event->cardAttributes;
- }
-
- return $cardAttributes;
+ return $event->cardAttributes;
}
/**
@@ -722,19 +606,12 @@ public static function attributePreviewHtml(array $attribute): mixed
*/
public static function defaultCardAttributes(): array
{
- $cardAttributes = static::defineDefaultCardAttributes();
-
- // Fire a 'registerDefaultCardAttributes' event
- if (Event::hasHandlers(static::class, Element::EVENT_REGISTER_DEFAULT_CARD_ATTRIBUTES)) {
- $event = new RegisterElementDefaultCardAttributesEvent([
- 'cardAttributes' => $cardAttributes,
- ]);
- Event::trigger(static::class, Element::EVENT_REGISTER_DEFAULT_CARD_ATTRIBUTES, $event);
-
- return $event->cardAttributes;
- }
+ event($event = new RegisterDefaultCardAttributes(
+ elementType: static::class,
+ cardAttributes: static::defineDefaultCardAttributes(),
+ ));
- return $cardAttributes;
+ return $event->cardAttributes;
}
/**
diff --git a/src/Element/Concerns/Eagerloadable.php b/src/Element/Concerns/Eagerloadable.php
index fca0de04184..a5edcc0a2a9 100644
--- a/src/Element/Concerns/Eagerloadable.php
+++ b/src/Element/Concerns/Eagerloadable.php
@@ -7,19 +7,18 @@
use craft\base\ElementInterface;
use craft\elements\db\EagerLoadInfo;
use craft\elements\db\EagerLoadPlan;
-use craft\events\DefineEagerLoadingMapEvent;
-use craft\events\SetEagerLoadedElementsEvent;
use craft\helpers\ElementHelper;
use CraftCms\Cms\Database\Table;
use CraftCms\Cms\Element\Element;
use CraftCms\Cms\Element\ElementCollection;
+use CraftCms\Cms\Element\Events\DefineEagerLoadingMap;
+use CraftCms\Cms\Element\Events\SetEagerLoadedElements;
use CraftCms\Cms\Field\Contracts\EagerLoadingFieldInterface;
use CraftCms\Cms\Support\Facades\Sites;
use CraftCms\Cms\User\Elements\User;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\DB;
use Tpetry\QueryExpressions\Language\Alias;
-use yii\base\Event;
use yii\base\InvalidConfigException;
/**
@@ -33,50 +32,6 @@
*/
trait Eagerloadable
{
- /**
- * @event DefineEagerLoadingMapEvent The event that is triggered when defining an eager-loading map.
- *
- * ```php
- * use CraftCms\Cms\Element\Element;
- * use craft\base\ElementInterface;
- * use craft\db\Query;
- * use CraftCms\Cms\Entry\Elements\Entry;
- * use craft\events\DefineEagerLoadingMapEvent;
- * use yii\base\Event;
- *
- * // Add support for `with(['bookClub'])` to entries
- * Event::on(
- * Entry::class,
- * Element::EVENT_DEFINE_EAGER_LOADING_MAP,
- * function(DefineEagerLoadingMapEvent $event) {
- * if ($event->handle === 'bookClub') {
- * $bookEntryIds = array_map(fn(ElementInterface $element) => $element->id, $event->elements);
- * $event->elementType = \my\plugin\BookClub::class,
- * $event->map = (new Query)
- * ->select(['source' => 'bookId', 'target' => 'clubId'])
- * ->from('{{%bookclub_books}}')
- * ->where(['bookId' => $bookEntryIds])
- * ->all();
- * $event->handled = true;
- * }
- * }
- * );
- * ```
- *
- * @since 3.1.0
- */
- public const EVENT_DEFINE_EAGER_LOADING_MAP = 'defineEagerLoadingMap';
-
- /**
- * @event SetEagerLoadedElementsEvent The event that is triggered when setting eager-loaded elements.
- *
- * Set [[Event::$handled]] to `true` to prevent the elements from getting stored to the private
- * `$_eagerLoadedElements` array.
- *
- * @since 3.5.0
- */
- public const EVENT_SET_EAGER_LOADED_ELEMENTS = 'setEagerLoadedElements';
-
/**
* @var ElementInterface[]|null All elements that the element was queried with.
*
@@ -205,19 +160,18 @@ public static function eagerLoadingMap(array $sourceElements, string $handle): a
}
// Fire a 'defineEagerLoadingMap' event
- if (Event::hasHandlers(static::class, Element::EVENT_DEFINE_EAGER_LOADING_MAP)) {
- $event = new DefineEagerLoadingMapEvent([
- 'sourceElements' => $sourceElements,
- 'handle' => $handle,
- ]);
- Event::trigger(static::class, Element::EVENT_DEFINE_EAGER_LOADING_MAP, $event);
- if ($event->elementType !== null) {
- return [
- 'elementType' => $event->elementType,
- 'map' => $event->map,
- 'criteria' => $event->criteria,
- ];
- }
+ event($event = new DefineEagerLoadingMap(
+ elementType: static::class,
+ sourceElements: $sourceElements,
+ handle: $handle,
+ ));
+
+ if ($event->targetElementType !== null) {
+ return [
+ 'elementType' => $event->targetElementType,
+ 'map' => $event->map,
+ 'criteria' => $event->criteria,
+ ];
}
// return null so eager-loading is ignored for this handle
@@ -651,16 +605,15 @@ public function setEagerLoadedElements(string $handle, array $elements, EagerLoa
break;
default:
// Fire a 'setEagerLoadedElements' event
- if ($this->hasEventHandlers(Element::EVENT_SET_EAGER_LOADED_ELEMENTS)) {
- $event = new SetEagerLoadedElementsEvent([
- 'handle' => $handle,
- 'elements' => $elements,
- 'plan' => $plan,
- ]);
- $this->trigger(Element::EVENT_SET_EAGER_LOADED_ELEMENTS, $event);
- if ($event->handled) {
- break;
- }
+ event($event = new SetEagerLoadedElements(
+ element: $this,
+ handle: $handle,
+ elements: $elements,
+ plan: $plan,
+ ));
+
+ if ($event->handled) {
+ break;
}
// No takers. Just store it in the internal array then.
diff --git a/src/Element/Concerns/Exportable.php b/src/Element/Concerns/Exportable.php
index eabb58c7933..06070b3afa6 100644
--- a/src/Element/Concerns/Exportable.php
+++ b/src/Element/Concerns/Exportable.php
@@ -6,8 +6,7 @@
use craft\elements\exporters\Expanded;
use craft\elements\exporters\Raw;
-use craft\events\RegisterElementExportersEvent;
-use yii\base\Event;
+use CraftCms\Cms\Element\Events\RegisterExporters;
/**
* Exportable provides element export functionality.
@@ -19,13 +18,6 @@
*/
trait Exportable
{
- /**
- * @event RegisterElementExportersEvent The event that is triggered when registering the available exporters for the element type.
- *
- * @since 3.4.0
- */
- public const EVENT_REGISTER_EXPORTERS = 'registerExporters';
-
/**
* Returns the available element exporters for a given source.
*
@@ -36,20 +28,13 @@ trait Exportable
*/
public static function exporters(string $source): array
{
- $exporters = static::defineExporters($source);
-
- // Fire a 'registerExporters' event
- if (Event::hasHandlers(static::class, self::EVENT_REGISTER_EXPORTERS)) {
- $event = new RegisterElementExportersEvent([
- 'source' => $source,
- 'exporters' => $exporters,
- ]);
- Event::trigger(static::class, self::EVENT_REGISTER_EXPORTERS, $event);
-
- return $event->exporters;
- }
+ event($event = new RegisterExporters(
+ elementType: static::class,
+ source: $source,
+ exporters: static::defineExporters($source),
+ ));
- return $exporters;
+ return $event->exporters;
}
/**
diff --git a/src/Element/Concerns/HasActions.php b/src/Element/Concerns/HasActions.php
index 1925d4978e4..a81f7e801e2 100644
--- a/src/Element/Concerns/HasActions.php
+++ b/src/Element/Concerns/HasActions.php
@@ -10,9 +10,8 @@
use craft\elements\actions\Edit;
use craft\elements\actions\SetStatus;
use craft\elements\actions\View as ViewAction;
-use craft\events\RegisterElementActionsEvent;
+use CraftCms\Cms\Element\Events\RegisterActions;
use Illuminate\Support\Collection;
-use yii\base\Event;
use function CraftCms\Cms\t;
@@ -26,11 +25,6 @@
*/
trait HasActions
{
- /**
- * @event RegisterElementActionsEvent The event that is triggered when registering the available bulk actions for the element type.
- */
- public const EVENT_REGISTER_ACTIONS = 'registerActions';
-
/**
* {@inheritdoc}
*/
@@ -86,20 +80,13 @@ public static function actions(string $source): array
$actions->push(Delete::class);
}
- $actions = $actions->all();
-
- // Fire a 'registerActions' event
- if (Event::hasHandlers(static::class, static::EVENT_REGISTER_ACTIONS)) {
- $event = new RegisterElementActionsEvent([
- 'source' => $source,
- 'actions' => $actions,
- ]);
- Event::trigger(static::class, static::EVENT_REGISTER_ACTIONS, $event);
-
- return $event->actions;
- }
+ event($event = new RegisterActions(
+ elementType: static::class,
+ source: $source,
+ actions: $actions->all(),
+ ));
- return $actions;
+ return $event->actions;
}
/**
diff --git a/src/Element/Concerns/HasControlPanelUI.php b/src/Element/Concerns/HasControlPanelUI.php
index a06a6ad08b7..7d73515b71a 100644
--- a/src/Element/Concerns/HasControlPanelUI.php
+++ b/src/Element/Concerns/HasControlPanelUI.php
@@ -7,15 +7,18 @@
use Craft;
use craft\base\NestedElementInterface;
use craft\controllers\ElementsController;
-use craft\events\DefineAltActionsEvent;
-use craft\events\DefineAttributeHtmlEvent;
-use craft\events\DefineHtmlEvent;
-use craft\events\DefineMenuItemsEvent;
-use craft\events\DefineMetadataEvent;
-use craft\events\RegisterElementHtmlAttributesEvent;
use craft\helpers\Cp;
use craft\helpers\ElementHelper;
use CraftCms\Cms\Element\ElementAttributeRenderer;
+use CraftCms\Cms\Element\Events\DefineActionMenuItems;
+use CraftCms\Cms\Element\Events\DefineAdditionalButtons;
+use CraftCms\Cms\Element\Events\DefineAltActions;
+use CraftCms\Cms\Element\Events\DefineAttributeHtml;
+use CraftCms\Cms\Element\Events\DefineInlineAttributeInputHtml;
+use CraftCms\Cms\Element\Events\DefineMetadata;
+use CraftCms\Cms\Element\Events\DefineMetaFieldsHtml;
+use CraftCms\Cms\Element\Events\DefineSidebarHtml;
+use CraftCms\Cms\Element\Events\RegisterHtmlAttributes;
use CraftCms\Cms\Http\Responses\CpScreenResponse;
use CraftCms\Cms\Shared\Enums\Color;
use CraftCms\Cms\Support\Arr;
@@ -36,81 +39,12 @@
* including edit URLs, sidebar HTML, metadata, action menus, and attribute rendering.
*
* @property string|null $ref The reference string to this element
- * @property array $htmlAttributes Any attributes that should be included in the element’s DOM representation in the control panel
+ * @property array $htmlAttributes Any attributes that should be included in the element's DOM representation in the control panel
*
* @internal
*/
trait HasControlPanelUI
{
- /**
- * @event DefineHtmlEvent The event that is triggered when defining additional buttons that should be shown at the top of the element's edit page.
- *
- * @see getAdditionalButtons()
- * @since 4.0.0
- */
- public const EVENT_DEFINE_ADDITIONAL_BUTTONS = 'defineAdditionalButtons';
-
- /**
- * @event DefineAltActionsEvent The event that is triggered when defining alternative form actions for the element.
- *
- * @see getAltActions()
- * @since 5.6.0
- */
- public const EVENT_DEFINE_ALT_ACTIONS = 'defineAltActions';
-
- /**
- * @event DefineMenuItemsEvent The event that is triggered when defining action menu items..
- *
- * @see getActionMenuItems()
- * @since 5.0.0
- */
- public const EVENT_DEFINE_ACTION_MENU_ITEMS = 'defineActionMenuItems';
-
- /**
- * @event DefineHtmlEvent The event that is triggered when defining the HTML for the editor sidebar.
- *
- * @see getSidebarHtml()
- * @since 3.7.0
- */
- public const EVENT_DEFINE_SIDEBAR_HTML = 'defineSidebarHtml';
-
- /**
- * @event DefineHtmlEvent The event that is triggered when defining the HTML for meta fields within the editor sidebar.
- *
- * @see metaFieldsHtml()
- * @since 3.7.0
- */
- public const EVENT_DEFINE_META_FIELDS_HTML = 'defineMetaFieldsHtml';
-
- /**
- * @event DefineMetadataEvent The event that is triggered when defining the element's metadata info.
- *
- * @see getMetadata()
- * @since 3.7.0
- */
- public const EVENT_DEFINE_METADATA = 'defineMetadata';
-
- /**
- * @event RegisterElementHtmlAttributesEvent The event that is triggered when registering the HTML attributes that should be included in the element's DOM representation in the control panel.
- */
- public const EVENT_REGISTER_HTML_ATTRIBUTES = 'registerHtmlAttributes';
-
- /**
- * @event DefineAttributeHtmlEvent The event that is triggered when defining an attribute's HTML for table and card views.
- *
- * @see getAttributeHtml()
- * @since 5.0.0
- */
- public const EVENT_DEFINE_ATTRIBUTE_HTML = 'defineAttributeHtml';
-
- /**
- * @event DefineAttributeHtmlEvent The event that is triggered when defining an attribute's inline input HTML.
- *
- * @see getInlineAttributeInputHtml()
- * @since 5.0.0
- */
- public const EVENT_DEFINE_INLINE_ATTRIBUTE_INPUT_HTML = 'defineInlineAttributeInputHtml';
-
/**
* @see getUiLabel()
* @see setUiLabel()
@@ -135,12 +69,7 @@ public function prepareEditScreen(Response|CpScreenResponse $response, string $c
*/
public function getAdditionalButtons(): string|Stringable
{
- if (! $this->hasEventHandlers(self::EVENT_DEFINE_ADDITIONAL_BUTTONS)) {
- return '';
- }
-
- $event = new DefineHtmlEvent;
- $this->trigger(self::EVENT_DEFINE_ADDITIONAL_BUTTONS, $event);
+ event($event = new DefineAdditionalButtons($this));
return $event->html;
}
@@ -206,14 +135,7 @@ public function getAltActions(): array
}
}
- if (! $this->hasEventHandlers(self::EVENT_DEFINE_ALT_ACTIONS)) {
- return $altActions;
- }
-
- $event = new DefineAltActionsEvent([
- 'altActions' => $altActions,
- ]);
- $this->trigger(self::EVENT_DEFINE_ALT_ACTIONS, $event);
+ event($event = new DefineAltActions($this, $altActions));
return $event->altActions;
}
@@ -228,12 +150,7 @@ public function getActionMenuItems(): array
...array_map(fn (array $item) => $item + ['destructive' => true], $this->destructiveActionMenuItems()),
];
- if (! $this->hasEventHandlers(self::EVENT_DEFINE_ACTION_MENU_ITEMS)) {
- return $items;
- }
-
- $event = new DefineMenuItemsEvent(['items' => $items]);
- $this->trigger(self::EVENT_DEFINE_ACTION_MENU_ITEMS, $event);
+ event($event = new DefineActionMenuItems($this, $items));
return $event->items;
}
@@ -510,15 +427,9 @@ public function getHtmlAttributes(string $context): array
],
]);
- // Fire a 'registerHtmlAttributes' event
- if ($this->hasEventHandlers(self::EVENT_REGISTER_HTML_ATTRIBUTES)) {
- $event = new RegisterElementHtmlAttributesEvent(['htmlAttributes' => $htmlAttributes]);
- $this->trigger(self::EVENT_REGISTER_HTML_ATTRIBUTES, $event);
+ event($event = new RegisterHtmlAttributes($this, $context, $htmlAttributes));
- return $event->htmlAttributes;
- }
-
- return $htmlAttributes;
+ return $event->htmlAttributes;
}
/**
@@ -538,18 +449,9 @@ protected function htmlAttributes(string $context): array
*/
public function getAttributeHtml(string $attribute): string|Stringable
{
- // Fire a 'defineAttributeHtml' event
- if ($this->hasEventHandlers(self::EVENT_DEFINE_ATTRIBUTE_HTML)) {
- $event = new DefineAttributeHtmlEvent([
- 'attribute' => $attribute,
- ]);
- $this->trigger(self::EVENT_DEFINE_ATTRIBUTE_HTML, $event);
- if (isset($event->html)) {
- return $event->html;
- }
- }
+ event($event = new DefineAttributeHtml($this, $attribute));
- return $this->attributeHtml($attribute);
+ return $event->html ?? $this->attributeHtml($attribute);
}
/**
@@ -557,16 +459,9 @@ public function getAttributeHtml(string $attribute): string|Stringable
*/
public function getInlineAttributeInputHtml(string $attribute): string|Stringable
{
- // Fire a 'defineInlineAttributeInputHtml' event
- if ($this->hasEventHandlers(self::EVENT_DEFINE_INLINE_ATTRIBUTE_INPUT_HTML)) {
- $event = new DefineAttributeHtmlEvent(['attribute' => $attribute]);
- $this->trigger(self::EVENT_DEFINE_INLINE_ATTRIBUTE_INPUT_HTML, $event);
- if (isset($event->html)) {
- return $event->html;
- }
- }
+ event($event = new DefineInlineAttributeInputHtml($this, $attribute));
- return $this->inlineAttributeInputHtml($attribute);
+ return $event->html ?? $this->inlineAttributeInputHtml($attribute);
}
/**
@@ -641,12 +536,7 @@ public function getSidebarHtml(bool $static): string|Stringable
$html = implode("\n", $components);
- if (! $this->hasEventHandlers(self::EVENT_DEFINE_SIDEBAR_HTML)) {
- return $html;
- }
-
- $event = new DefineHtmlEvent(['html' => $html]);
- $this->trigger(self::EVENT_DEFINE_SIDEBAR_HTML, $event);
+ event($event = new DefineSidebarHtml($this, $static, $html));
return $event->html;
}
@@ -660,12 +550,7 @@ public function getSidebarHtml(bool $static): string|Stringable
*/
protected function metaFieldsHtml(bool $static): string|Stringable
{
- if (! $this->hasEventHandlers(self::EVENT_DEFINE_META_FIELDS_HTML)) {
- return '';
- }
-
- $event = new DefineHtmlEvent(['static' => $static]);
- $this->trigger(self::EVENT_DEFINE_META_FIELDS_HTML, $event);
+ event($event = new DefineMetaFieldsHtml($this, $static));
return $event->html;
}
@@ -808,12 +693,8 @@ public function getMetadata(): array
{
$metadata = $this->metadata();
- // Fire a 'defineMetadata' event
- if ($this->hasEventHandlers(self::EVENT_DEFINE_METADATA)) {
- $event = new DefineMetadataEvent(['metadata' => $metadata]);
- $this->trigger(self::EVENT_DEFINE_METADATA, $event);
- $metadata = $event->metadata;
- }
+ event($event = new DefineMetadata($this, $metadata));
+ $metadata = $event->metadata;
$formatter = I18N::getFormatter();
diff --git a/src/Element/Concerns/HasCustomFields.php b/src/Element/Concerns/HasCustomFields.php
index 68be33ff8b0..8ea7a8b7985 100644
--- a/src/Element/Concerns/HasCustomFields.php
+++ b/src/Element/Concerns/HasCustomFields.php
@@ -23,9 +23,9 @@
* This trait contains all logic related to getting, setting, normalizing,
* and tracking changes to custom field values on elements.
*
- * @property array $serializedFieldValues Array of the element’s serialized custom field values, indexed by their handles
- * @property array $fieldValues The element’s normalized custom field values, indexed by their handles
- * @property string $fieldContext The field context this element’s content uses
+ * @property array $serializedFieldValues Array of the element's serialized custom field values, indexed by their handles
+ * @property array $fieldValues The element's normalized custom field values, indexed by their handles
+ * @property string $fieldContext The field context this element's content uses
* @property FieldLayout|null $fieldLayout The field layout used by this element
* @property array $fieldParamNamespace The namespace used by custom field params on the request
*
@@ -34,16 +34,7 @@
trait HasCustomFields
{
/**
- * @event RegisterElementFieldLayoutsEvent The event that is triggered when registering all of the field layouts
- * associated with elements from a given source.
- *
- * @see fieldLayouts()
- * @since 3.5.0
- */
- public const EVENT_REGISTER_FIELD_LAYOUTS = 'registerFieldLayouts';
-
- /**
- * @var int|null The element’s field layout ID
+ * @var int|null The element's field layout ID
*/
public ?int $fieldLayoutId = null;
diff --git a/src/Element/Concerns/HasLifecycleHooks.php b/src/Element/Concerns/HasLifecycleHooks.php
index 29beb4b6c94..6dd3920ec0b 100644
--- a/src/Element/Concerns/HasLifecycleHooks.php
+++ b/src/Element/Concerns/HasLifecycleHooks.php
@@ -4,9 +4,14 @@
namespace CraftCms\Cms\Element\Concerns;
-use craft\events\ModelEvent;
-use CraftCms\Cms\Element\Element;
use CraftCms\Cms\Element\ElementRelations;
+use CraftCms\Cms\Element\Events\AfterDelete;
+use CraftCms\Cms\Element\Events\AfterPropagate;
+use CraftCms\Cms\Element\Events\AfterRestore;
+use CraftCms\Cms\Element\Events\AfterSave;
+use CraftCms\Cms\Element\Events\BeforeDelete;
+use CraftCms\Cms\Element\Events\BeforeRestore;
+use CraftCms\Cms\Element\Events\BeforeSave;
/**
* HasLifecycleHooks provides the lifecycle hooks for the element.
@@ -17,119 +22,6 @@
*/
trait HasLifecycleHooks
{
- /**
- * @event ModelEvent The event that is triggered before the element is saved.
- *
- * You may set [[\yii\base\ModelEvent::$isValid]] to `false` to prevent the element from getting saved.
- *
- * If you want to ignore events for drafts or revisions, call [[\craft\helpers\ElementHelper::isDraftOrRevision()]]
- * from your event handler:
- *
- * ```php
- * use CraftCms\Cms\Element\Element;
- * use CraftCms\Cms\Entry\Elements\Entry;
- * use craft\events\ModelEvent;
- * use craft\helpers\ElementHelper;
- * use yii\base\Event;
- *
- * Event::on(Entry::class, Element::EVENT_BEFORE_SAVE, function(ModelEvent $e) {
- * // @var Entry $entry
- * $entry = $e->sender;
- *
- * if (ElementHelper::isDraftOrRevision($entry)) {
- * return;
- * }
- *
- * // ...
- * });
- * ```
- */
- public const EVENT_BEFORE_SAVE = 'beforeSave';
-
- /**
- * @event ModelEvent The event that is triggered after the element is saved.
- *
- * If you want to ignore events for drafts or revisions, call [[\craft\helpers\ElementHelper::isDraftOrRevision()]]
- * from your event handler:
- *
- * ```php
- * use CraftCms\Cms\Element\Element;
- * use CraftCms\Cms\Entry\Elements\Entry;
- * use craft\events\ModelEvent;
- * use craft\helpers\ElementHelper;
- * use yii\base\Event;
- *
- * Event::on(Entry::class, Element::EVENT_AFTER_SAVE, function(ModelEvent $e) {
- * // @var Entry $entry
- * $entry = $e->sender;
- *
- * if (ElementHelper::isDraftOrRevision($entry)) {
- * return;
- * }
- *
- * // ...
- * });
- * ```
- */
- public const EVENT_AFTER_SAVE = 'afterSave';
-
- /**
- * @event ModelEvent The event that is triggered after the element is fully saved and propagated to other sites.
- *
- * If you want to ignore events for drafts or revisions, call [[\craft\helpers\ElementHelper::isDraftOrRevision()]]
- * from your event handler:
- *
- * ```php
- * use CraftCms\Cms\Element\Element;
- * use CraftCms\Cms\Entry\Elements\Entry;
- * use craft\events\ModelEvent;
- * use craft\helpers\ElementHelper;
- * use yii\base\Event;
- *
- * Event::on(Entry::class, Element::EVENT_AFTER_PROPAGATE, function(ModelEvent $e) {
- * // @var Entry $entry
- * $entry = $e->sender;
- *
- * if (ElementHelper::isDraftOrRevision($entry) {
- * return;
- * }
- *
- * // ...
- * });
- * ```
- *
- * @since 3.2.0
- */
- public const EVENT_AFTER_PROPAGATE = 'afterPropagate';
-
- /**
- * @event ModelEvent The event that is triggered before the element is deleted.
- *
- * You may set [[\yii\base\ModelEvent::$isValid]] to `false` to prevent the element from getting deleted.
- */
- public const EVENT_BEFORE_DELETE = 'beforeDelete';
-
- /**
- * @event \yii\base\Event The event that is triggered after the element is deleted.
- */
- public const EVENT_AFTER_DELETE = 'afterDelete';
-
- /**
- * @event ModelEvent The event that is triggered before the element is restored.
- *
- * You may set [[\yii\base\ModelEvent::$isValid]] to `false` to prevent the element from getting restored.
- *
- * @since 3.1.0
- */
- public const EVENT_BEFORE_RESTORE = 'beforeRestore';
-
- /**
- * @event \yii\base\Event The event that is triggered after the element is restored.
- *
- * @since 3.1.0
- */
- public const EVENT_AFTER_RESTORE = 'afterRestore';
-
/**
* {@inheritdoc}
*
@@ -142,15 +34,9 @@ public function beforeSave(bool $isNew): bool
return false;
}
- // Fire a 'beforeSave' event
- if ($this->hasEventHandlers(Element::EVENT_BEFORE_SAVE)) {
- $event = new ModelEvent(['isNew' => $isNew]);
- $this->trigger(Element::EVENT_BEFORE_SAVE, $event);
+ event($event = new BeforeSave($this, $isNew));
- return $event->isValid;
- }
-
- return true;
+ return $event->isValid;
}
/**
@@ -160,7 +46,7 @@ public function beforeSave(bool $isNew): bool
*/
public function afterSave(bool $isNew): void
{
- // Update the element’s relation data
+ // Update the element's relation data
app(ElementRelations::class)->updateRelations($this, $isNew);
// Tell the fields about it
@@ -168,12 +54,7 @@ public function afterSave(bool $isNew): void
$field->afterElementSave($this, $isNew);
}
- // Fire an 'afterSave' event
- if ($this->hasEventHandlers(Element::EVENT_AFTER_SAVE)) {
- $this->trigger(Element::EVENT_AFTER_SAVE, new ModelEvent([
- 'isNew' => $isNew,
- ]));
- }
+ event(new AfterSave($this, $isNew));
}
/**
@@ -188,12 +69,7 @@ public function afterPropagate(bool $isNew): void
$field->afterElementPropagate($this, $isNew);
}
- // Fire an 'afterPropagate' event
- if ($this->hasEventHandlers(Element::EVENT_AFTER_PROPAGATE)) {
- $this->trigger(Element::EVENT_AFTER_PROPAGATE, new ModelEvent([
- 'isNew' => $isNew,
- ]));
- }
+ event(new AfterPropagate($this, $isNew));
$this->handleDraftSave();
}
@@ -210,15 +86,9 @@ public function beforeDelete(): bool
return false;
}
- // Fire a 'beforeDelete' event
- if ($this->hasEventHandlers(Element::EVENT_BEFORE_DELETE)) {
- $event = new ModelEvent;
- $this->trigger(Element::EVENT_BEFORE_DELETE, $event);
+ event($event = new BeforeDelete($this));
- return $event->isValid;
- }
-
- return true;
+ return $event->isValid;
}
/**
@@ -233,10 +103,7 @@ public function afterDelete(): void
$field->afterElementDelete($this);
}
- // Fire an 'afterDelete' event
- if ($this->hasEventHandlers(Element::EVENT_AFTER_DELETE)) {
- $this->trigger(Element::EVENT_AFTER_DELETE);
- }
+ event(new AfterDelete($this));
$this->handleRevisionDelete();
$this->handleDraftDelete();
@@ -280,15 +147,9 @@ public function beforeRestore(): bool
return false;
}
- // Fire a 'beforeRestore' event
- if ($this->hasEventHandlers(Element::EVENT_BEFORE_RESTORE)) {
- $event = new ModelEvent;
- $this->trigger(Element::EVENT_BEFORE_RESTORE, $event);
+ event($event = new BeforeRestore($this));
- return $event->isValid;
- }
-
- return true;
+ return $event->isValid;
}
/**
@@ -303,9 +164,6 @@ public function afterRestore(): void
$field->afterElementRestore($this);
}
- // Fire an 'afterRestore' event
- if ($this->hasEventHandlers(Element::EVENT_AFTER_RESTORE)) {
- $this->trigger(Element::EVENT_AFTER_RESTORE);
- }
+ event(new AfterRestore($this));
}
}
diff --git a/src/Element/Concerns/HasPreviewTargets.php b/src/Element/Concerns/HasPreviewTargets.php
index 5719308eb64..f5702d20e92 100644
--- a/src/Element/Concerns/HasPreviewTargets.php
+++ b/src/Element/Concerns/HasPreviewTargets.php
@@ -5,8 +5,8 @@
namespace CraftCms\Cms\Element\Concerns;
use Craft;
-use craft\events\RegisterPreviewTargetsEvent;
use craft\helpers\UrlHelper;
+use CraftCms\Cms\Element\Events\RegisterPreviewTargets;
use CraftCms\Cms\Support\Env;
use Illuminate\Support\Collection;
@@ -22,13 +22,6 @@
*/
trait HasPreviewTargets
{
- /**
- * @event RegisterPreviewTargetsEvent The event that is triggered when registering the element's preview targets.
- *
- * @since 3.2.0
- */
- public const EVENT_REGISTER_PREVIEW_TARGETS = 'registerPreviewTargets';
-
/**
* @var bool Whether the element is currently being previewed.
*
@@ -43,17 +36,10 @@ trait HasPreviewTargets
*/
public function getPreviewTargets(): array
{
- $previewTargets = $this->previewTargets();
-
- // Fire a 'registerPreviewTargets' event
- if ($this->hasEventHandlers(self::EVENT_REGISTER_PREVIEW_TARGETS)) {
- $event = new RegisterPreviewTargetsEvent(['previewTargets' => $previewTargets]);
- $this->trigger(self::EVENT_REGISTER_PREVIEW_TARGETS, $event);
- $previewTargets = $event->previewTargets;
- }
+ event($event = new RegisterPreviewTargets($this, $this->previewTargets()));
// Normalize the targets
- return new Collection($previewTargets)
+ return new Collection($event->previewTargets)
->map(function (array $previewTarget) {
if (isset($previewTarget['urlFormat'])) {
$url = trim(Craft::$app->getView()->renderObjectTemplate(Env::parse($previewTarget['urlFormat']), $this));
diff --git a/src/Element/Concerns/HasRoutesAndUrls.php b/src/Element/Concerns/HasRoutesAndUrls.php
index b1cf6fecc63..d9c964b92bf 100644
--- a/src/Element/Concerns/HasRoutesAndUrls.php
+++ b/src/Element/Concerns/HasRoutesAndUrls.php
@@ -5,13 +5,14 @@
namespace CraftCms\Cms\Element\Concerns;
use craft\base\NestedElementInterface;
-use craft\events\DefineUrlEvent;
-use craft\events\SetElementRouteEvent;
use craft\helpers\ElementHelper;
use craft\helpers\Template;
use craft\helpers\UrlHelper;
use craft\web\twig\AllowedInSandbox;
use CraftCms\Cms\Element\Element;
+use CraftCms\Cms\Element\Events\BeforeDefineUrl;
+use CraftCms\Cms\Element\Events\DefineUrl;
+use CraftCms\Cms\Element\Events\SetRoute;
use CraftCms\Cms\Support\Html;
use Twig\Markup;
@@ -33,99 +34,7 @@
trait HasRoutesAndUrls
{
/**
- * @event SetElementRouteEvent The event that is triggered when defining the route that should be used when this element’s URL is requested.
- *
- * Set [[Event::$handled]] to `true` to explicitly tell the element that a route has been set (even if you’re
- * setting it to `null`).
- *
- * ```php
- * Event::on(craft\elements\Entry::class, craft\base\Element::EVENT_SET_ROUTE, function(craft\events\SetElementRouteEvent $e) {
- * // @var craft\elements\Entry $entry
- * $entry = $e->sender;
- *
- * if ($entry->uri === 'pricing') {
- * $e->route = 'module/pricing/index';
- *
- * // Explicitly tell the element that a route has been set,
- * // and prevent other event handlers from running, and tell
- * $e->handled = true;
- * }
- * });
- * ```
- */
- public const string EVENT_SET_ROUTE = 'setRoute';
-
- /**
- * @event DefineUrlEvent The event that is triggered before defining the element’s URL.
- *
- * It can be used to provide a custom URL, completely bypassing the default URL generation.
- *
- * ```php
- * use CraftCms\Cms\Element\Element;
- * use CraftCms\Cms\Entry\Elements\Entry;
- * use craft\events\DefineUrlEvent;
- * use craft\helpers\UrlHelper;
- * use yii\base\Event;
- *
- * Event::on(
- * Entry::class,
- * Element::EVENT_BEFORE_DEFINE_URL,
- * function(DefineUrlEvent $e
- * ) {
- * // @var Entry $entry
- * $entry = $e->sender;
- *
- * $event->url = '...';
- * });
- * ```
- *
- * To prevent the element from getting a URL, ensure `$event->url` is set to `null`,
- * and set `$event->handled` to `true`.
- *
- * Note that [[EVENT_DEFINE_URL]] will still be called regardless of what happens with this event.
- *
- * @see getUrl()
- * @since 4.4.6
- */
- public const string EVENT_BEFORE_DEFINE_URL = 'beforeDefineUrl';
-
- /**
- * @event DefineUrlEvent The event that is triggered when defining the element’s URL.
- *
- * ```php
- * use CraftCms\Cms\Element\Element;
- * use CraftCms\Cms\Entry\Elements\Entry;
- * use craft\events\DefineUrlEvent;
- * use craft\helpers\UrlHelper;
- * use yii\base\Event;
- *
- * Event::on(
- * Entry::class,
- * Element::EVENT_DEFINE_URL,
- * function(DefineUrlEvent $e
- * ) {
- * // @var Entry $entry
- * $entry = $e->sender;
- *
- * // Add a custom query string param to the URL
- * if ($event->value !== null) {
- * $event->url = UrlHelper::urlWithParams($event->url, [
- * 'foo' => 'bar',
- * ]);
- * }
- * });
- * ```
- *
- * To prevent the element from getting a URL, ensure `$event->url` is set to `null`,
- * and set `$event->handled` to `true`.
- *
- * @see getUrl()
- * @since 4.3.0
- */
- public const string EVENT_DEFINE_URL = 'defineUrl';
-
- /**
- * @var string|null The element’s URI
+ * @var string|null The element's URI
*/
#[AllowedInSandbox]
public ?string $uri = null;
@@ -152,12 +61,9 @@ public function getUriFormat(): ?string
public function getRoute(): mixed
{
// Fire a 'setRoute' event
- if ($this->hasEventHandlers(self::EVENT_SET_ROUTE)) {
- $event = new SetElementRouteEvent;
- $this->trigger(self::EVENT_SET_ROUTE, $event);
- if ($event->handled || $event->route !== null) {
- return $event->route ?: null;
- }
+ event($event = new SetRoute($this));
+ if ($event->handled || $event->route !== null) {
+ return $event->route ?: null;
}
if ($this instanceof NestedElementInterface) {
@@ -195,31 +101,22 @@ public function getIsHomepage(): bool
*/
public function getUrl(): ?string
{
- $url = null;
- $handled = false;
-
// Fire a 'beforeDefineUrl' event
- if ($this->hasEventHandlers(self::EVENT_BEFORE_DEFINE_URL)) {
- $event = new DefineUrlEvent;
- $this->trigger(self::EVENT_BEFORE_DEFINE_URL, $event);
- $url = $event->url;
- $handled = $event->handled;
- }
+ event($beforeEvent = new BeforeDefineUrl($this));
+ $url = $beforeEvent->url;
+ $handled = $beforeEvent->handled;
- // If DefineAssetUrlEvent::$url is set to null, only respect that if $handled is true
+ // If BeforeDefineUrl::$url is set to null, only respect that if $handled is true
if ($url === null && ! $handled && isset($this->uri)) {
$path = $this->getIsHomepage() ? '' : $this->uri;
$url = UrlHelper::siteUrl($path, null, null, $this->siteId);
}
// Fire a 'defineUrl' event
- if ($this->hasEventHandlers(self::EVENT_DEFINE_URL)) {
- $event = new DefineUrlEvent(['url' => $url]);
- $this->trigger(self::EVENT_DEFINE_URL, $event);
- // If DefineAssetUrlEvent::$url is set to null, only respect that if $handled is true
- if ($event->url !== null || $event->handled) {
- $url = $event->url;
- }
+ event($event = new DefineUrl($this, $url));
+ // If DefineUrl::$url is set to null, only respect that if $handled is true
+ if ($event->url !== null || $event->handled) {
+ $url = $event->url;
}
if ($url === null) {
diff --git a/src/Element/Concerns/HasSources.php b/src/Element/Concerns/HasSources.php
index bdbb95a5a5b..a6eb8e2c51d 100644
--- a/src/Element/Concerns/HasSources.php
+++ b/src/Element/Concerns/HasSources.php
@@ -4,11 +4,10 @@
namespace CraftCms\Cms\Element\Concerns;
-use craft\events\RegisterElementFieldLayoutsEvent;
-use craft\events\RegisterElementSourcesEvent;
use craft\models\FieldLayout;
+use CraftCms\Cms\Element\Events\RegisterFieldLayouts;
+use CraftCms\Cms\Element\Events\RegisterSources;
use CraftCms\Cms\Support\Facades\Fields;
-use yii\base\Event;
/**
* HasSources provides element source management functionality.
@@ -20,11 +19,6 @@
*/
trait HasSources
{
- /**
- * @event RegisterElementSourcesEvent The event that is triggered when registering the available sources for the element type.
- */
- public const EVENT_REGISTER_SOURCES = 'registerSources';
-
/**
* @see sources()
*/
@@ -47,15 +41,8 @@ public static function sources(string $context): array
// Memoize the results immediately, in case sources() gets called again via the event
self::$sources[static::class][$context] = static::defineSources($context);
- // Fire a 'registerSources' event
- if (Event::hasHandlers(static::class, self::EVENT_REGISTER_SOURCES)) {
- $event = new RegisterElementSourcesEvent([
- 'context' => $context,
- 'sources' => self::$sources[static::class][$context],
- ]);
- Event::trigger(static::class, self::EVENT_REGISTER_SOURCES, $event);
- self::$sources[static::class][$context] = $event->sources;
- }
+ event($event = new RegisterSources(static::class, $context, self::$sources[static::class][$context]));
+ self::$sources[static::class][$context] = $event->sources;
}
return self::$sources[static::class][$context];
@@ -105,15 +92,7 @@ public static function fieldLayouts(?string $source): array
{
$fieldLayouts = static::defineFieldLayouts($source);
- if (! Event::hasHandlers(static::class, self::EVENT_REGISTER_FIELD_LAYOUTS)) {
- return $fieldLayouts;
- }
-
- $event = new RegisterElementFieldLayoutsEvent([
- 'source' => $source,
- 'fieldLayouts' => $fieldLayouts,
- ]);
- Event::trigger(static::class, self::EVENT_REGISTER_FIELD_LAYOUTS, $event);
+ event($event = new RegisterFieldLayouts(static::class, $source, $fieldLayouts));
return $event->fieldLayouts;
}
diff --git a/src/Element/Concerns/Renderable.php b/src/Element/Concerns/Renderable.php
index 5c79cf0e56e..2cc777c7f67 100644
--- a/src/Element/Concerns/Renderable.php
+++ b/src/Element/Concerns/Renderable.php
@@ -5,9 +5,9 @@
namespace CraftCms\Cms\Element\Concerns;
use Craft;
-use craft\events\RenderElementEvent;
use craft\web\View;
use CraftCms\Cms\Cms;
+use CraftCms\Cms\Element\Events\Render;
use CraftCms\Cms\Support\Arr;
use CraftCms\Cms\Support\Html;
use Twig\Markup;
@@ -22,27 +22,6 @@
*/
trait Renderable
{
- /**
- * @event RenderElementEvent The event that is triggered before an element is rendered.
- *
- * @since 5.7.5
- *
- * ```php
- * use CraftCms\Cms\Element\Element;
- * use craft\events\RenderElementEvent;
- * use yii\base\Event;
- *
- * Event::on(
- * Element::class,
- * Element::EVENT_RENDER,
- * function(RenderElementEvent $event) {
- * $event->output = '…';
- * }
- * );
- * ```
- */
- public const EVENT_RENDER = 'render';
-
/**
* {@inheritdoc}
*/
@@ -54,22 +33,19 @@ public function render(array $variables = []): Markup
$variables[$refHandle] = $this;
}
- if ($this->hasEventHandlers(self::EVENT_RENDER)) {
- $event = new RenderElementEvent([
- 'templates' => $templates,
- 'variables' => $variables,
- ]);
-
- $this->trigger(self::EVENT_RENDER, $event);
+ event($event = new Render(
+ element: $this,
+ templates: $templates,
+ variables: $variables,
+ ));
- if (isset($event->output)) {
- return new Markup($event->output, 'UTF-8');
- }
-
- $templates = $event->templates;
- $variables = $event->variables;
+ if ($event->output !== null) {
+ return new Markup($event->output, 'UTF-8');
}
+ $templates = $event->templates;
+ $variables = $event->variables;
+
if (! empty($templates)) {
$view = Craft::$app->getView();
foreach (Arr::sort($templates, 'priority') as $template) {
diff --git a/src/Element/Concerns/Searchable.php b/src/Element/Concerns/Searchable.php
index ccc6980d970..4fe5a80399e 100644
--- a/src/Element/Concerns/Searchable.php
+++ b/src/Element/Concerns/Searchable.php
@@ -4,7 +4,7 @@
namespace CraftCms\Cms\Element\Concerns;
-use craft\events\DefineAttributeKeywordsEvent;
+use CraftCms\Cms\Element\Events\DefineKeywords;
use CraftCms\Cms\Support\Str;
/**
@@ -20,45 +20,12 @@
trait Searchable
{
/**
- * @event DefineAttributeKeywordsEvent The event that is triggered when defining the search keywords for an
- * element attribute.
- *
- * Note that you _must_ set [[Event::$handled]] to `true` if you want the element to accept your custom
- * [[DefineAttributeKeywordsEvent::$keywords|$keywords]] value.
- *
- * ```php
- * Event::on(
- * craft\elements\Entry::class,
- * craft\base\Element::EVENT_DEFINE_KEYWORDS,
- * function(craft\events\DefineAttributeKeywordsEvent $e
- * ) {
- * // @var craft\elements\Entry $entry
- * $entry = $e->sender;
- *
- * // Prevent entry titles in the Parts section from getting search keywords
- * if ($entry->section->handle === 'parts' && $e->attribute === 'title') {
- * $e->keywords = '';
- * $e->handled = true;
- * }
- * });
- * ```
- *
- * @since 3.5.0
- */
- public const EVENT_DEFINE_KEYWORDS = 'defineKeywords';
-
- /**
- * @event RegisterElementSearchableAttributesEvent The event that is triggered when registering the searchable attributes for the element type.
- */
- public const EVENT_REGISTER_SEARCHABLE_ATTRIBUTES = 'registerSearchableAttributes';
-
- /**
- * @var int|null The element’s search score, if the [[\craft\elements\db\ElementQuery::search]] parameter was used when querying for the element
+ * @var int|null The element's search score, if the [[\craft\elements\db\ElementQuery::search]] parameter was used when querying for the element
*/
public ?int $searchScore = null;
/**
- * @var bool Whether the element’s search keywords should be indexed immediately.
+ * @var bool Whether the element's search keywords should be indexed immediately.
*
* If `null`, the search index will only be updated immediately for console requests.
*
@@ -71,13 +38,13 @@ trait Searchable
*/
public function getSearchKeywords(string $attribute): string
{
- if ($this->hasEventHandlers(self::EVENT_DEFINE_KEYWORDS)) {
- $event = new DefineAttributeKeywordsEvent(['attribute' => $attribute]);
- $this->trigger(self::EVENT_DEFINE_KEYWORDS, $event);
+ event($event = new DefineKeywords(
+ element: $this,
+ attribute: $attribute,
+ ));
- if ($event->handled) {
- return $event->keywords ?? '';
- }
+ if ($event->handled) {
+ return $event->keywords;
}
return $this->searchKeywords($attribute);
diff --git a/src/Element/Concerns/Structurable.php b/src/Element/Concerns/Structurable.php
index 8bb196636f6..120559e8fea 100644
--- a/src/Element/Concerns/Structurable.php
+++ b/src/Element/Concerns/Structurable.php
@@ -6,9 +6,10 @@
use Craft;
use craft\base\ElementInterface;
-use craft\events\ElementStructureEvent;
use CraftCms\Cms\Element\Element;
use CraftCms\Cms\Element\ElementCollection;
+use CraftCms\Cms\Element\Events\AfterMoveInStructure;
+use CraftCms\Cms\Element\Events\BeforeMoveInStructure;
use CraftCms\Cms\Element\Queries\Contracts\ElementQueryInterface;
use CraftCms\Cms\Element\Queries\ElementQuery;
@@ -35,18 +36,6 @@
*/
trait Structurable
{
- /**
- * @event ElementStructureEvent The event that is triggered before the element is moved in a structure.
- *
- * You may set [[\yii\base\ModelEvent::$isValid]] to `false` to prevent the element from getting moved.
- */
- public const string EVENT_BEFORE_MOVE_IN_STRUCTURE = 'beforeMoveInStructure';
-
- /**
- * @event ElementStructureEvent The event that is triggered after the element is moved in a structure.
- */
- public const string EVENT_AFTER_MOVE_IN_STRUCTURE = 'afterMoveInStructure';
-
public ?int $structureId = null;
public ?int $root = null;
@@ -372,14 +361,9 @@ public function isNextSiblingOf(ElementInterface $element): bool
public function beforeMoveInStructure(int $structureId): bool
{
// Fire a 'beforeMoveInStructure' event
- if ($this->hasEventHandlers(self::EVENT_BEFORE_MOVE_IN_STRUCTURE)) {
- $event = new ElementStructureEvent(['structureId' => $structureId]);
- $this->trigger(self::EVENT_BEFORE_MOVE_IN_STRUCTURE, $event);
-
- return $event->isValid;
- }
+ event($event = new BeforeMoveInStructure($this, $structureId));
- return true;
+ return $event->isValid;
}
/**
@@ -388,11 +372,7 @@ public function beforeMoveInStructure(int $structureId): bool
public function afterMoveInStructure(int $structureId): void
{
// Fire an 'afterMoveInStructure' event
- if ($this->hasEventHandlers(self::EVENT_AFTER_MOVE_IN_STRUCTURE)) {
- $this->trigger(self::EVENT_AFTER_MOVE_IN_STRUCTURE, new ElementStructureEvent([
- 'structureId' => $structureId,
- ]));
- }
+ event(new AfterMoveInStructure($this, $structureId));
// Invalidate caches for this element
Craft::$app->getElements()->invalidateCachesForElement($this);
diff --git a/src/Element/Drafts.php b/src/Element/Drafts.php
index fd100e86216..2779b6bdc7e 100644
--- a/src/Element/Drafts.php
+++ b/src/Element/Drafts.php
@@ -6,11 +6,10 @@
use Craft;
use craft\base\ElementInterface;
-use craft\behaviors\EventBehavior;
-use craft\events\ModelEvent;
use craft\helpers\ElementHelper;
use CraftCms\Cms\Cms;
use CraftCms\Cms\Database\Table;
+use CraftCms\Cms\Element\Events\AfterPropagate;
use CraftCms\Cms\Element\Events\ApplyingDraft;
use CraftCms\Cms\Element\Events\CreatingDraft;
use CraftCms\Cms\Element\Events\DraftApplied;
@@ -19,9 +18,11 @@
use CraftCms\Cms\Support\Arr;
use CraftCms\Cms\Support\Facades\Structures;
use Illuminate\Container\Attributes\Singleton;
+use Illuminate\Database\Query\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;
use Throwable;
use Tpetry\QueryExpressions\Language\Alias;
@@ -121,21 +122,28 @@ public function createDraft(
$newAttributes['trackDraftChanges'] = $canonical::trackChanges();
$newAttributes['markDraftAsSaved'] = $markAsSaved;
- /** @TODO: Remove behavior */
- $newAttributes['behaviors']['duplicateOwnershipAfterPropagate'] = new EventBehavior([
- Element::EVENT_AFTER_PROPAGATE => function (ModelEvent $event) use ($canonical) {
- /** @var ElementInterface $draft */
- $draft = $event->sender;
-
- // Duplicate nested element ownership
- DB::table(Table::ELEMENTS_OWNERS)
- ->insertUsing(['elementId', 'ownerId', 'sortOrder'],
- DB::table(Table::ELEMENTS_OWNERS, 'o')
- ->select('o.elementId', DB::raw($draft->id), 'o.sortOrder')
- ->where('o.ownerId', $canonical->id)
- );
- },
- ], true);
+ Event::listen(function (AfterPropagate $event) use ($draftId, $canonical) {
+ $draft = $event->element;
+
+ // Make sure we're dealing with the same element
+ if ($draft->getCanonicalId() !== $canonical->id || $draft->draftId !== $draftId) {
+ return;
+ }
+
+ // Duplicate nested element ownership
+ DB::table(Table::ELEMENTS_OWNERS)->insertUsing(
+ columns: ['elementId', 'ownerId', 'sortOrder'],
+ query: DB::table(Table::ELEMENTS_OWNERS, 'o')
+ ->select('o.elementId', DB::raw($draft->id), 'o.sortOrder')
+ ->where('o.ownerId', $canonical->id)
+ ->whereNotExists(function (Builder $q) use ($draft) {
+ $q->selectRaw('1')
+ ->from(Table::ELEMENTS_OWNERS)
+ ->whereColumn('elementId', 'o.elementId')
+ ->where('ownerId', $draft->id);
+ }),
+ );
+ });
$draft = Craft::$app->getElements()->duplicateElement($canonical, $newAttributes);
diff --git a/src/Element/Element.php b/src/Element/Element.php
index df036cf73ea..5712c128f57 100644
--- a/src/Element/Element.php
+++ b/src/Element/Element.php
@@ -19,7 +19,6 @@
use CraftCms\Cms\Validation\Attributes\Ruleset;
use CraftCms\Cms\Validation\Concerns\ValidatesWithRuleset;
use DateTime;
-use Deprecated;
use Illuminate\Support\Facades\Validator as ValidatorFacade;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Validation\Validator as LaravelValidator;
@@ -27,7 +26,6 @@
use Throwable;
use Traversable;
use yii\base\ArrayableTrait;
-use yii\base\Event;
use yii\base\InvalidCallException;
use yii\base\UnknownPropertyException;
@@ -87,137 +85,8 @@ abstract class Element extends Component implements ElementInterface
public const string SCENARIO_LIVE = 'live';
- // Events
- // -------------------------------------------------------------------------
-
- /**
- * @event AuthorizationCheckEvent The event that is triggered when determining whether a user is authorized to view the element’s edit page.
- *
- * To authorize the user, set [[AuthorizationCheckEvent::$authorized]] to `true`.
- *
- * ```php
- * Event::on(
- * Entry::class,
- * Element::EVENT_AUTHORIZE_VIEW,
- * function(AuthorizationCheckEvent $event) {
- * $event->authorized = true;
- * }
- * );
- * ```
- *
- * @see canView()
- * @since 4.0.0
- */
- #[Deprecated(message: 'in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_VIEW]] should be used instead.')]
- public const EVENT_AUTHORIZE_VIEW = 'authorizeView';
-
- /**
- * @event AuthorizationCheckEvent The event that is triggered when determining whether a user is authorized to save the element in its current state.
- *
- * To authorize the user, set [[AuthorizationCheckEvent::$authorized]] to `true`.
- *
- * ```php
- * Event::on(
- * Entry::class,
- * Element::EVENT_AUTHORIZE_SAVE,
- * function(AuthorizationCheckEvent $event) {
- * $event->authorized = true;
- * }
- * );
- * ```
- *
- * @see canSave()
- * @since 4.0.0
- */
- #[Deprecated(message: 'in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_SAVE]] should be used instead.')]
- public const EVENT_AUTHORIZE_SAVE = 'authorizeSave';
-
- /**
- * @event AuthorizationCheckEvent The event that is triggered when determining whether a user is authorized to create drafts for the element.
- *
- * To authorize the user, set [[AuthorizationCheckEvent::$authorized]] to `true`.
- *
- * ```php
- * Event::on(
- * Entry::class,
- * Element::EVENT_AUTHORIZE_CREATE_DRAFTS,
- * function(AuthorizationCheckEvent $event) {
- * $event->authorized = true;
- * }
- * );
- * ```
- *
- * @see canCreateDrafts()
- * @since 4.0.0
- */
- #[Deprecated(message: 'in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_CREATE_DRAFTS]] should be used instead.')]
- public const EVENT_AUTHORIZE_CREATE_DRAFTS = 'authorizeCreateDrafts';
-
- /**
- * @event AuthorizationCheckEvent The event that is triggered when determining whether a user is authorized to duplicate the element.
- *
- * To authorize the user, set [[AuthorizationCheckEvent::$authorized]] to `true`.
- *
- * ```php
- * Event::on(
- * Entry::class,
- * Element::EVENT_AUTHORIZE_DUPLICATE,
- * function(AuthorizationCheckEvent $event) {
- * $event->authorized = true;
- * }
- * );
- * ```
- *
- * @see canDuplicate()
- * @since 4.0.0
- */
- #[Deprecated(message: 'in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_DUPLICATE]] should be used instead.')]
- public const EVENT_AUTHORIZE_DUPLICATE = 'authorizeDuplicate';
-
- /**
- * @event AuthorizationCheckEvent The event that is triggered when determining whether a user is authorized to delete the element.
- *
- * To authorize the user, set [[AuthorizationCheckEvent::$authorized]] to `true`.
- *
- * ```php
- * Event::on(
- * Entry::class,
- * Element::EVENT_AUTHORIZE_DELETE,
- * function(AuthorizationCheckEvent $event) {
- * $event->authorized = true;
- * }
- * );
- * ```
- *
- * @see canDelete()
- * @since 4.0.0
- */
- #[Deprecated(message: 'in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_DELETE]] should be used instead.')]
- public const EVENT_AUTHORIZE_DELETE = 'authorizeDelete';
-
- /**
- * @event AuthorizationCheckEvent The event that is triggered when determining whether a user is authorized to delete the element for its current site.
- *
- * To authorize the user, set [[AuthorizationCheckEvent::$authorized]] to `true`.
- *
- * ```php
- * Event::on(
- * Entry::class,
- * Element::EVENT_AUTHORIZE_DELETE_FOR_SITE,
- * function(AuthorizationCheckEvent $event) {
- * $event->authorized = true;
- * }
- * );
- * ```
- *
- * @see canDeleteForSite()
- * @since 4.0.0
- */
- #[Deprecated(message: 'in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_DELETE_FOR_SITE]] should be used instead.')]
- public const EVENT_AUTHORIZE_DELETE_FOR_SITE = 'authorizeDeleteForSite';
-
/**
- * @var int|null The element’s ID
+ * @var int|null The element's ID
*/
#[AllowedInSandbox]
public ?int $id = null;
diff --git a/src/Element/Events/AfterDelete.php b/src/Element/Events/AfterDelete.php
new file mode 100644
index 00000000000..6e0f8f15b5d
--- /dev/null
+++ b/src/Element/Events/AfterDelete.php
@@ -0,0 +1,19 @@
+ $elementType The element type class being queried
+ * @param ElementInterface[] $sourceElements An array of the source elements
+ * @param string $handle The property handle used to identify which target elements should be included in the map
+ * @param class-string|null $targetElementType The element type class to eager-load
+ * @param array|null $map An array of element ID mappings, where each element is a sub-array with `source` and `target` keys
+ * @param array|null $criteria Any criteria parameters that should be applied to the element query when fetching the eager-loaded elements
+ */
+ public function __construct(
+ public string $elementType,
+ public array $sourceElements,
+ public string $handle,
+ public ?string $targetElementType = null,
+ public ?array $map = null,
+ public ?array $criteria = null,
+ ) {}
+}
diff --git a/src/Element/Events/DefineInlineAttributeInputHtml.php b/src/Element/Events/DefineInlineAttributeInputHtml.php
new file mode 100644
index 00000000000..7d730324027
--- /dev/null
+++ b/src/Element/Events/DefineInlineAttributeInputHtml.php
@@ -0,0 +1,30 @@
+ $elementType The element type class
+ * @param ElementQueryInterface $query The element query
+ * @param string $attribute The attribute name
+ * @param bool $handled Whether the event has been handled
+ */
+ public function __construct(
+ public string $elementType,
+ public ElementQueryInterface $query,
+ public string $attribute,
+ public bool $handled = false,
+ ) {}
+}
diff --git a/src/Element/Events/RegisterActions.php b/src/Element/Events/RegisterActions.php
new file mode 100644
index 00000000000..e58d9295693
--- /dev/null
+++ b/src/Element/Events/RegisterActions.php
@@ -0,0 +1,24 @@
+ $elementType The element type class
+ * @param string $source The selected source's key
+ * @param array $actions List of registered bulk actions for the element type
+ */
+ public function __construct(
+ public string $elementType,
+ public string $source,
+ public array $actions = [],
+ ) {}
+}
diff --git a/src/Element/Events/RegisterCardAttributes.php b/src/Element/Events/RegisterCardAttributes.php
new file mode 100644
index 00000000000..c1014924636
--- /dev/null
+++ b/src/Element/Events/RegisterCardAttributes.php
@@ -0,0 +1,25 @@
+ $elementType The element type class
+ * @param array $cardAttributes The card attributes
+ * @param FieldLayout|null $fieldLayout The field layout
+ */
+ public function __construct(
+ public string $elementType,
+ public array $cardAttributes = [],
+ public ?FieldLayout $fieldLayout = null,
+ ) {}
+}
diff --git a/src/Element/Events/RegisterDefaultCardAttributes.php b/src/Element/Events/RegisterDefaultCardAttributes.php
new file mode 100644
index 00000000000..b3d4fe529d6
--- /dev/null
+++ b/src/Element/Events/RegisterDefaultCardAttributes.php
@@ -0,0 +1,22 @@
+ $elementType The element type class
+ * @param array $cardAttributes The default card attribute keys
+ */
+ public function __construct(
+ public string $elementType,
+ public array $cardAttributes = [],
+ ) {}
+}
diff --git a/src/Element/Events/RegisterDefaultTableAttributes.php b/src/Element/Events/RegisterDefaultTableAttributes.php
new file mode 100644
index 00000000000..83f03d41076
--- /dev/null
+++ b/src/Element/Events/RegisterDefaultTableAttributes.php
@@ -0,0 +1,24 @@
+ $elementType The element type class
+ * @param string $source The source key
+ * @param array $tableAttributes The default table attribute keys
+ */
+ public function __construct(
+ public string $elementType,
+ public string $source,
+ public array $tableAttributes = [],
+ ) {}
+}
diff --git a/src/Element/Events/RegisterExporters.php b/src/Element/Events/RegisterExporters.php
new file mode 100644
index 00000000000..22b8c339409
--- /dev/null
+++ b/src/Element/Events/RegisterExporters.php
@@ -0,0 +1,24 @@
+ $elementType The element type class
+ * @param string $source The selected source's key
+ * @param array $exporters List of registered exporters for the element type
+ */
+ public function __construct(
+ public string $elementType,
+ public string $source,
+ public array $exporters = [],
+ ) {}
+}
diff --git a/src/Element/Events/RegisterFieldLayouts.php b/src/Element/Events/RegisterFieldLayouts.php
new file mode 100644
index 00000000000..ba11f57d81f
--- /dev/null
+++ b/src/Element/Events/RegisterFieldLayouts.php
@@ -0,0 +1,28 @@
+ $elementType The element type class
+ * @param string|null $source The selected source's key, or null if all known field layouts should be returned
+ * @param FieldLayout[] $fieldLayouts The registered field layouts
+ */
+ public function __construct(
+ public string $elementType,
+ public ?string $source,
+ public array $fieldLayouts = [],
+ ) {}
+}
diff --git a/src/Element/Events/RegisterHtmlAttributes.php b/src/Element/Events/RegisterHtmlAttributes.php
new file mode 100644
index 00000000000..822bafadc16
--- /dev/null
+++ b/src/Element/Events/RegisterHtmlAttributes.php
@@ -0,0 +1,27 @@
+ $elementType The element type class
+ * @param array $attributes The searchable attributes
+ */
+ public function __construct(
+ public string $elementType,
+ public array $attributes = [],
+ ) {}
+}
diff --git a/src/Element/Events/RegisterSortOptions.php b/src/Element/Events/RegisterSortOptions.php
new file mode 100644
index 00000000000..2d939aa8454
--- /dev/null
+++ b/src/Element/Events/RegisterSortOptions.php
@@ -0,0 +1,22 @@
+ $elementType The element type class
+ * @param array $sortOptions The sort options
+ */
+ public function __construct(
+ public string $elementType,
+ public array $sortOptions = [],
+ ) {}
+}
diff --git a/src/Element/Events/RegisterSources.php b/src/Element/Events/RegisterSources.php
new file mode 100644
index 00000000000..c03a9345954
--- /dev/null
+++ b/src/Element/Events/RegisterSources.php
@@ -0,0 +1,26 @@
+ $elementType The element type class
+ * @param string $context The context ('index', 'modal', 'field', or 'settings')
+ * @param array $sources The registered sources
+ */
+ public function __construct(
+ public string $elementType,
+ public string $context,
+ public array $sources = [],
+ ) {}
+}
diff --git a/src/Element/Events/RegisterTableAttributes.php b/src/Element/Events/RegisterTableAttributes.php
new file mode 100644
index 00000000000..7a55baaa788
--- /dev/null
+++ b/src/Element/Events/RegisterTableAttributes.php
@@ -0,0 +1,22 @@
+ $elementType The element type class
+ * @param array $tableAttributes The table attributes
+ */
+ public function __construct(
+ public string $elementType,
+ public array $tableAttributes = [],
+ ) {}
+}
diff --git a/src/Element/Events/Render.php b/src/Element/Events/Render.php
new file mode 100644
index 00000000000..7df6d5ba27d
--- /dev/null
+++ b/src/Element/Events/Render.php
@@ -0,0 +1,28 @@
+hasEventHandlers(self::EVENT_DEFINE_ENTRY_TYPES)) {
- $event = new DefineEntryTypesEvent(['entryTypes' => $entryTypes]);
- $this->trigger(self::EVENT_DEFINE_ENTRY_TYPES, $event);
- $entryTypes = $event->entryTypes;
+ if ($triggerEvent) {
+ event($event = new DefineEntryTypes($this, $entryTypes));
+
+ return $event->entryTypes;
}
return $entryTypes;
@@ -2443,18 +2417,9 @@ public function metaFieldsHtml(bool $static): string
$fields[] = parent::metaFieldsHtml($static);
- // Fire a 'defineEntryMetaFields' event
- if ($this->hasEventHandlers(self::EVENT_DEFINE_META_FIELDS)) {
- $event = new DefineMetaFields([
- 'element' => $this,
- 'static' => $static,
- 'fields' => $fields,
- ]);
- $this->trigger(self::EVENT_DEFINE_META_FIELDS, $event);
- $fields = $event->fields;
- }
+ event($event = new \CraftCms\Cms\Entry\Events\DefineMetaFields($this, $static, $fields));
- return implode("\n", $fields);
+ return implode("\n", $event->fields);
}
/**
@@ -2569,15 +2534,9 @@ private function _parentOptionCriteria(Section $section): array
$parentOptionCriteria['level'] = sprintf('<=%s', $section->maxLevels - $depth);
}
- // Fire a 'defineParentSelectionCriteria' event
- if ($this->hasEventHandlers(self::EVENT_DEFINE_PARENT_SELECTION_CRITERIA)) {
- $event = new ElementCriteriaEvent(['criteria' => $parentOptionCriteria]);
- $this->trigger(self::EVENT_DEFINE_PARENT_SELECTION_CRITERIA, $event);
-
- return $event->criteria;
- }
+ event($event = new DefineParentSelectionCriteria($this, $parentOptionCriteria));
- return $parentOptionCriteria;
+ return $event->criteria;
}
/**
diff --git a/src/Entry/Events/DefineEntryTypes.php b/src/Entry/Events/DefineEntryTypes.php
new file mode 100644
index 00000000000..24a9809b253
--- /dev/null
+++ b/src/Entry/Events/DefineEntryTypes.php
@@ -0,0 +1,21 @@
+hasEventHandlers(self::EVENT_DEFINE_NAME)) {
- $event = new DefineValueEvent;
- $this->trigger(self::EVENT_DEFINE_NAME, $event);
- if ($event->value !== null) {
- return $event->value;
- }
- }
+ event($event = new DefineName($this));
- return $this->fullName ?? (string) $this->username;
+ return $event->name ?? $this->fullName ?? (string) $this->username;
}
/**
@@ -1353,16 +1325,9 @@ public function getFriendlyName(): ?string
private function _defineFriendlyName(): ?string
{
- // Fire a 'defineFriendlyName' event
- if ($this->hasEventHandlers(self::EVENT_DEFINE_FRIENDLY_NAME)) {
- $event = new DefineValueEvent;
- $this->trigger(self::EVENT_DEFINE_FRIENDLY_NAME, $event);
- if ($event->handled || $event->value !== null) {
- return $event->value;
- }
- }
+ event($event = new DefineFriendlyName($this));
- return $this->firstName ?? $this->username;
+ return $event->name ?? $this->firstName ?? $this->username;
}
/**
diff --git a/src/User/Events/DefineFriendlyName.php b/src/User/Events/DefineFriendlyName.php
new file mode 100644
index 00000000000..c66dca32018
--- /dev/null
+++ b/src/User/Events/DefineFriendlyName.php
@@ -0,0 +1,18 @@
+setCustomCacheTags(['original']);
- Event::on(
- TestCacheableElement::class,
- Element::EVENT_DEFINE_CACHE_TAGS,
- function (DefineValueEvent $event) {
- $event->value = array_merge($event->value, ['added-by-event']);
- }
- );
+ \Illuminate\Support\Facades\Event::listen(function (DefineCacheTags $event) {
+ $event->tags = array_merge($event->tags, ['added-by-event']);
+ });
$tags = $element->getCacheTags();
expect($tags)->toContain('original');
expect($tags)->toContain('added-by-event');
-
- Event::off(TestCacheableElement::class, Element::EVENT_DEFINE_CACHE_TAGS);
});
test('works with real Entry element', function () {
diff --git a/tests/Element/Concerns/DisplayedInIndexTest.php b/tests/Element/Concerns/DisplayedInIndexTest.php
index c7a7921cd01..2d4fda09fba 100644
--- a/tests/Element/Concerns/DisplayedInIndexTest.php
+++ b/tests/Element/Concerns/DisplayedInIndexTest.php
@@ -2,15 +2,14 @@
declare(strict_types=1);
-use craft\events\RegisterElementDefaultCardAttributesEvent;
-use craft\events\RegisterElementDefaultTableAttributesEvent;
-use craft\events\RegisterElementSortOptionsEvent;
-use craft\events\RegisterElementTableAttributesEvent;
-use CraftCms\Cms\Element\Element;
+use CraftCms\Cms\Element\Events\RegisterDefaultCardAttributes;
+use CraftCms\Cms\Element\Events\RegisterDefaultTableAttributes;
+use CraftCms\Cms\Element\Events\RegisterSortOptions;
+use CraftCms\Cms\Element\Events\RegisterTableAttributes;
use CraftCms\Cms\Element\Queries\Contracts\ElementQueryInterface;
use CraftCms\Cms\Entry\Elements\Entry;
use CraftCms\Cms\Entry\Models\Entry as EntryModel;
-use yii\base\Event;
+use Illuminate\Support\Facades\Event;
/**
* Test Entry class that exposes protected methods from DisplayedInIndex trait
@@ -559,82 +558,66 @@ public static function hasStatuses(): bool
$eventTriggered = false;
$capturedAttributes = null;
- Event::on(
- Entry::class,
- Element::EVENT_REGISTER_TABLE_ATTRIBUTES,
- function (RegisterElementTableAttributesEvent $event) use (&$eventTriggered, &$capturedAttributes) {
- $eventTriggered = true;
- $capturedAttributes = $event->tableAttributes;
+ Event::listen(function (RegisterTableAttributes $event) use (&$eventTriggered, &$capturedAttributes) {
+ if ($event->elementType !== Entry::class) {
+ return;
}
- );
+ $eventTriggered = true;
+ $capturedAttributes = $event->tableAttributes;
+ });
$attributes = Entry::tableAttributes();
expect($eventTriggered)->toBeTrue();
expect($capturedAttributes)->toBeArray();
expect($capturedAttributes)->toEqual($attributes);
-
- // Clean up
- Event::off(Entry::class, Element::EVENT_REGISTER_TABLE_ATTRIBUTES);
});
test('registerSortOptions event is triggered', function () {
$eventTriggered = false;
- Event::on(
- Entry::class,
- Element::EVENT_REGISTER_SORT_OPTIONS,
- function (RegisterElementSortOptionsEvent $event) use (&$eventTriggered) {
- $eventTriggered = true;
+ Event::listen(function (RegisterSortOptions $event) use (&$eventTriggered) {
+ if ($event->elementType !== Entry::class) {
+ return;
}
- );
+ $eventTriggered = true;
+ });
Entry::sortOptions();
expect($eventTriggered)->toBeTrue();
-
- // Clean up
- Event::off(Entry::class, Element::EVENT_REGISTER_SORT_OPTIONS);
});
test('registerDefaultTableAttributes event is triggered', function () {
$eventTriggered = false;
$capturedSource = null;
- Event::on(
- Entry::class,
- Element::EVENT_REGISTER_DEFAULT_TABLE_ATTRIBUTES,
- function (RegisterElementDefaultTableAttributesEvent $event) use (&$eventTriggered, &$capturedSource) {
- $eventTriggered = true;
- $capturedSource = $event->source;
+ Event::listen(function (RegisterDefaultTableAttributes $event) use (&$eventTriggered, &$capturedSource) {
+ if ($event->elementType !== Entry::class) {
+ return;
}
- );
+ $eventTriggered = true;
+ $capturedSource = $event->source;
+ });
Entry::defaultTableAttributes('*');
expect($eventTriggered)->toBeTrue();
expect($capturedSource)->toBe('*');
-
- // Clean up
- Event::off(Entry::class, Element::EVENT_REGISTER_DEFAULT_TABLE_ATTRIBUTES);
});
test('registerDefaultCardAttributes event is triggered', function () {
$eventTriggered = false;
- Event::on(
- Entry::class,
- Element::EVENT_REGISTER_DEFAULT_CARD_ATTRIBUTES,
- function (RegisterElementDefaultCardAttributesEvent $event) use (&$eventTriggered) {
- $eventTriggered = true;
+ Event::listen(function (RegisterDefaultCardAttributes $event) use (&$eventTriggered) {
+ if ($event->elementType !== Entry::class) {
+ return;
}
- );
+ $eventTriggered = true;
+ });
Entry::defaultCardAttributes();
expect($eventTriggered)->toBeTrue();
-
- // Clean up
- Event::off(Entry::class, Element::EVENT_REGISTER_DEFAULT_CARD_ATTRIBUTES);
});
});
diff --git a/tests/Element/Concerns/ExportableTest.php b/tests/Element/Concerns/ExportableTest.php
index 4f950e85e99..63d6fb48a9d 100644
--- a/tests/Element/Concerns/ExportableTest.php
+++ b/tests/Element/Concerns/ExportableTest.php
@@ -4,9 +4,9 @@
use craft\elements\exporters\Expanded;
use craft\elements\exporters\Raw;
-use craft\events\RegisterElementExportersEvent;
+use CraftCms\Cms\Element\Events\RegisterExporters;
use CraftCms\Cms\Entry\Elements\Entry;
-use yii\base\Event;
+use Illuminate\Support\Facades\Event;
describe('exporters', function () {
test('returns default exporters', function () {
@@ -27,8 +27,7 @@
]);
});
- test('triggers registerExporters event', function () {
- $eventTriggered = false;
+ test('RegisterExporters event allows adding custom exporters', function () {
$customExporter = new class
{
public static function displayName(): string
@@ -37,72 +36,52 @@ public static function displayName(): string
}
};
- Event::on(
- Entry::class,
- Entry::EVENT_REGISTER_EXPORTERS,
- function (RegisterElementExportersEvent $event) use (&$eventTriggered, $customExporter) {
- $eventTriggered = true;
+ Event::listen(function (RegisterExporters $event) use ($customExporter) {
+ if ($event->elementType === Entry::class) {
$event->exporters[] = $customExporter::class;
}
- );
+ });
$exporters = Entry::exporters('*');
- expect($eventTriggered)->toBeTrue();
expect($exporters)->toContain(Raw::class);
expect($exporters)->toContain(Expanded::class);
expect($exporters)->toContain($customExporter::class);
-
- Event::off(Entry::class, Entry::EVENT_REGISTER_EXPORTERS);
});
test('event provides source key', function () {
$capturedSource = null;
- Event::on(
- Entry::class,
- Entry::EVENT_REGISTER_EXPORTERS,
- function (RegisterElementExportersEvent $event) use (&$capturedSource) {
- $capturedSource = $event->source;
- }
- );
+ Event::listen(function (RegisterExporters $event) use (&$capturedSource) {
+ $capturedSource = $event->source;
+ });
Entry::exporters('section:my-section');
expect($capturedSource)->toBe('section:my-section');
-
- Event::off(Entry::class, Entry::EVENT_REGISTER_EXPORTERS);
});
test('event can modify exporters', function () {
- Event::on(
- Entry::class,
- Entry::EVENT_REGISTER_EXPORTERS,
- function (RegisterElementExportersEvent $event) {
+ Event::listen(function (RegisterExporters $event) {
+ if ($event->elementType === Entry::class) {
$event->exporters = [Raw::class];
}
- );
+ });
$exporters = Entry::exporters('*');
expect($exporters)->toBe([Raw::class]);
-
- Event::off(Entry::class, Entry::EVENT_REGISTER_EXPORTERS);
});
test('event can remove all exporters', function () {
- Event::on(
- Entry::class,
- Entry::EVENT_REGISTER_EXPORTERS,
- function (RegisterElementExportersEvent $event) {
+ Event::listen(function (RegisterExporters $event) {
+ if ($event->elementType === Entry::class) {
$event->exporters = [];
}
- );
+ });
$exporters = Entry::exporters('*');
expect($exporters)->toBe([]);
-
- Event::off(Entry::class, Entry::EVENT_REGISTER_EXPORTERS);
});
});
diff --git a/tests/Element/Concerns/HasActionsTest.php b/tests/Element/Concerns/HasActionsTest.php
index cae242fab95..948f55bc38c 100644
--- a/tests/Element/Concerns/HasActionsTest.php
+++ b/tests/Element/Concerns/HasActionsTest.php
@@ -7,7 +7,9 @@
use craft\elements\actions\Edit;
use craft\elements\actions\SetStatus;
use craft\elements\actions\View;
+use CraftCms\Cms\Element\Events\RegisterActions;
use CraftCms\Cms\Entry\Elements\Entry;
+use Illuminate\Support\Facades\Event;
function extractActionTypes(array $actions): array
{
@@ -43,3 +45,19 @@ protected static function defineActions(string $source): array
expect($class::actions('all'))->toContain(Foo::class);
});
+
+test('RegisterActions event allows adding custom actions', function () {
+ Event::listen(function (RegisterActions $event) {
+ if ($event->elementType === Entry::class) {
+ $event->actions[] = CustomAction::class;
+ }
+ });
+
+ $actions = Entry::actions('all');
+ $actionTypes = extractActionTypes($actions);
+
+ expect($actionTypes)->toContain(CustomAction::class);
+});
+
+class CustomAction {}
+class Foo {}
diff --git a/tests/Element/Concerns/HasControlPanelUITest.php b/tests/Element/Concerns/HasControlPanelUITest.php
index d296fa636c7..58e417c503d 100644
--- a/tests/Element/Concerns/HasControlPanelUITest.php
+++ b/tests/Element/Concerns/HasControlPanelUITest.php
@@ -2,18 +2,20 @@
declare(strict_types=1);
-use craft\events\DefineAltActionsEvent;
-use craft\events\DefineAttributeHtmlEvent;
-use craft\events\DefineHtmlEvent;
-use craft\events\DefineMenuItemsEvent;
-use craft\events\DefineMetadataEvent;
-use craft\events\RegisterElementHtmlAttributesEvent;
use CraftCms\Cms\Cms;
+use CraftCms\Cms\Element\Events\DefineActionMenuItems;
+use CraftCms\Cms\Element\Events\DefineAdditionalButtons;
+use CraftCms\Cms\Element\Events\DefineAltActions;
+use CraftCms\Cms\Element\Events\DefineAttributeHtml;
+use CraftCms\Cms\Element\Events\DefineInlineAttributeInputHtml;
+use CraftCms\Cms\Element\Events\DefineMetadata;
+use CraftCms\Cms\Element\Events\DefineSidebarHtml;
+use CraftCms\Cms\Element\Events\RegisterHtmlAttributes;
use CraftCms\Cms\Entry\Elements\Entry;
use CraftCms\Cms\Entry\Models\Entry as EntryModel;
use CraftCms\Cms\Http\Responses\CpScreenResponse;
use CraftCms\Cms\User\Elements\User;
-use yii\base\Event;
+use Illuminate\Support\Facades\Event;
use function Pest\Laravel\actingAs;
@@ -54,25 +56,19 @@
expect((string) $this->entry->getAdditionalButtons())->toBe('');
});
- test('triggers defineAdditionalButtons event', function () {
+ test('triggers DefineAdditionalButtons event', function () {
$eventTriggered = false;
$customHtml = '';
- Event::on(
- Entry::class,
- Entry::EVENT_DEFINE_ADDITIONAL_BUTTONS,
- function (DefineHtmlEvent $event) use (&$eventTriggered, $customHtml) {
- $eventTriggered = true;
- $event->html = $customHtml;
- }
- );
+ Event::listen(function (DefineAdditionalButtons $event) use (&$eventTriggered, $customHtml) {
+ $eventTriggered = true;
+ $event->html = $customHtml;
+ });
$buttons = $this->entry->getAdditionalButtons();
expect($eventTriggered)->toBeTrue();
expect((string) $buttons)->toBe($customHtml);
-
- Event::off(Entry::class, Entry::EVENT_DEFINE_ADDITIONAL_BUTTONS);
});
});
@@ -97,50 +93,38 @@ function (DefineHtmlEvent $event) use (&$eventTriggered, $customHtml) {
expect($continueEditingAction)->toHaveKey('redirect');
});
- test('triggers defineAltActions event', function () {
+ test('triggers DefineAltActions event', function () {
$eventTriggered = false;
$customAction = [
'label' => 'Custom Action',
'action' => 'custom/action',
];
- Event::on(
- Entry::class,
- Entry::EVENT_DEFINE_ALT_ACTIONS,
- function (DefineAltActionsEvent $event) use (&$eventTriggered, $customAction) {
- $eventTriggered = true;
- $event->altActions[] = $customAction;
- }
- );
+ Event::listen(function (DefineAltActions $event) use (&$eventTriggered, $customAction) {
+ $eventTriggered = true;
+ $event->altActions[] = $customAction;
+ });
$altActions = $this->entry->getAltActions();
expect($eventTriggered)->toBeTrue();
expect($altActions)->toContain($customAction);
-
- Event::off(Entry::class, Entry::EVENT_DEFINE_ALT_ACTIONS);
});
test('event can modify alt actions', function () {
- Event::on(
- Entry::class,
- Entry::EVENT_DEFINE_ALT_ACTIONS,
- function (DefineAltActionsEvent $event) {
- $event->altActions = [
- [
- 'label' => 'Only Action',
- 'action' => 'test/action',
- ],
- ];
- }
- );
+ Event::listen(function (DefineAltActions $event) {
+ $event->altActions = [
+ [
+ 'label' => 'Only Action',
+ 'action' => 'test/action',
+ ],
+ ];
+ });
$altActions = $this->entry->getAltActions();
expect($altActions)->toHaveCount(1);
expect($altActions[0]['label'])->toBe('Only Action');
-
- Event::off(Entry::class, Entry::EVENT_DEFINE_ALT_ACTIONS);
});
});
@@ -161,7 +145,7 @@ function (DefineAltActionsEvent $event) {
expect($hasDestructiveItems)->toBeTrue();
});
- test('triggers defineActionMenuItems event', function () {
+ test('triggers DefineActionMenuItems event', function () {
$eventTriggered = false;
$customItem = [
'id' => 'custom-action',
@@ -169,43 +153,31 @@ function (DefineAltActionsEvent $event) {
'icon' => 'wand',
];
- Event::on(
- Entry::class,
- Entry::EVENT_DEFINE_ACTION_MENU_ITEMS,
- function (DefineMenuItemsEvent $event) use (&$eventTriggered, $customItem) {
- $eventTriggered = true;
- $event->items[] = $customItem;
- }
- );
+ Event::listen(function (DefineActionMenuItems $event) use (&$eventTriggered, $customItem) {
+ $eventTriggered = true;
+ $event->items[] = $customItem;
+ });
$items = $this->entry->getActionMenuItems();
expect($eventTriggered)->toBeTrue();
expect($items)->toContain($customItem);
-
- Event::off(Entry::class, Entry::EVENT_DEFINE_ACTION_MENU_ITEMS);
});
test('event can modify menu items', function () {
- Event::on(
- Entry::class,
- Entry::EVENT_DEFINE_ACTION_MENU_ITEMS,
- function (DefineMenuItemsEvent $event) {
- $event->items = [
- [
- 'id' => 'only-item',
- 'label' => 'Only Item',
- ],
- ];
- }
- );
+ Event::listen(function (DefineActionMenuItems $event) {
+ $event->items = [
+ [
+ 'id' => 'only-item',
+ 'label' => 'Only Item',
+ ],
+ ];
+ });
$items = $this->entry->getActionMenuItems();
expect($items)->toHaveCount(1);
expect($items[0]['label'])->toBe('Only Item');
-
- Event::off(Entry::class, Entry::EVENT_DEFINE_ACTION_MENU_ITEMS);
});
});
@@ -222,47 +194,35 @@ function (DefineMenuItemsEvent $event) {
expect($attributes['data'])->toHaveKey('disallow-status');
});
- test('triggers registerHtmlAttributes event', function () {
+ test('triggers RegisterHtmlAttributes event', function () {
$eventTriggered = false;
$customAttribute = 'custom-value';
- Event::on(
- Entry::class,
- Entry::EVENT_REGISTER_HTML_ATTRIBUTES,
- function (RegisterElementHtmlAttributesEvent $event) use (&$eventTriggered, $customAttribute) {
- $eventTriggered = true;
- $event->htmlAttributes['data']['custom'] = $customAttribute;
- }
- );
+ Event::listen(function (RegisterHtmlAttributes $event) use (&$eventTriggered, $customAttribute) {
+ $eventTriggered = true;
+ $event->htmlAttributes['data']['custom'] = $customAttribute;
+ });
$attributes = $this->entry->getHtmlAttributes('index');
expect($eventTriggered)->toBeTrue();
expect($attributes['data']['custom'])->toBe($customAttribute);
-
- Event::off(Entry::class, Entry::EVENT_REGISTER_HTML_ATTRIBUTES);
});
test('event can modify html attributes', function () {
- Event::on(
- Entry::class,
- Entry::EVENT_REGISTER_HTML_ATTRIBUTES,
- function (RegisterElementHtmlAttributesEvent $event) {
- $event->htmlAttributes = [
- 'class' => 'custom-class',
- 'data' => [
- 'test' => 'value',
- ],
- ];
- }
- );
+ Event::listen(function (RegisterHtmlAttributes $event) {
+ $event->htmlAttributes = [
+ 'class' => 'custom-class',
+ 'data' => [
+ 'test' => 'value',
+ ],
+ ];
+ });
$attributes = $this->entry->getHtmlAttributes('index');
expect($attributes)->toHaveKey('class', 'custom-class');
expect($attributes['data'])->toHaveKey('test', 'value');
-
- Event::off(Entry::class, Entry::EVENT_REGISTER_HTML_ATTRIBUTES);
});
});
@@ -273,45 +233,33 @@ function (RegisterElementHtmlAttributesEvent $event) {
expect($html)->toBeString();
});
- test('triggers defineAttributeHtml event', function () {
+ test('triggers DefineAttributeHtml event', function () {
$eventTriggered = false;
$customHtml = 'Custom HTML';
- Event::on(
- Entry::class,
- Entry::EVENT_DEFINE_ATTRIBUTE_HTML,
- function (DefineAttributeHtmlEvent $event) use (&$eventTriggered, $customHtml) {
- $eventTriggered = true;
- if ($event->attribute === 'title') {
- $event->html = $customHtml;
- }
+ Event::listen(function (DefineAttributeHtml $event) use (&$eventTriggered, $customHtml) {
+ $eventTriggered = true;
+ if ($event->attribute === 'title') {
+ $event->html = $customHtml;
}
- );
+ });
$html = $this->entry->getAttributeHtml('title');
expect($eventTriggered)->toBeTrue();
expect((string) $html)->toBe($customHtml);
-
- Event::off(Entry::class, Entry::EVENT_DEFINE_ATTRIBUTE_HTML);
});
test('event receives correct attribute name', function () {
$capturedAttribute = null;
- Event::on(
- Entry::class,
- Entry::EVENT_DEFINE_ATTRIBUTE_HTML,
- function (DefineAttributeHtmlEvent $event) use (&$capturedAttribute) {
- $capturedAttribute = $event->attribute;
- }
- );
+ Event::listen(function (DefineAttributeHtml $event) use (&$capturedAttribute) {
+ $capturedAttribute = $event->attribute;
+ });
$this->entry->getAttributeHtml('slug');
expect($capturedAttribute)->toBe('slug');
-
- Event::off(Entry::class, Entry::EVENT_DEFINE_ATTRIBUTE_HTML);
});
});
@@ -322,45 +270,33 @@ function (DefineAttributeHtmlEvent $event) use (&$capturedAttribute) {
expect($html)->toBeString();
});
- test('triggers defineInlineAttributeInputHtml event', function () {
+ test('triggers DefineInlineAttributeInputHtml event', function () {
$eventTriggered = false;
$customHtml = '';
- Event::on(
- Entry::class,
- Entry::EVENT_DEFINE_INLINE_ATTRIBUTE_INPUT_HTML,
- function (DefineAttributeHtmlEvent $event) use (&$eventTriggered, $customHtml) {
- $eventTriggered = true;
- if ($event->attribute === 'title') {
- $event->html = $customHtml;
- }
+ Event::listen(function (DefineInlineAttributeInputHtml $event) use (&$eventTriggered, $customHtml) {
+ $eventTriggered = true;
+ if ($event->attribute === 'title') {
+ $event->html = $customHtml;
}
- );
+ });
$html = $this->entry->getInlineAttributeInputHtml('title');
expect($eventTriggered)->toBeTrue();
expect((string) $html)->toBe($customHtml);
-
- Event::off(Entry::class, Entry::EVENT_DEFINE_INLINE_ATTRIBUTE_INPUT_HTML);
});
test('event receives correct attribute name', function () {
$capturedAttribute = null;
- Event::on(
- Entry::class,
- Entry::EVENT_DEFINE_INLINE_ATTRIBUTE_INPUT_HTML,
- function (DefineAttributeHtmlEvent $event) use (&$capturedAttribute) {
- $capturedAttribute = $event->attribute;
- }
- );
+ Event::listen(function (DefineInlineAttributeInputHtml $event) use (&$capturedAttribute) {
+ $capturedAttribute = $event->attribute;
+ });
$this->entry->getInlineAttributeInputHtml('slug');
expect($capturedAttribute)->toBe('slug');
-
- Event::off(Entry::class, Entry::EVENT_DEFINE_INLINE_ATTRIBUTE_INPUT_HTML);
});
});
@@ -377,41 +313,29 @@ function (DefineAttributeHtmlEvent $event) use (&$capturedAttribute) {
expect($html)->toBeString();
});
- test('triggers defineSidebarHtml event', function () {
+ test('triggers DefineSidebarHtml event', function () {
$eventTriggered = false;
$customHtml = '