6

I can't decide if I'm missing something or this should be a bug. With the recent changes to Drafts/Revisions in Craft 3.7 it's not clear to me how to distinguish between New and Updated Entries using the craft\elements\Entry::EVENT_AFTER_SAVE

I've run several tests and documented what I think the key variables I need to be looking at are:

available new/updated entry information

Things I've noticed:

  • Some scenarios trigger the save behavior multiple times
  • The craft\elements\EVENT_AFTER_SAVE::$isNew value just relates to new elements in the db and has nothing to do with published, live entries.
  • The elements that match a "live" scenario also have Draft IDs, so using something like ElementHelper::isDraftOrRevision($entry) doesn't help rule them out
  • In the instances where I'm updating a Live Entry it appears a 'default' scenario exists

However, both New and Updated entries look very similar and the only way I see to distinguish between them is to watch the full request and identify the second 'default' scenario after the first 'live' scenario is triggered.

This feels complicated. Am I missing anything that would make it easier to distinguish between the New and Updated Entry scenarios in the Entry::EVENT_AFTER_SAVE event?

1
  • 2
    I think it would be helpful to specify a Craft version in the question. Craft 3.7 introduced a new entry edit process, as well as concepts such as canonical elements, modified fields and attributes, provisional drafts, etc. github.com/craftcms/cms/blob/develop/… – Ben Croker Jul 20 at 15:43
6

If you want to run some code when changes are published for an entry, you’re going to want to check !ElementHelper::isDraftOrRevision($entry), which has been the case since Craft 3.2. Those saves only use the essentials scenario because validation has already been run at that point, on the draft that is being applied to the entry.

Here’s a full rundown of what happens behind the scenes for each of the entry actions (tailored for 3.7.5+):

Press “New entry” from Entries index page:

  1. An unpublished draft is created
    • isDraft: true
    • isProvisionalDraft: false
    • isCanonical: true
    • firstSave: false
    • scenario: essentials

Make additional changes to the unpublished draft

  1. Unpublished draft is saved
    • isDraft: true
    • isProvisionalDraft: false
    • isCanonical: true
    • firstSave: false
    • scenario: essentials

Press “Create entry” from the Edit Entry page

  1. Draft is updated with any last-minute changes in the POST data and fully validated
    • isDraft: true
    • isProvisionalDraft: false
    • isCanonical: true
    • firstSave: false
    • scenario: live
  2. Draft is resaved as a normal entry
    • isDraft: false
    • isProvisionalDraft: false
    • isCanonical: true
    • firstSave: true
    • scenario: essentials

Start editing the Current revision of an entry

  1. The entry is duplicated as a provisional draft
    • isDraft: true
    • isProvisionalDraft: true
    • isCanonical: false
    • firstSave: false
    • scenario: essentials

Make additional changes to the provisional draft

  1. Provisional draft is saved
    • isDraft: true
    • isProvisionalDraft: true
    • isCanonical: false
    • firstSave: false
    • scenario: essentials

Press “Save” on the provisional draft

  1. Draft is updated with any last-minute changes in the POST data and fully validated
    • isDraft: true
    • isProvisionalDraft: true
    • isCanonical: false
    • scenario: live
  2. Draft is merged into the canonical entry
    • isDraft: false
    • isProvisionalDraft: false
    • isCanonical: true
    • firstSave: false
    • scenario: essentials

Press “Create a draft” on the Current revision (not a provisional draft)

  1. The entry is duplicated as a (normal) draft
    • isDraft: true
    • isProvisionalDraft: false
    • isCanonical: false
    • firstSave: false
    • scenario: essentials

Press “Create a draft” on a provisional draft

  1. The draft is resaved with isProvisionalDraft = false
    • isDraft: true
    • isProvisionalDraft: false
    • isCanonical: false
    • firstSave: false
    • scenario: essentials

Press “Apply draft” on a (normal) draft

  1. Draft is updated with any last-minute changes in the POST data and fully validated
    • isDraft: true
    • isProvisionalDraft: false
    • isCanonical: false
    • firstSave: false
    • scenario: live
  2. Draft is merged into the canonical entry
    • isDraft: false
    • isProvisionalDraft: false
    • isCanonical: true
    • firstSave: false
    • scenario: essentials
8
  • I'll take some time and review this and follow up if I still can't figure out how to distinguish between new and updated entries. I was using !ElementHelper::isDraftOrRevision($entry) in Sprout Email, which I believe you helped me lean on after 3.2, but have folks reporting bugs again after this 3.7. – Ben Parizek Jul 20 at 16:22
  • Thanks for the detailed answer Brandon!! Is it intended behaviour that all fields are marked as dirty when a "draft is merged into the canonical entry"? – Ben Croker Jul 20 at 16:43
  • And no fields are marked dirty when a "draft is resaved as a normal entry"... – Ben Croker Jul 20 at 17:12
  • Or, should I be listening for the "live" scenario if I want to detect which fields/attributes have been modified? – Ben Croker Jul 20 at 17:45
  • 1
    Thanks Brandon! I’d love to see this answer expanded upon and added to the Craft docs, especially since behaviour has changed in recent Craft versions. – Ben Croker Jul 24 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.