Handling Entry Saves
As of Craft 3.2, drafts and revisions are elements just like published entries.
If your plugin or module was registering a listener for an entry’s Element::EVENT_BEFORE_SAVE
or Element::EVENT_AFTER_SAVE
, you may want to avoid multiple saves by first checking whether the element is a draft or revision as opposed to a published entry:
use craft\base\Element;
use craft\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)) {
// don’t do anything with drafts or revisions
return;
}
// ...
}
);
The same applies to Elements::EVENT_BEFORE_SAVE_ELEMENT
and Elements::EVENT_AFTER_SAVE_ELEMENT
.
Craft 3.2 consolidated drafts and revisions, previously with their own separate workflow and storage, intro entries with new draftId
and revisionId
properties and that ElementHelper::isDraftOrRevision()
method.
Craft 3.7 overhauled entry authoring to be more intuitive, adding several concepts to clarify more nuanced underlying context.
Provisional Drafts #
The first of these concepts is a “provisional” draft, which consists of an author’s edits to an entry that weren’t explicitly saved or published. The author is prompted to discard or publish these changes, and that provisional draft stops being provisional when it’s explicitly saved as a draft, published, merged, or discarded.
Canonical Entries #
Craft 3.7 also introduced the concept of “canonical” entries.
Since an entry may represent implicit edits, an explicit draft or revision, or published content, it’s challenging to distinguish the most current, primary source of content from unpublished edits. That’s exactly what “canonical” entries are; if you don’t care about private edits but only entries that are live or pending, look for entries where the isCanonical
property is true
. The opposite of a canonical entry is any one of its ephemeral, derivative counterparts. For that reason, entries have an isDerivative
property that will be true
when it’s a draft or revision, and otherwise false
.
Fresh Entries #
An entry is considered “fresh” when it hasn’t been explicitly saved, but it doesn’t have any validation errors. In other words, when that entry’s content has first been edited, its isFresh
property will be true
.
Entries have a few boolean properties that describe newness:
isNew
has been around longest and indicates whether the entry being saved is new. This became unreliable in Craft 3.2 since drafts and revisions were also entries that could be new—though these derivatives were usually unexpected.isNewForSite
was added more recently thanisNew
and is almost identical, but relative to current site instead of the Craft install as a whole.firstSave
indicates whether an entry is being saved for the first time in a canonical, non-derivative state. (This is most similar toisNew
prior to Craft 3.2.)