Answers.Body: <p>If you want to run some code when changes are published for an entry, you’re going to want to check <code>!ElementHelper::isDraftOrRevision($entry)</code>, which has been the case <a href="https://craftcms.com/knowledge-base/handling-entry-saves" rel="noreferrer">since Craft 3.2</a>. Those saves only use the <code>essentials</code> scenario because validation has already been run at that point, on the draft that is being applied to the entry.</p>
  <p>Here’s a full rundown of what happens behind the scenes for each of the entry actions (tailored for 3.7.5+):</p>
  <p><strong>Press “New entry” from Entries index page:</strong></p>
  <ol>
  <li>An unpublished draft is created
  <ul>
  <li><code>isDraft</code>: <code>true</code></li>
  <li><code>isProvisionalDraft</code>: <code>false</code></li>
  <li><code>isCanonical</code>: <code>true</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>essentials</code></li>
  </ul>
  </li>
  </ol>
  <p><strong>Make additional changes to the unpublished draft</strong></p>
  <ol>
  <li>Unpublished draft is saved
  <ul>
  <li><code>isDraft</code>: <code>true</code></li>
  <li><code>isProvisionalDraft</code>: <code>false</code></li>
  <li><code>isCanonical</code>: <code>true</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>essentials</code></li>
  </ul>
  </li>
  </ol>
  <p><strong>Press “Create entry” from the Edit Entry page</strong></p>
  <ol>
  <li>Draft is updated with any last-minute changes in the POST data and fully validated
  <ul>
  <li><code>isDraft</code>: <code>true</code></li>
  <li><code>isProvisionalDraft</code>: <code>false</code></li>
  <li><code>isCanonical</code>: <code>true</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>live</code></li>
  </ul>
  </li>
  <li>Draft is resaved as a normal entry
  <ul>
  <li><code>isDraft</code>: <code>false</code></li>
  <li><code>isProvisionalDraft</code>: <code>false</code></li>
  <li><code>isCanonical</code>: <code>true</code></li>
  <li><code>firstSave</code>: <code>true</code></li>
  <li><code>scenario</code>: <code>essentials</code></li>
  </ul>
  </li>
  </ol>
  <p><strong>Start editing the Current revision of an entry</strong></p>
  <ol>
  <li>The entry is duplicated as a provisional draft
  <ul>
  <li><code>isDraft</code>: <code>true</code></li>
  <li><code>isProvisionalDraft</code>: <code>true</code></li>
  <li><code>isCanonical</code>: <code>false</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>essentials</code></li>
  </ul>
  </li>
  </ol>
  <p><strong>Make additional changes to the provisional draft</strong></p>
  <ol>
  <li>Provisional draft is saved
  <ul>
  <li><code>isDraft</code>: <code>true</code></li>
  <li><code>isProvisionalDraft</code>: <code>true</code></li>
  <li><code>isCanonical</code>: <code>false</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>essentials</code></li>
  </ul>
  </li>
  </ol>
  <p><strong>Press “Save” on the provisional draft</strong></p>
  <ol>
  <li>Draft is updated with any last-minute changes in the POST data and fully validated
  <ul>
  <li><code>isDraft</code>: <code>true</code></li>
  <li><code>isProvisionalDraft</code>: <code>true</code></li>
  <li><code>isCanonical</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>live</code></li>
  </ul>
  </li>
  <li>Draft is merged into the canonical entry
  <ul>
  <li><code>isDraft</code>: <code>false</code></li>
  <li><code>isProvisionalDraft</code>: <code>false</code></li>
  <li><code>isCanonical</code>: <code>true</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>essentials</code></li>
  </ul>
  </li>
  </ol>
  <p><strong>Press “Create a draft” on the Current revision (not a provisional draft)</strong></p>
  <ol>
  <li>The entry is duplicated as a (normal) draft
  <ul>
  <li><code>isDraft</code>: <code>true</code></li>
  <li><code>isProvisionalDraft</code>: <code>false</code></li>
  <li><code>isCanonical</code>: <code>false</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>essentials</code></li>
  </ul>
  </li>
  </ol>
  <p><strong>Press “Create a draft” on a provisional draft</strong></p>
  <ol>
  <li>The draft is resaved with <code>isProvisionalDraft = false</code>
  <ul>
  <li><code>isDraft</code>: <code>true</code></li>
  <li><code>isProvisionalDraft</code>: <code>false</code></li>
  <li><code>isCanonical</code>: <code>false</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>essentials</code></li>
  </ul>
  </li>
  </ol>
  <p><strong>Press “Apply draft” on a (normal) draft</strong></p>
  <ol>
  <li>Draft is updated with any last-minute changes in the POST data and fully validated
  <ul>
  <li><code>isDraft</code>: <code>true</code></li>
  <li><code>isProvisionalDraft</code>: <code>false</code></li>
  <li><code>isCanonical</code>: <code>false</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>live</code></li>
  </ul>
  </li>
  <li>Draft is merged into the canonical entry
  <ul>
  <li><code>isDraft</code>: <code>false</code></li>
  <li><code>isProvisionalDraft</code>: <code>false</code></li>
  <li><code>isCanonical</code>: <code>true</code></li>
  <li><code>firstSave</code>: <code>false</code></li>
  <li><code>scenario</code>: <code>essentials</code></li>
  </ul>
  </li>
  </ol>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-20T16:22:04.010Z
Answers.Text: 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.
Answers.UserDisplayName: Ben Parizek
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-20T16:43:02.837Z
Answers.Text: 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"?
Answers.UserDisplayName: Ben Croker
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-20T17:12:37.807Z
Answers.Text: And no fields are marked dirty when a "draft is resaved as a normal entry"...
Answers.UserDisplayName: Ben Croker
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-20T17:45:44.080Z
Answers.Text: Or, should I be listening for the "live" scenario if I want to detect which fields/attributes have been modified?
Answers.UserDisplayName: Ben Croker
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-24T04:00:10.347Z
Answers.Text: @BenCroker Unfortunately we don’t have a super reliable way of knowing which fields are dirty/clean outside of a delta form submission, so yes, for now it’s expected that all fields would be marked as dirty. (See [craftcms/cms#9591](https://github.com/craftcms/cms/issues/9591).)
Answers.UserDisplayName: Brandon Kelly
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-24T09:15:54.687Z
Answers.Text: 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.
Answers.UserDisplayName: Ben Croker
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-24T13:02:16.927Z
Answers.Text: Yeah, we’re working on it :)
Answers.UserDisplayName: Brandon Kelly
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-24T13:07:24.760Z
Answers.Text: There was an unintended change in behavior in 3.7, which is that previously `isNew` would be `true` when first publishing an unpublished draft (“Press “Create entry” from the Edit Entry page” above). To compensate, I’ve added a new `firstSave` property in Craft 3.7.5, which will only be `true` when an entry is being saved in a non-draft + non-revision state for the first time. (See [craftcms/cms#9638](https://github.com/craftcms/cms/discussions/9638).) I’ve updated my answer above to include it as well.
Answers.UserDisplayName: Brandon Kelly
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-20T15:55:44.223Z
Answers.LastActivityDate: 2021-07-24T13:04:34.067Z
Answers.LastEditDate: 2021-07-24T13:04:34.067Z
Answers.UserDisplayName: Brandon Kelly
Answers.Body: <p>Brandon's answer was a helpful starting point for me but I think the answer goes deeper and has more scenarios to consider. Here's my attempt at clarifying that:</p>
  <h2>Historic Context</h2>
  <p>Before Drafts and Revisions were Elements, this was simple. When a new Element was created before and after save events had an $isNew property and if it was <code>true</code> you could assume an Element was being saved the first time. If it was <code>false</code> an Element was being updated. Drafts and Revisions were saved in separate tables, using a separate process.</p>
  <p>I believe in Craft 3.2, Drafts and Revisions get updated and become more like Elements in the way they store their data. Rather than their content being stored as a JSON blob in their own unique workflow, they start getting saved like Elements where they have a primary table that stores their ID data and their content gets stored in the content table like other Elements.</p>
  <p>At this point things get more confusing and <code>$element-&gt;resaving</code> becomes a more important variable to know about because if you are running a task that re-saves all Elements, you are not only resaving all primary content in your database you are also potentially re-saving a bunch of Drafts and Revisions too. (Make sure any loosly written email triggering scripts are tended to before updating past 3.2, or when Craft resaves all Elements during it's upgrade process to 3.2, you might be triggering lots of emails!) I believe <code>$isNew</code> continued to mean the same thing.</p>
  <p>In Craft 3.7, Craft made a change to keep the entry ID consistent between its unpublished draft and the real entry (<a href="https://github.com/craftcms/cms/issues/9104" rel="noreferrer">#9104</a>) which had the unintended consequence of changing the meaning of <code>$isNew</code> in the events where it was used. Brandon writes: &quot;Before 3.7, the unpublished draft was duplicated into a normal entry, with a new ID, therefore <code>$isNew</code> was true.&quot; However, after 3.7, <code>$isNew</code> is only true when the initial unpublished draft is auto-saved in the control panel creating the first instance of the element in the db.</p>
  <p>This was addressed in Craft 3.7.5 where a <a href="https://github.com/craftcms/cms/commit/416479f66997bdac211abc883e24d46519a8709e" rel="noreferrer">$firstSave</a> property is introduced for entries.</p>
  <p><em>The above summary is based on my experience and best recollections, so do your testing. My main goal here was to get a lot of these items written down so anybody else that runs into troubles and needs to figure out this stuff might find more information than I did while trying to make sense of it all. If anybody wants to confirm or correct specific version numbers, timeframes, or behaviors, please edit away.</em></p>
  <p><em>For those new to Craft post 3.7.5, there will likely be less confusion or need to care about this than those of us that were working with the CMS from 1.x and 2.x and had to break down our original assumptions of what was going on here.</em></p>
  <h2>New and Updated Elements</h2>
  <p>Below I present a way to target new Elements and Updated Elements. These examples come from a discussion with Brandon Kelly about the topic <a href="https://github.com/craftcms/cms/discussions/9638" rel="noreferrer">here</a>.</p>
  <h3>New Elements</h3>
  <p>To identify new elements, use the <code>$element-&gt;firstSave</code> property.</p>
  <p>The <code>craft\base\Element::EVENT_AFTER_PROPAGATE</code> method only triggers once if you have a multi-site setup so you'll need less logic than if you use <code>EVENT_AFTER_SAVE</code> which gets triggered after Drafts, Revisions, and other multi-site versions of an Element getting saved.</p>
  <p>Here's an example of an event that will trigger once when a new Element is saved:</p>
  <pre><code>use craft\base\Element;
  use craft\elements\Entry;
  use craft\events\ModelEvent;
  use yii\base\Event;
  
  Event::on(
      Entry::class,
      Element::EVENT_AFTER_PROPAGATE,
      function(ModelEvent $event) {
          /** @var Entry $entry */
          $entry = $event-&gt;sender;
          
          if ($entry-&gt;firstSave &amp;&amp; $entry-&gt;getStatus() === Entry::STATUS_LIVE) {
              // boom
          }
      }
  );
  </code></pre>
  <h3>Updated Elements</h3>
  <p>For updated Elements, we need to check a few more things as there can be several scenarios where Elements get updated (canonical elements, drafts, revisions, multi-site). In addition to making sure we don't have a new element, and the element is not a Draft or Revision, you probably also want to make sure to not trigger anything when there is a mass re-save event such as when you update the URL Format of a Section and all Elements in that Section are re-saved. To avoid the <code>ResaveElements</code> queue job scenario we check for <code>!$element-&gt;resaving</code>.</p>
  <p>Below is a helper method that would return <code>true</code> or <code>false</code> if an Element is being updated.</p>
  <pre><code>public function isUpdatedElement($element): bool
  {
      return
          !$element-&gt;firstSave &amp;&amp;
          !ElementHelper::isDraftOrRevision($element) &amp;&amp;
          !$element-&gt;resaving;
  }
  </code></pre>
  <p>Be sure to test. And note that each Element will have different &quot;statuses&quot; so you may need to target a status that is more meaningful to your scenario.</p>
  <p>There may be a few other limitations to be aware of. In the case of trying to match a new, live Entry Element the <code>$entry-&gt;firstSave &amp;&amp; $entry-&gt;getStatus() === Entry::STATUS_LIVE</code> check above would not match a scenario where an author created a new entry and marked it as <code>disabled</code> before they saved it for the first time. In that case, the <code>disabled</code> status of the new entry would not match your check, and only when the author updated the Entry Element to be <code>enabled</code> and re-saved would the element return true for something like the <code>isUpdatedElement()</code> method.</p>
  <p>Similarly, saving a new Entry Element with a <code>postDate</code> in the future would return false for the <code>$entry-&gt;firstSave &amp;&amp; $entry-&gt;getStatus() === Entry::STATUS_LIVE</code> check. No action takes place when a future date becomes a date in the past on the calendar, this type of &quot;new entry&quot; scenario would require some other method to be identified, such as using a cron-job.</p>
  <h2>List of Things that happen</h2>
  <p>While Brandon's list of actions in his answer is a helpful starting point if you ever need to dig into this more than the examples above can address, there's more to it so I would be careful to treat that list as comprehensive. Here's my own list of actions that I ran into while testing.</p>
  <ul>
  <li>Press “New entry” from Entries index page</li>
  <li>Make additional changes to the unpublished draft</li>
  <li>Press “Create entry” from the Edit Entry page</li>
  <li>Press  “Command+S”  from the Edit Entry page (save new entry)</li>
  <li>Start editing the Current revision of an entry</li>
  <li>Make additional changes to the provisional draft</li>
  <li>Press “Save” on the provisional draft</li>
  <li>Press  “Command+S”  from the Edit Entry page (save existing entry with no edits)</li>
  <li>Press “Create a draft” on the Current revision (not a provisional draft)</li>
  <li>Press “Create a draft” on a provisional draft</li>
  <li>Press “Apply draft” on a (normal) draft</li>
  <li>Enable a disabled Entry Element via Element Action</li>
  <li>Disable an Entry Element via Element Action</li>
  <li>Trigger a ResaveElements Task (a simple way to test is to update the URL Format in a Section)</li>
  <li>When an Entry is propagated (If you run multi-site, every time you save a canonical entry you may be triggering an addition save for every other site. If you have a section where 10 Sites can be edited, you may be triggering 10 Elements to be saved behind the scenes)</li>
  <li>Programmatic creation (new &amp; updated scenarios may vary if you are creating Elements via custom code, depending on what methods you are using)</li>
  <li>Guest Entries plugin (As an example of how custom code may differ, the Guest Entry Plugin calls <code>Craft::$app-&gt;getElements()-&gt;saveElement($entry)</code> directly vs sending the request to the <code>EntriesController::actionSaveEntry</code> method which preps a few things before calling the Elements service <code>saveElement</code> method.</li>
  </ul>
  <h2>Some related discussions</h2>
  <ul>
  <li><a href="https://github.com/craftcms/cms/discussions/9638" rel="noreferrer">How do I know if an element is published for the first time?</a></li>
  <li><a href="https://github.com/craftcms/cms/discussions/9669" rel="noreferrer">How do I know if an element is updated and not being updated by the ResaveElements task?</a></li>
  </ul>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-08-16T08:02:06.147Z
Answers.Text: Thanks for this great write-up! I will definitely be referring to this a lot …
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-08-14T11:59:28.013Z
Answers.LastActivityDate: 2021-08-16T20:24:06.357Z
Answers.LastEditDate: 2021-08-16T20:24:06.357Z
Answers.UserDisplayName: Ben Parizek
Answers.Body: <p>Ben's historical explanation is 100% accurate, as is Brandon's technical explanation.</p>
  <p>Here is a <em>practical</em> explanation...</p>
  <p>Much of the time, you won't want this event triggered for Drafts and Revisions. If not explicitly listening for Drafts/Revisions, you can simply <strong>exclude them</strong> based on the <a href="https://craftcms.com/knowledge-base/handling-entry-saves" rel="nofollow noreferrer">example in the docs</a>...</p>
  <pre class="lang-php prettyprint-override"><code>if (ElementHelper::isDraftOrRevision($entry)) {
      // don’t do anything with drafts or revisions
      return;
  }
  </code></pre>
  <p><strong>This will give you the behavior that most people expect.</strong></p>
  <p>Filtering out Drafts &amp; Revisions means that you will only ever see Published Entries. This means that there are realistically only two scenarios where your event will be fully fired...</p>
  <ol>
  <li>When an Entry is <strong>published</strong> for the very first time. (<code>$entry-&gt;firstSave</code> is set to <code>true</code>)</li>
  <li>When an existing published entry is <strong>re-saved</strong>. (<code>$entry-&gt;firstSave</code> is set to <code>false</code>)</li>
  </ol>
  <p>That's basically it! Suppressing Drafts &amp; Revisions makes it much easier to wrap your head around how this event operates.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-09-27T22:02:11.777Z
Answers.LastActivityDate: 2021-09-27T22:02:11.777Z
Answers.UserDisplayName: Lindsey D
Body: <p>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 <code>craft\elements\Entry::EVENT_AFTER_SAVE</code></p>
  <p>I've run several tests and documented what I think the key variables I need to be looking at are:</p>
  <p><a href="https://i.sstatic.net/FcLoa.png" rel="noreferrer"><img src="https://i.sstatic.net/FcLoa.png" alt="available new/updated entry information" /></a></p>
  <p>Things I've noticed:</p>
  <ul>
  <li>Some scenarios trigger the save behavior multiple times</li>
  <li>The <code>craft\elements\EVENT_AFTER_SAVE::$isNew</code> value just relates to new elements in the db and has nothing to do with published, live entries.</li>
  <li>The elements that match a &quot;live&quot; scenario also have Draft IDs, so using something like ElementHelper::isDraftOrRevision($entry) doesn't help rule them out</li>
  <li>In the instances where I'm updating a Live Entry it appears a 'default' scenario exists</li>
  </ul>
  <p>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.</p>
  <p>This feels complicated. Am I missing anything that would make it easier to distinguish between the New and Updated Entry scenarios in the <code>Entry::EVENT_AFTER_SAVE</code> event?</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2021-07-20T15:43:37.373Z
Comments.Text: 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.
  https://github.com/craftcms/cms/blob/develop/CHANGELOG.md#370---2021-07-13
Comments.UserDisplayName: Ben Croker
Tags: <events><element>
Title: How do we distinguish between a 'New' and 'Updated' Live Entry using the craft\elements\Entry::EVENT_AFTER_SAVE event?
ThreadText: # How do we distinguish between a 'New' and 'Updated' Live Entry using the craft\elements\Entry::EVENT_AFTER_SAVE event?
  
  (Asked by: username_0 on 2021-07-20)
  
  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](https://i.sstatic.net/FcLoa.png)](https://i.sstatic.net/FcLoa.png)
  
  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?
  
  **Tags:** events, element
  
  > **Comments:**
  > **username_1**: 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. https://github.com/craftcms/cms/blob/develop/CHANGELOG.md#370---2021-07-13  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_2 on 2021-07-20. Score: 14
  
  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](https://craftcms.com/knowledge-base/handling-entry-saves). 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`
  
  > **Comments:**
  > **username_0**: 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.  
  > **username_1**: Thanks for the detailed answer username_2!! Is it intended behaviour that all fields are marked as dirty when a "draft is merged into the canonical entry"?  
  > **username_1**: And no fields are marked dirty when a "draft is resaved as a normal entry"...  
  > **username_1**: Or, should I be listening for the "live" scenario if I want to detect which fields/attributes have been modified?  
  > **username_2**: @username_1 Unfortunately we don’t have a super reliable way of knowing which fields are dirty/clean outside of a delta form submission, so yes, for now it’s expected that all fields would be marked as dirty. (See [craftcms/cms#9591](https://github.com/craftcms/cms/issues/9591).)  
  > **username_1**: Thanks username_2! I’d love to see this answer expanded upon and added to the Craft docs, especially since behaviour has changed in recent Craft versions.  
  > **username_2**: Yeah, we’re working on it :)  
  > **username_2**: There was an unintended change in behavior in 3.7, which is that previously `isNew` would be `true` when first publishing an unpublished draft (“Press “Create entry” from the Edit Entry page” above). To compensate, I’ve added a new `firstSave` property in Craft 3.7.5, which will only be `true` when an entry is being saved in a non-draft + non-revision state for the first time. (See [craftcms/cms#9638](https://github.com/craftcms/cms/discussions/9638).) I’ve updated my answer above to include it as well.  
  
  ---
  
  ### Answer by username_0 on 2021-08-14. Score: 7
  
  username_2's answer was a helpful starting point for me but I think the answer goes deeper and has more scenarios to consider. Here's my attempt at clarifying that:
  
  ## Historic Context
  
  Before Drafts and Revisions were Elements, this was simple. When a new Element was created before and after save events had an $isNew property and if it was `true` you could assume an Element was being saved the first time. If it was `false` an Element was being updated. Drafts and Revisions were saved in separate tables, using a separate process.
  
  I believe in Craft 3.2, Drafts and Revisions get updated and become more like Elements in the way they store their data. Rather than their content being stored as a JSON blob in their own unique workflow, they start getting saved like Elements where they have a primary table that stores their ID data and their content gets stored in the content table like other Elements.
  
  At this point things get more confusing and `$element->resaving` becomes a more important variable to know about because if you are running a task that re-saves all Elements, you are not only resaving all primary content in your database you are also potentially re-saving a bunch of Drafts and Revisions too. (Make sure any loosly written email triggering scripts are tended to before updating past 3.2, or when Craft resaves all Elements during it's upgrade process to 3.2, you might be triggering lots of emails!) I believe `$isNew` continued to mean the same thing.
  
  In Craft 3.7, Craft made a change to keep the entry ID consistent between its unpublished draft and the real entry ([#9104](https://github.com/craftcms/cms/issues/9104)) which had the unintended consequence of changing the meaning of `$isNew` in the events where it was used. username_2 writes: "Before 3.7, the unpublished draft was duplicated into a normal entry, with a new ID, therefore `$isNew` was true." However, after 3.7, `$isNew` is only true when the initial unpublished draft is auto-saved in the control panel creating the first instance of the element in the db.
  
  This was addressed in Craft 3.7.5 where a [$firstSave](https://github.com/craftcms/cms/commit/416479f66997bdac211abc883e24d46519a8709e) property is introduced for entries.
  
  *The above summary is based on my experience and best recollections, so do your testing. My main goal here was to get a lot of these items written down so anybody else that runs into troubles and needs to figure out this stuff might find more information than I did while trying to make sense of it all. If anybody wants to confirm or correct specific version numbers, timeframes, or behaviors, please edit away.*
  
  *For those new to Craft post 3.7.5, there will likely be less confusion or need to care about this than those of us that were working with the CMS from 1.x and 2.x and had to break down our original assumptions of what was going on here.*
  
  ## New and Updated Elements
  
  Below I present a way to target new Elements and Updated Elements. These examples come from a discussion with username_2 about the topic [here](https://github.com/craftcms/cms/discussions/9638).
  
  ### New Elements
  
  To identify new elements, use the `$element->firstSave` property.
  
  The `craft\base\Element::EVENT_AFTER_PROPAGATE` method only triggers once if you have a multi-site setup so you'll need less logic than if you use `EVENT_AFTER_SAVE` which gets triggered after Drafts, Revisions, and other multi-site versions of an Element getting saved.
  
  Here's an example of an event that will trigger once when a new Element is saved:
  
  ```
  use craft\base\Element;
  use craft\elements\Entry;
  use craft\events\ModelEvent;
  use yii\base\Event;
  
  Event::on(
      Entry::class,
      Element::EVENT_AFTER_PROPAGATE,
      function(ModelEvent $event) {
          /** @var Entry $entry */
          $entry = $event->sender;
          
          if ($entry->firstSave && $entry->getStatus() === Entry::STATUS_LIVE) {
              // boom
          }
      }
  );
  
  ```
  
  ### Updated Elements
  
  For updated Elements, we need to check a few more things as there can be several scenarios where Elements get updated (canonical elements, drafts, revisions, multi-site). In addition to making sure we don't have a new element, and the element is not a Draft or Revision, you probably also want to make sure to not trigger anything when there is a mass re-save event such as when you update the URL Format of a Section and all Elements in that Section are re-saved. To avoid the `ResaveElements` queue job scenario we check for `!$element->resaving`.
  
  Below is a helper method that would return `true` or `false` if an Element is being updated.
  
  ```
  public function isUpdatedElement($element): bool
  {
      return
          !$element->firstSave &&
          !ElementHelper::isDraftOrRevision($element) &&
          !$element->resaving;
  }
  
  ```
  
  Be sure to test. And note that each Element will have different "statuses" so you may need to target a status that is more meaningful to your scenario.
  
  There may be a few other limitations to be aware of. In the case of trying to match a new, live Entry Element the `$entry->firstSave && $entry->getStatus() === Entry::STATUS_LIVE` check above would not match a scenario where an author created a new entry and marked it as `disabled` before they saved it for the first time. In that case, the `disabled` status of the new entry would not match your check, and only when the author updated the Entry Element to be `enabled` and re-saved would the element return true for something like the `isUpdatedElement()` method.
  
  Similarly, saving a new Entry Element with a `postDate` in the future would return false for the `$entry->firstSave && $entry->getStatus() === Entry::STATUS_LIVE` check. No action takes place when a future date becomes a date in the past on the calendar, this type of "new entry" scenario would require some other method to be identified, such as using a cron-job.
  
  ## List of Things that happen
  
  While username_2's list of actions in his answer is a helpful starting point if you ever need to dig into this more than the examples above can address, there's more to it so I would be careful to treat that list as comprehensive. Here's my own list of actions that I ran into while testing.
  
  * Press “New entry” from Entries index page
  * Make additional changes to the unpublished draft
  * Press “Create entry” from the Edit Entry page
  * Press “Command+S” from the Edit Entry page (save new entry)
  * Start editing the Current revision of an entry
  * Make additional changes to the provisional draft
  * Press “Save” on the provisional draft
  * Press “Command+S” from the Edit Entry page (save existing entry with no edits)
  * Press “Create a draft” on the Current revision (not a provisional draft)
  * Press “Create a draft” on a provisional draft
  * Press “Apply draft” on a (normal) draft
  * Enable a disabled Entry Element via Element Action
  * Disable an Entry Element via Element Action
  * Trigger a ResaveElements Task (a simple way to test is to update the URL Format in a Section)
  * When an Entry is propagated (If you run multi-site, every time you save a canonical entry you may be triggering an addition save for every other site. If you have a section where 10 Sites can be edited, you may be triggering 10 Elements to be saved behind the scenes)
  * Programmatic creation (new & updated scenarios may vary if you are creating Elements via custom code, depending on what methods you are using)
  * Guest Entries plugin (As an example of how custom code may differ, the Guest Entry Plugin calls `Craft::$app->getElements()->saveElement($entry)` directly vs sending the request to the `EntriesController::actionSaveEntry` method which preps a few things before calling the Elements service `saveElement` method.
  
  ## Some related discussions
  
  * [How do I know if an element is published for the first time?](https://github.com/craftcms/cms/discussions/9638)
  * [How do I know if an element is updated and not being updated by the ResaveElements task?](https://github.com/craftcms/cms/discussions/9669)
  
  > **Comments:**
  > **username_3**: Thanks for this great write-up! I will definitely be referring to this a lot …  
  
  ---
  
  ### Answer by username_4 on 2021-09-27. Score: 3
  
  Ben's historical explanation is 100% accurate, as is username_2's technical explanation.
  
  Here is a *practical* explanation...
  
  Much of the time, you won't want this event triggered for Drafts and Revisions. If not explicitly listening for Drafts/Revisions, you can simply **exclude them** based on the [example in the docs](https://craftcms.com/knowledge-base/handling-entry-saves)...
  
  ```php
  if (ElementHelper::isDraftOrRevision($entry)) {
      // don’t do anything with drafts or revisions
      return;
  }
  
  ```
  
  **This will give you the behavior that most people expect.**
  
  Filtering out Drafts & Revisions means that you will only ever see Published Entries. This means that there are realistically only two scenarios where your event will be fully fired...
  
  1. When an Entry is **published** for the very first time. (`$entry->firstSave` is set to `true`)
  2. When an existing published entry is **re-saved**. (`$entry->firstSave` is set to `false`)
  
  That's basically it! Suppressing Drafts & Revisions makes it much easier to wrap your head around how this event operates.
  
  
  ---
  
  