isFlagged status is not reflected correctly in some cases, most cases of this will incorrectly show the wrong flag status until the page is refreshed.

Two calls to $flag->isFlagged($entity) that span a Flagging save or a Flagging delete operation will not update the isFlagged status.

Ex.
$flag->isFlagged($entity); (returns Not Flagged)
Call to FlagService flag with $entity.
$flag->isFlagged($entity); (returns Not Flagged Incorrectly)

OR

$flag->isFlagged($entity); (returns Flagged)
Delete Flagging for $entity for $flag_id
$flag->isFlagged($entity); (returns Flagged Incorrectly)

Since the addition of the FlaggingStorage (https://www.drupal.org/commitlog/commit/6408/cf93be36cd4f89a0f6ddafe0bbb...) this has been an issue.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rbrandon created an issue. See original summary.

rbrandon’s picture

I have tested a fix for this that updates the static cache in flaggingStorage.

rbrandon’s picture

Status: Active » Needs review
socketwench’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

Not bad so far! Needs tests.

jhedstrom’s picture

This also needs to implement the resetCache() method to clear these variables, something like:

  /**
   * {@inheritdoc}
   */
  public function resetCache(array $ids = NULL) {
    parent::resetCache($ids);
    $this->flagIdsByEntity = [];
    $this->globalFlagIdsByEntity = [];
  }

but it would ideally take into account the $ids variable and selectively unset them instead.

jhedstrom’s picture

This adds a test to demonstrate the issue, and adds the cache reset method.

The last submitted patch, 6: 2801423-06-TEST-ONLY.patch, failed testing.

The last submitted patch, 6: 2801423-06-TEST-ONLY.patch, failed testing.

jhedstrom’s picture

This patch actually resolves #2826227: Test to verify flagging events with multiple flags. I've re-rolled that issue, as it is probably still worth committing the functional javascript test once this issue is committed.

jhedstrom’s picture

Re-rolled to use the flag create trait now that that is in.

martin107’s picture

I like this issue a lot, the description of the bug is excellent, and the solution looks good.

Regarding the test

This looks good to me,

it uses nothing but standard techniques
it exposes the problem.

the patch as a whole is great. so +1 from me.

My patch fixes a minor nit only.

FlaggingStorageTest::flaggingStorage is defined but unused so I have removed it.

Additionally, I have an alternate perspective which I am not minded to do anything about!

Just for discussion FlaggingStorageTest exercises only FlagService methods to get at the underlying Storage...
I would have argued that at this level we don't care about the underlying storage implementation, or any future implementation we test , we only care that isFlagged() always responds correctly.

In short, I would have been added a test method to the FlagServiceTest without creating a whole new test class.
but I don't want to step in the way or Jhedstrom's design choices, which are all perfectly reasonable.

socketwench’s picture

Status: Needs review » Needs work

In short, I would have been added a test method to the FlagServiceTest without creating a whole new test class.

I like that idea myself, but when I start looking at the code it doesn't seem like the right way forward. This is testing the cache reset of FlaggingStorage. Which leads me to the next problem:

+++ b/src/Entity/Storage/FlaggingStorage.php
@@ -27,6 +27,15 @@ class FlaggingStorage extends SqlContentEntityStorage implements FlaggingStorage
+  public function resetCache(array $ids = NULL) {
+    parent::resetCache($ids);
+    $this->flagIdsByEntity = [];
+    $this->globalFlagIdsByEntity = [];
+  }

If this is public, shouldn't it be a part of FlaggingStorageInterface? Then a separate test makes a lot more sense.

jhedstrom’s picture

If this is public, shouldn't it be a part of FlaggingStorageInterface? Then a separate test makes a lot more sense.

The resetCache method is part of EntityStorageInterface, which this one extends, so no need to redeclare that method on the flagging storage interface.

As for the separate test method, kernel tests are very lightweight compared to web/browser tests, so adding a storage specific test class doesn't add much in terms of run time. It also is specific to the storage class, rather than the flag service. However, I don't want to block this fix, so either way is fine by me :)

jhedstrom’s picture

Status: Needs work » Needs review

Setting back to needs review for #13.

socketwench’s picture

Status: Needs review » Reviewed & tested by the community

The resetCache method is part of EntityStorageInterface, which this one extends, so no need to redeclare that method on the flagging storage interface.

Makes sense. I can't find anything else to hold up this patch.

  • socketwench committed 03d0bd6 on 8.x-4.x authored by martin107
    Issue #2801423 by jhedstrom, martin107, rbrandon: Fixed FlaggingStorage...
socketwench’s picture

Status: Reviewed & tested by the community » Fixed

Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.