Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Flag module passes NULL object to entity hooks. This commit
http://drupalcode.org/project/flag.git/commitdiff/ed26347
unconditionally passes $flagging variable to entity_presave hooks. The patch fixes this.
Comment | File | Size | Author |
---|---|---|---|
#26 | 2162925.26.flag_.entity-hooks-null.patch | 14.44 KB | joachim |
#15 | flag-2162925-15.patch | 1.75 KB | claudiu.cristea |
Comments
Comment #1
joachim CreditAttribution: joachim commentedThat's not the right way to fix this, I'm afraid.
We're always going to be saving a flagging, so we should always invoke that hook.
It's just that it's being invoked too early.
Comment #2
claudiu.cristeaI'm confirming this bug. I'm using flag on user with ajax. When I click the flag I get 500 error. And the error is
I traced the error and found that
$flagging
variable isNULL
when is passed to entity presave hook implementations. In my particular case it crashes intitle_entity_presave()
.I see here the same error caused by the same
NULL
$flagged
variable: #2189461: EntityMalformedException: Missing bundle property on entity of type flagging. in entity_extract_ids() (line 7721 of XXX\includes\common.inc)..I don't know if this patch is the right approach. It seems to me that it only hides the problem. We have to find out why the entity comes as NULL.
And this is critical.
Comment #3
claudiu.cristea#2189461: EntityMalformedException: Missing bundle property on entity of type flagging. in entity_extract_ids() (line 7721 of XXX\includes\common.inc). has been marked as duplicate.
Comment #4
joachim CreditAttribution: joachim commentedThe entity passed to the hook is NULL because the hook is invoked at the wrong point.
It should be invoked later on in the process, when there is definitely a flagging object.
Comment #5
claudiu.cristeaThis is fixing the issue.
Comment #6
mglaman@claudiu.cristea, THANK YOU. I've been going nuts on this for past 3 hours.\
Patch 2162925-5 resolves 500 error.
Comment #7
beamsky CreditAttribution: beamsky commented"flag-null_entity.patch" worked for me. Thank you very very much. You saved me a lot of time!
Comment #8
beamsky CreditAttribution: beamsky commentedoops - won't let me edit my comment. It is Patch 2162925-5 that worked for me. Thanks again!
Comment #9
socketwench CreditAttribution: socketwench commentedTests clean for me too.
Comment #10
joachim CreditAttribution: joachim commentedPatch looks good, but will need some careful reading of the function it changes to check all cases are covered: we need to be invoking this hook iff there is a Flagging that is about to be saved.
It seems to me that there is an existing, separate bug where the hook is not invoked if the entity is already flagged -- that should be filed as a new issue once we've taken care of this.
Comment #11
claudiu.cristeaI checked all possible cases in this function. The only point where we need to 'hook presave" is when
$action == 'flag'
AND!$flagged
. Anonymous is saving in cookies and when $flagged = FALSE we are not saving. So here's the place for presave to live.Comment #12
georgir CreditAttribution: georgir commentedThe proposed patch will prevent entity_presave to be called in the case when
$this->_update_flagging($flagging);
is reached, i.e. when$action == 'flag' && $flagged == TRUE && $flagging
Comment #13
joachim CreditAttribution: joachim commented> It seems to me that there is an existing, separate bug where the hook is not invoked if the entity is already flagged
I was wrong when I said this -- @georgir is correct. This is introduced by the patch, not a separate existing bug.
However, when $this->_update_flagging() is called, no actual database saving is performed. So invoking this hook here is actually incorrect.
Comment #14
claudiu.cristea@joachim, yes, you're right
Comment #15
claudiu.cristeapatch
Comment #16
SweetchuckThe patch in the #15 is solve my problem.
Comment #17
joachim CreditAttribution: joachim commented15: flag-2162925-15.patch queued for re-testing.
Comment #18
joachim CreditAttribution: joachim commentedI committed tests this morning for hook invocation.
Let's check these pass with the patch, and then also consider expanding them to cover this case.
Comment #19
mikl CreditAttribution: mikl commented#15 works for me as well :)
Comment #20
Pierre_G CreditAttribution: Pierre_G commented#15 works for me too! thanks!
Comment #21
joachim CreditAttribution: joachim commentedPatch looks good, though I'll add a few more comments to it and reroll when I have more time.
Particularly for this bit, which while it makes perfect sense, needs more explanation for future maintainer sanity:
We're doing something in the case that we got a $flagging passed in, but we have to account for the fact that we possibly just made one a few lines up... it makes sense and I don't think it can be done better, but all the same... urgh.
I think part of the problem here is that with the advent of flagging entities in 3.x, the flag() method has gained a 3rd purpose, which is pretty much undocumented:
- you want to flag a thing
- you want to unflag a thing
- you want to update the flagging on a thing
The thing about the 3rd purpose, the update of the flagging, is that the flagging object itself is never updated! This is for the simple reason that there are no properties in the {flagging} table that you can update: there is no 'changed' timestamp, and if you want to change anything else (such as the uid, the entity id, the flag id) then you are actually wanting to unflag and then make a completely new flagging.
Therefore, when you use flag() to update a flagging, while the Field API fields on the flagging can get updated, the flagging table is not, and the flagging object itself is not saved!
This raises an interesting question about whether hook_entity_presave() should even be called in this case! I'm going to say that it should, since the fields are updated, and everywhere in Entity and Field API you have to save an entity to save fields. Therefore, we are in principle updating the Flagging entity, even if we're not bothering to update the {flagging} database table -- this can be viewed as a mere performance enhancement.
Hence I'll add some comments about that too :)
Comment #22
drupov CreditAttribution: drupov commentedPatch from #15 did it for me too.
Comment #23
sam.spinoy@gmail.com CreditAttribution: sam.spinoy@gmail.com commentedPatch #15 did the trick here as well.
Comment #24
maximpodorov CreditAttribution: maximpodorov commentedWill somebody mark it as RTBC?
Comment #25
joachim CreditAttribution: joachim commentedI said in #21 I intend to work on it a bit more before committing it.
Comment #26
joachim CreditAttribution: joachim commentedUpdated patch, with more comments, and expanded tests to check for the parameters that hooks get.
We still need tests for the re-flagging case, but I've run out of time -- I'll file a follow-up.
Tests all pass for me locally.
Comment #27
Pere OrgaThe patch does not apply to current git:
Am I doing something wrong?
Comment #28
joachim CreditAttribution: joachim commentedYou might not be on HEAD. Applies for me.
Comment #29
Pere OrgaI already made sure I was in HEAD. And I've tried again:
Comment #30
Pere OrgaOh, I needed to use
git apply
, sorry for that.The patch seems to work for me so far, by the way.
Comment #31
Pere OrgaComment #32
joachim CreditAttribution: joachim commentedThanks everyone -- claudiu.cristea for working on the patch & everyone who tested and reporting back.
git commit -m "Issue #2162925 by claudiu.cristea, joachim: Fixed hook_entity_presave() getting invoked with a NULL for the Flagging entity." --author="claudiucristea "
Comment #33
joachim CreditAttribution: joachim commentedFollow-ups:
- expand our tests: #2196097: add testing of re-flagging case to FlagHookInvocationsTestCase
- while writing the tests, I discovered these bugs! -- #2196085: hook_entity_delete() should be invoked before field data is deleted, #2196055: entity hooks don't get passed a proper Flagging entity.
Comment #35
maximpodorov CreditAttribution: maximpodorov commentedThank you for fixing this.
Comment #37
joachim CreditAttribution: joachim commentedYou're welcome :)
(Resetting to fixed; the testbot doesn't know what it's doing!)
Comment #38
claudiu.cristeaGreat. Thanks!
Comment #40
Yuri CreditAttribution: Yuri commentedis this part of the dev version now?
Can't apply the patch to the latest dev version.
Comment #41
Yuri CreditAttribution: Yuri commentedComment #42
joachim CreditAttribution: joachim commentedThe patch was committed in comment #32.
Comment #43
Yuri CreditAttribution: Yuri commentedI still get this error: EntityMalformedException: Missing bundle property on entity of type flagging. in entity_extract_ids() (line 7727 of xx/includes/common.inc).
Is this not associated with this issue?
Comment #44
joachim CreditAttribution: joachim commentedNope, that's something else. If the flagging were NULL, you'd get a PHP crash because you wouldn't even have an object at all.