Trying to get simplenews to work in the use case of a blog where one of the newsletter types notifies subscribers of new posts. I want mail to happen without additional action beyond publishing a post. In order to do that (barring a better way), I set $node->simplenews_issue->status = SIMPLENEWS_STATUS_SEND_PUBLISH
in a custom hook_node_create().
This causes a fatal error on saving the node if it is published on its first revision, because sending is triggered from simplenews_node_presave
before the node has been given an id (so it can't be spooled.)
Attached patch adds support for sending immediately on publish like this.
Comment | File | Size | Author |
---|---|---|---|
#13 | 2625412-13.patch | 2.39 KB | mbaynton |
#10 | 2625412-10.patch | 1.96 KB | mbaynton |
| |||
#5 | 2625412-5.patch | 1.88 KB | mbaynton |
| |||
#5 | 2625412-3-5.interdiff.txt | 2.31 KB | mbaynton |
#3 | 2625412-3.patch | 1.59 KB | mbaynton |
|
Comments
Comment #2
mbayntonComment #3
mbayntonCommented new function
Comment #4
BerdirThanks.
We don't really do comments like that. Should be above the code and explain what the code below is doing.
Also, I think if (!$node->isNew()) is a bit more self-explanatory.
so this will only do it if it is set to that value.
That's not very clear from the function name, so we should have some comment that explains when and under which condition this is called.
Also not sure if it really makes sense to have a helper function here. Having different explicit checks in those two hooks might better explain what the code is doing?
coding style nitpick: there should be an empty line between the @param's and the @return. descriptions should be kept < 80 characters. initial line of a function should below, descriptions for return/param should be split to multiple lines.
coding style nitpick: FALSE
Comment #5
mbayntonThanks for the quick response. How's this?
Yes; I could just return TRUE there, but if for some reason
\Drupal::service('simplenews.spool_storage')->addFromEntity($node);
failed to update the status,simplenews_node_insert
would endless loop.Thought about it but kept it for now (with a different name.) There isn't branching within the helper function depending on where it's called from at all, so you just duplicate that code. The function and its usages are within 47 lines now amply commented so I think its fairly clear to see what is happening.
Comment #6
Berdirnew function name works for me. comment is also almost fine, the "or have an id yet" part seems confusing since we don' check for that and it also doesn't really seem valid english to me? I think we can just remove that.
a function reference should have (). I think this comment can be simplified a bit, using revisions here seems confusing to me. What about:
// simplenews_node_presave() cannot automatically send new nodes, send those here and resave.
Hm, now that I think about it, I had an idea. To avoid the double save and also possible problems if saving to spool fails (an exception thrown there in presave could interrupt the node from being saved), what if we always send the node in insert() and just change the flag in presave?
That of course means that we need to save in a different way that we want to send the node. We could use a flag on the node object although that's a bit discouraged (but still quite widely used). Or we could use a pattern with a function that has a static property (or method on a service) that remembers the nid and on insert()/update(), we just check if we had added that/flagged that node?
We should also expand our test coverage for this a bit.
Comment #7
mbayntonyeah that would be bad
Do you mean change the flag to the value we ultimately want saved with the node, SIMPLENEWS_STATUS_SEND_PENDING?
Currently that happens in
SpoolStorage::addFromEntity
after a db insert to simplenews_mail_spool, which I'm guessing is important. So the status on the entity's field will only indicate it's spooled if it really has been. If we switch it up we haveStill I'm definitely for minimizing the amount of things that happen before the node is saved and like your idea because of it. But we would I think want to also find a way to mitigate the impacts of the possible inconsistent state where the node incorrectly thinks it's SEND_PENDING (which the UI currently relies on to tell the user their thing is sending).
Comment #8
mbayntonOr, take the hit and always double-save? Would let you update the spool and entity transactionally even if you wanted and would simplify things quite a bit.
Comment #9
BerdirYes, you're right, that's risky too.
Fair enough, then lets change it so that we always do a double save, it shouldn't happen too often. Add a comment that explains why and we can get this in :)
Comment #10
mbayntonOk this is seriously harder than it should be. When moving to a model where we always save the entity first and then possibly send as a result of publication afterward, hook_node_update breaks. You just can't recursively save a revisionable entity again from within hook_insert / hook_update. The reason is a super-annoying
unset($entity->original)
inEntityStorageBase::doPostSave()
. The second recursive entity save will run to completion before the original one's hook_update implementations run, and those implementations expect $entity->original to exist, but the php object has already experienced one complete save process and part of completely saving the entity is unsetting$entity->original
.I see that
ContentEntityBase
implements __clone and so the obvious solution seemed to be saving a clone of the entity. It seems to work.Just a brand new patch with no interdiff because this is basically starting over.
Comment #11
miro_dietikerThis makes sense, but we really need a test for such an extra use case.
Comment #12
VitaliyDemchuk CreditAttribution: VitaliyDemchuk commentedThere are some changes to this problem?
Comment #13
mbaynton@Berdir, you were right all along in #6. My concern that your approach could lead to an inconsistent state between the saved
simpenews_issue
field and the actual mail spool if some hook_insert() et. al failed was inaccurate, or at least nowadays under core 8.5.6 it's inaccurate, because failures in those hooks result in the database transaction that updated thesimpenews_issue
field to be rolled back.Here's an updated patch that follows the approach you suggested in #6 and seems to be working beautifully in fact; the single-save approach is clearly superior. I'm still strongly considering writing tests too so this is more likely to get in ;) but I wanted to post the patch regardless in case I don't do that and someone else finds it useful.
Just a brand new patch with no interdiff because this is basically starting over. Again.
Comment #14
AdamPS CreditAttribution: AdamPS at AlbanyWeb commented