Unflagg for an entity or a user and add tests for that, ensuring that when a user is deleted the flags are also deleted.

This is actually quite likely to happen right now because flag_entity_delete() is not implemented. But if when it will be, I think making sure that this doesn't fail hard is important.

CommentFileSizeAuthor
#76 interdiff_2501575_66-76.txt996 bytessocketwench
#76 avoid_fatal_error_when-2501575-76.patch9.23 KBsocketwench
#71 interdiff-2501575-67-71.txt1.28 KBmartin107
#71 avoid_fatal_error_when-2501575-71.patch9.2 KBmartin107
#67 interdiff-avoid_fatal_error_when-2501575-62-66.txt3.64 KBedurenye
#67 avoid_fatal_error_when-2501575-66.patch9.21 KBedurenye
#64 avoid_fatal_error_when-2501575-64.patch.txt8.7 KBmartin107
#64 interdiff-2501575-62-64.txt2.65 KBmartin107
#62 interdiff-avoid_fatal_error_when-2501575-58-62.txt4.29 KBedurenye
#62 avoid_fatal_error_when-2501575-62.patch7.4 KBedurenye
#58 interdiff-avoid_fatal_error_when-2501575-56-58.txt1.19 KBedurenye
#58 avoid_fatal_error_when-2501575-58.patch7.53 KBedurenye
#56 interdiff-avoid_fatal_error_when-2501575-53-56.txt1.03 KBedurenye
#56 avoid_fatal_error_when-2501575-56.patch7.35 KBedurenye
#53 avoid_fatal_error_when-2501575-53.patch8.1 KBedurenye
#50 interdiff-avoid_fatal_error_when-2501575-44-50.txt4.15 KBedurenye
#50 avoid_fatal_error_when-2501575-50.patch7.92 KBedurenye
#44 interdiff-avoid_fatal_error_when-2501575-40-44.txt1.01 KBedurenye
#44 avoid_fatal_error_when-2501575-44.patch8.25 KBedurenye
#40 avoid_fatal_error_when-2501575-40.patch8.25 KBedurenye
#36 avoid_fatal_error_when-2501575-35.patch8.25 KBedurenye
#35 avoid_fatal_error_when-2501575-35.patch0 bytesedurenye
#31 interdiff-fix_flagging_entity-2536380-30-31.txt1.04 KBedurenye
#31 fix_flagging_entity-2536380-31.patch8.08 KBedurenye
#30 interdiff-fix_flagging_entity-2536380-28-30.txt1.01 KBedurenye
#30 fix_flagging_entity-2536380-30.patch8.04 KBedurenye
#28 interdiff-fix_flagging_entity-2536380-25-28.txt2.94 KBedurenye
#28 fix_flagging_entity-2536380-28.patch8.04 KBedurenye
#25 interdiff-fix_flagging_entity-2536380-23-25.txt758 bytesedurenye
#25 fix_flagging_entity-2536380-25.patch7.3 KBedurenye
#23 interdiff-fix_flagging_entity-2536380-20-23.txt3.26 KBedurenye
#23 fix_flagging_entity-2536380-23.patch7.51 KBedurenye
#20 interdiff-fix_flagging_entity-2536380-18-20.txt726 bytesedurenye
#20 fix_flagging_entity-2536380-20.patch6.42 KBedurenye
#18 interdiff-fix_flagging_entity-2536380-16-18.txt1.5 KBedurenye
#18 fix_flagging_entity-2536380-18.patch6.36 KBedurenye
#16 interdiff-fix_flagging_entity-2536380-14-16.txt2.1 KBedurenye
#16 fix_flagging_entity-2536380-16.patch6.17 KBedurenye
avoid-fatal-error.patch947 bytesBerdir
#3 avoid_fatal_error_when-2501575-3-test.patch2.17 KBedurenye
#3 avoid_fatal_error_when-2501575-3-complete.patch3.09 KBedurenye
#6 avoid_fatal_error_when-2501575-6.patch4.45 KBedurenye
#6 interdiff-avoid_fatal_error_when-2501575-3-6.txt3.41 KBedurenye
#10 fix_flagging_entity-2536380-10.patch3.64 KBedurenye
#10 interdiff-fix_flagging_entity-2536380-6-10.txt3.64 KBedurenye
#12 fix_flagging_entity-2536380-12.patch5.23 KBedurenye
#12 interdiff-fix_flagging_entity-2536380-10-12.txt3.13 KBedurenye
#14 fix_flagging_entity-2536380-14.patch5.2 KBedurenye
#14 interdiff-fix_flagging_entity-2536380-12-14.txt525 bytesedurenye
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Anonymous’s picture

Status: Active » Needs review
joachim’s picture

If the flaggable entity is missing, we should probably still remove the flagging.

Though then that would mean we'd have a call to flagging->delete() which bypasses the API, which I can't help but think sets a bad example :/

edurenye’s picture

The last submitted patch, 3: avoid_fatal_error_when-2501575-3-test.patch, failed testing.

mbovan’s picture

Status: Needs review » Needs work
  1. +++ b/src/Tests/FlagSimpleTest.php
    @@ -252,35 +252,45 @@ class FlagSimpleTest extends WebTestBase {
    +    $node1 = $this->drupalCreateNode(['type' => $this->nodeType]);
    +    $node1_id = $node1->id();
    +    $node2 = $this->drupalCreateNode(['type' => $this->nodeType]);
    +    $node2_id = $node2->id();
    ...
    +    $this->drupalGet('node/' . $node1_id);
    ...
    +    $this->drupalGet('node/' . $node2_id);
    ...
    +      ->condition('entity_id', $node1_id)
    ...
    +    $this->drupalPostForm('node/' . $node2_id . '/delete', [], t('Delete'));
    ...
    +      ->condition('entity_id', $node1_id)
    

    Just call $node1->id() or $node2->id().

  2. +++ b/src/Tests/FlagSimpleTest.php
    @@ -252,35 +252,45 @@ class FlagSimpleTest extends WebTestBase {
    +    $this->clickLink('Flag this item');
    

    $this->clickLink(t('Flag this item'));

edurenye’s picture

Status: Needs work » Needs review
FileSize
4.45 KB
3.41 KB

Done.

Status: Needs review » Needs work

The last submitted patch, 6: avoid_fatal_error_when-2501575-6.patch, failed testing.

Berdir’s picture

+++ b/flag.module
@@ -277,13 +277,17 @@ function flag_user_account_removal(UserInterface $account) {
   foreach ($flaggings as $flagging_id => $flagging) {
-    $flag_service->unflag($flagging->getFlag(), $flagging->getFlaggable(), $account);
+    if ($flaggable = $flagging->getFlaggable()) {
+      $flag_service->unflag($flagging->getFlag(), $flaggable, $account);
+    }

We should still try to delete the flagging. So an else that just does $flagging->delete().

And the test should make sure that we are deleting them in the end. You could also add a check to confirm that they haven't been deleted already before the user is deleted, but that would then fail in the follow-up that's suggested below. But that's ok too, file the issue and add a @todo to it.

+++ b/src/Tests/FlagSimpleTest.php
@@ -300,9 +308,9 @@ class FlagSimpleTest extends WebTestBase {
     $this->drupalGet('node/' . $node_id);
-    $this->clickLink('Flag this item');
+    $this->clickLink(t('Flag this item'));
     $this->assertResponse(200);

Contrary to what @mbo said, let's not change this here. It makes the patch a lot bigger due to completely unrelated changes. Let's keep them all without t().

I'd even suggest to not rename $node to $node1 but just add $node2.

Note that the test is only failing as expected and providing the necessary test coverage because flag_entity_delete() is not implemented at all. So we should have a follow-up issue to do so. If that is implemented then we should be fine with this too since it shouldn't happen anymore.

edurenye’s picture

Status: Needs work » Needs review
FileSize
3.64 KB
3.64 KB

I think it's ok now, I made those changes.

Berdir’s picture

Status: Needs review » Needs work
  1. +++ b/src/Tests/FlagSimpleTest.php
    @@ -254,36 +254,38 @@ class FlagSimpleTest extends WebTestBase {
    +    // Ensure both of them are flagged.
    +    $count_flags_before = $this->countFlagging($user_1, $node);
    +    $this->assertTrue(2, $count_flags_before);
    

    I'm confused about this.. you pass in the first node and only count flags for that node ID. So why does that return 2?

  2. +++ b/src/Tests/FlagSimpleTest.php
    @@ -361,4 +363,16 @@ class FlagSimpleTest extends WebTestBase {
    +
    +  protected function countFlagging($user, $node) {
    +    // Ensure there is still one flagged.
    +    return $count_flags = \Drupal::entityQuery('flagging')
    

    $count_flags is unused now and the method needs documentation.

edurenye’s picture

Status: Needs work » Needs review
FileSize
5.23 KB
3.13 KB

I has asserting bad the tests, I have to compare no check if it's true, now the tests are ok.

mbovan’s picture

Status: Needs review » Needs work
+++ b/src/Tests/FlagSimpleTest.php
@@ -245,36 +247,45 @@ class FlagSimpleTest extends WebTestBase {
+    debug($count_flags_before);

One debug() left. :)

edurenye’s picture

Status: Needs work » Needs review
FileSize
525 bytes
5.2 KB

Yes, I forgot to remove, sorry.

mbovan’s picture

+++ b/flag.module
@@ -275,13 +275,23 @@ function flag_user_account_removal(UserInterface $account) {
   $flaggings = $flag_service->getFlaggings(NULL, NULL, $account);
   foreach ($flaggings as $flagging_id => $flagging) {
-    $flag_service->unflag($flagging->getFlag(), $flagging->getFlaggable(), $account);
+    if ($flaggable = $flagging->getFlaggable()) {
+      $flag_service->unflag($flagging->getFlag(), $flaggable, $account);
+    }
+    else {
+      $flagging->delete();
+    }
   }
...
   $flaggings = $flag_service->getFlaggings(NULL, $account);
   foreach ($flaggings as $flagging_id => $flagging) {
-    $flag_service->unflag($flagging->getFlag(), $flagging->getFlaggable());
+    if ($flaggable = $flagging->getFlaggable()) {
+      $flag_service->unflag($flagging->getFlag(), $flaggable);
+    }
+    else {
+      $flagging->delete();
+    }

There is 96.86% similarity between these 2 blocks so I would suggest to create a helper method (in flag.module) and call it twice as it was before with unflag() method.

Won't change the status, as this is only a suggestion.

edurenye’s picture

Here is your suggestion applied.

mbovan’s picture

Status: Needs review » Needs work

Looks nice. :)
Just small changes.

  1. +++ b/flag.module
    @@ -12,7 +12,9 @@ define('FLAG_ADMIN_PATH_START', 3);
    +use Drupal\flag\FlagInterface;
    

    PhpStorm is saying this is not used.

  2. +++ b/flag.module
    @@ -269,19 +271,31 @@ function flag_user_delete(UserInterface $account) {
    +function unflag(EntityInterface $entity = NULL, AccountInterface $account = NULL) {
    

    I would rename this to flag_unflag() (reads strange, but first word in the method name should be module name).

  3. +++ b/flag.module
    @@ -269,19 +271,31 @@ function flag_user_delete(UserInterface $account) {
    +  unflag($account, NULL);
    

    And then change this flag_unflag($account). Second param is null by default.

  4. +++ b/flag.module
    @@ -269,19 +271,31 @@ function flag_user_delete(UserInterface $account) {
    +    if ($flaggable = $flagging->getFlaggable()) {
    

    Possibly add /** @var \Drupal\flag\FlaggingInterface $flagging */ above this line.

edurenye’s picture

Status: Needs work » Needs review
FileSize
6.36 KB
1.5 KB

Done all those changes.

mbovan’s picture

Status: Needs review » Needs work
  1. +++ b/flag.module
    @@ -269,19 +268,32 @@ function flag_user_delete(UserInterface $account) {
    -  /** var \Drupal\flag\FlagServiceInterface $flag_service */
    -  $flag_service = \Drupal::service('flag');
    ...
    +  /** @var \Drupal\flag\FlaggingInterface $flagging */
    +  $flag_service = \Drupal::service('flag');
    

    I think this should be like before.

  2. +++ b/flag.module
    @@ -269,19 +268,32 @@ function flag_user_delete(UserInterface $account) {
    +  $flaggings = $flag_service->getFlaggings(NULL, $entity, $account);
    

    And /** @var \Drupal\flag\FlaggingInterface $flagging */ one line above this one. :)

Other than that, looks good.

edurenye’s picture

Status: Needs work » Needs review
FileSize
6.42 KB
726 bytes

Done.

mbovan’s picture

Looks nice. :)

Berdir’s picture

Status: Needs review » Needs work
+++ b/flag.module
@@ -269,19 +268,33 @@ function flag_user_delete(UserInterface $account) {
+/**
+ * Unflag all flags given to an entity or by an account.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface|NULL $entity
+ *    Will remove all flags done to this entity.
+ * @param \Drupal\Core\Session\AccountInterface|NULL $account
+ *    Will remove all flags by this account.
+ */
+function flag_unflag(EntityInterface $entity = NULL, AccountInterface $account = NULL) {

Seems like this should rather be a method on the flag service, which already has unflag(), so we should add some alternative method there? unflagAll() maybe?

edurenye’s picture

Status: Needs work » Needs review
FileSize
7.51 KB
3.26 KB

Moved to service.

LKS90’s picture

Status: Needs review » Needs work
+++ b/src/Tests/FlagSimpleTest.php
@@ -245,36 +247,44 @@ class FlagSimpleTest extends WebTestBase {
+    // Ensure that are still flagged.

Que?

And:

You could also add a check to confirm that they haven't been deleted already before the user is deleted, but that would then fail in the follow-up that's suggested below. But that's ok too, file the issue and add a @todo to it.

Create the issue, add a @todo, update the issue summary (that one would be really helpful).

edurenye’s picture

Status: Needs work » Needs review
FileSize
7.3 KB
758 bytes

Moved the tests to a todo.

LKS90’s picture

Status: Needs review » Needs work

Create the issue, revert the removal of the test which will fail in the future, update the issue summary (that one would be really helpful).

socketwench’s picture

+++ b/src/FlagService.php
@@ -266,6 +266,25 @@ class FlagService implements FlagServiceInterface {
+    $flag_service = \Drupal::service('flag');

We don't need to call service(), since this is now a just a FlagService method. We can just use $this. ^_^

I was wondering why we even need unflagAll() when we have reset(), and then I saw the different parameter lists. We should add some @see directives to FlagInterface::unflagAll() and FlagInterface::reset() to reduce confusion elsewhere.

edurenye’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
8.04 KB
2.94 KB

Created the issue, added again the tests, added the correct @todo, removed service, added @see tags and edited the summary.

LKS90’s picture

Status: Needs review » Needs work
+++ b/src/Tests/FlagSimpleTest.php
@@ -272,7 +272,13 @@ class FlagSimpleTest extends WebTestBase {
+    // Ensure that are still flagged.

This comment still doesn't make any sense.

edurenye’s picture

Status: Needs work » Needs review
FileSize
8.04 KB
1.01 KB

Done, I hope.

edurenye’s picture

LKS90’s picture

Status: Needs review » Reviewed & tested by the community

Hooray! Looks good to go.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 31: fix_flagging_entity-2536380-31.patch, failed testing.

edurenye’s picture

Status: Needs work » Needs review
FileSize
0 bytes

Rebased.

edurenye’s picture

Wrong file.

juanse254’s picture

Status: Needs review » Needs work

Rebase Needed.

The last submitted patch, 36: avoid_fatal_error_when-2501575-35.patch, failed testing.

edurenye’s picture

Status: Needs work » Needs review
FileSize
8.25 KB

Rebased.

juanse254’s picture

Some nitpicking and good to go

  1. +++ b/flag.module
    @@ -266,20 +264,12 @@ function flag_user_delete(UserInterface $account) {
    -
    

    Unrelated empty line

  2. +++ b/src/Tests/FlagSimpleTest.php
    @@ -245,36 +247,45 @@ class FlagSimpleTest extends WebTestBase {
    +    // Flag both nodes.
    

    improve the comment.

juanse254’s picture

Status: Needs review » Needs work
edurenye’s picture

Status: Needs work » Needs review
FileSize
8.25 KB
1.01 KB

Done.

Status: Needs review » Needs work

The last submitted patch, 44: avoid_fatal_error_when-2501575-44.patch, failed testing.

edurenye’s picture

Status: Needs work » Needs review

Unrelated failing test.

juanse254’s picture

Status: Needs review » Reviewed & tested by the community

Okay tests are good, setting to RTBC.

joachim’s picture

Status: Reviewed & tested by the community » Needs work

Sorry I've not given this any attention. I've been aware of people working on this one.

I think unflagAll() is a good addition. Though reading this patch, I was thinking about how (IIRC) we don't yet take care of deleting flaggings when a flag is deleted. Which let me to thinking that when we tackle that, unflagAll() would acquire an extra $flag parameter. Which then makes reset() a bit pointless really -- reset() is just a special case of unflagAll() where we only specify the $flag parameter. The 'reset' part becomes legacy terminology from previous version of Flag. But that can be dealt with in a clean-up issue later.

The patch does have a few things that need fixing:

  1. +++ b/flag.module
    @@ -9,13 +9,11 @@ define('FLAG_API_VERSION', 3);
    -use Drupal\flag\Entity\Flag;
     use Drupal\node\NodeInterface;
     use Drupal\Core\Entity\EntityInterface;
     use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
     use Drupal\Core\Routing\RouteMatchInterface;
     use Drupal\user\UserInterface;
    -use Drupal\Core\Form\FormStateInterface;
    

    That looks like unrelated cleanup.

  2. +++ b/flag.module
    @@ -266,20 +264,14 @@ function flag_user_delete(UserInterface $account) {
    -  /** var \Drupal\flag\FlagServiceInterface $flag_service */
    +  /** @var \Drupal\flag\FlagService $flag_service */
    

    This shouldn't be changed. The @var type declaration is an interface. See standard proposal: https://www.drupal.org/node/2305593.

  3. +++ b/src/FlagService.php
    @@ -268,6 +268,25 @@ class FlagService implements FlagServiceInterface {
    +    /** @var \Drupal\flag\FlagServiceInterface $flag_service */
    +    $flag_service = \Drupal::service('flag');
    

    We're in the service here! It's $this ;)

  4. +++ b/src/FlagService.php
    @@ -268,6 +268,25 @@ class FlagService implements FlagServiceInterface {
    +      if ($flaggable = $flagging->getFlaggable()) {
    +        $flag_service->unflag($flagging->getFlag(), $flaggable, $account);
    +      }
    +      else {
    +        $flagging->delete();
    +      }
    

    This needs a comment to explain that we're working around the potential situation where the flagging is already gone. Also, it should be mentioned that the unflag event won't get fired. Basically, if we get here, it's because our data is broken and we're trying to do our best to clean it up.

  5. +++ b/src/FlagServiceInterface.php
    @@ -148,16 +148,31 @@ interface FlagServiceInterface {
    +   *    Will remove all flags done to this entity.
    ...
    +   *    Will remove all flags by this account.
    

    Say 'flaggings', not 'flags' here.

  6. +++ b/src/FlagServiceInterface.php
    @@ -148,16 +148,31 @@ interface FlagServiceInterface {
    +   * @see FlagServiceInterface::remove()
    +   *    Not be confused with remove().
    +   */
    

    remove()?

  7. +++ b/src/Tests/FlagSimpleTest.php
    +++ b/src/Tests/FlagSimpleTest.php
    @@ -7,9 +7,11 @@
    

    Hmmmmyeah this test class is a bit of a dumping ground for random bits. I really do appreciate the tests though :)

  8. +++ b/src/Tests/FlagSimpleTest.php
    @@ -245,36 +247,45 @@ class FlagSimpleTest extends WebTestBase {
    +    // Add flags to the nodes.
    

    'Flag the nodes.'

  9. +++ b/src/Tests/FlagSimpleTest.php
    @@ -352,4 +363,27 @@ class FlagSimpleTest extends WebTestBase {
    +  /**
    +   * Count the number of flags of the user over an entity.
    +   *
    

    Is there a reason we're not using the count service? I suppose tests should query the DB directly. Should this go in the base test class maybe?

  10. +++ b/src/Tests/FlagSimpleTest.php
    @@ -352,4 +363,27 @@ class FlagSimpleTest extends WebTestBase {
    +    // Ensure there is still one flagged.
    

    Comment doesn't fit here.

edurenye’s picture

Status: Needs work » Needs review
FileSize
7.92 KB
4.15 KB

Done everything.
In the point 9, I don't have any method in count service to count the flags of a user over an entity, if we have to add it there, then maybe it should be done in a follow up?
The other solution of moving it to base test, means that FlagSimpleTest has to extend base test, or maybe as now most of the things we are testing are in services maybe we should move the tests to that other test class?

socketwench’s picture

Status: Needs review » Reviewed & tested by the community

Verified everything appears to be fixed.

In the point 9, I don't have any method in count service to count the flags of a user over an entity, if we have to add it there, then maybe it should be done in a follow up?

We should create a follow up and add it to the count service if it sounds like it has value. That can be done in another issue.

joachim’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

Argh, needs a reroll, sorry. My fault for taking too long to get round to committing this.

edurenye’s picture

Status: Needs work » Needs review
FileSize
8.1 KB

Rebased.

Berdir’s picture

  1. +++ b/src/FlagServiceInterface.php
    @@ -148,16 +148,31 @@ interface FlagServiceInterface {
    +   * @param \Drupal\Core\Entity\EntityInterface|NULL $entity
    +   *    Will remove all flaggings done to this entity.
    +   * @param \Drupal\Core\Session\AccountInterface|NULL $account
    +   *    Will remove all flaggings by this account.
    

    The description of this could be a bit better. What it basically does is filter on that, if provided. So it should say (optional) and something like If provided, unflags flaggings done to this entity/by this account.

    Also, what happens if neither is provided? Delete everything? Is that supported? (There are actually use cases, for example to be able to uninstall flag. Core has default validations that you can't avoid that prevent you from uninstalling a module that has remaining content entities). Should probably be mentioned.

  2. +++ b/src/FlagServiceInterface.php
    @@ -148,16 +148,31 @@ interface FlagServiceInterface {
    +   * @see FlagServiceInterface::reset()
    +   *    Not be confused with reset().
    

    I don't think @see supports a description? What about making this an inline documentation that references that. Combined with the above.

    * Unflag all flags, optionally filtered by entity and/or an account.
    *
    * Not to be confused with FlagServiceInterface::reset(), which removes flaggings for a flag.
    

    * I actually find "Unflag all flags" quite confusing, the flagging vs flag terminology is tricky. reset() uses "Remove all flagged entities", which is better, but what we actually remove is the flagging, not the entity, so that's kind of confusing too. "Removes all flaggings" might be simpler and clearer? Then we could unify those two descriptions.

Leaving at needs review, lets wait for feedback from @joachim/@socketwench before making changes.

joachim’s picture

Status: Needs review » Needs work

Yup, I agree with all those points.

> I don't think @see supports a description? What about making this an inline documentation that references that. Combined with the above.

Yup. Also, don't say reset() as that's a core PHP function!

> * I actually find "Unflag all flags" quite confusing, the flagging vs flag terminology is tricky. reset() uses "Remove all flagged entities", which is better, but what we actually remove is the flagging, not the entity, so that's kind of confusing too. "Removes all flaggings" might be simpler and clearer? Then we could unify those two descriptions.

Yup. "Remove all flaggings made with this flag / on this entity" is the clearest.

edurenye’s picture

Rebased and applied those changes.
I deleted the @see as FlagServiceInterface doesn't define the reset() anymore.

LKS90’s picture

Status: Needs review » Needs work

Everything looks good except this comment is missing:

Also, what happens if neither is provided? Delete everything? Is that supported? [...] Should probably be mentioned.

edurenye’s picture

Added this comments and changed the short description to "Remove all flaggings from an entity / made by an account."
I think has more sense as this method never removes for a flag, always remove on all the flags just depending on the entity or account.

LKS90’s picture

Status: Needs review » Reviewed & tested by the community

I think the comments should be correct and explanatory now, good to go!

The last submitted patch, 53: avoid_fatal_error_when-2501575-53.patch, failed testing.

joachim’s picture

Status: Reviewed & tested by the community » Needs work

Sorry to knock this back another time :(

There's a few things in unflagAll() that don't quite make sense to me.

  1. +++ b/flag.module
    @@ -7,7 +7,6 @@
    -use Drupal\Core\Access\AccessResult;
    

    Leave this in please -- it's there for commented-out code.

  2. +++ b/src/FlagService.php
    @@ -272,6 +272,25 @@ class FlagService implements FlagServiceInterface {
    +  public function unflagAll(EntityInterface $entity = NULL, AccountInterface $account = NULL) {
    +    $flaggings = $this->getFlaggings(NULL, $entity, $account);
    +
    +    /** @var \Drupal\flag\FlaggingInterface $flagging */
    +    foreach ($flaggings as $flagging_id => $flagging) {
    +      // We're working around the potential situation where the flagging
    +      // is already gone and the unflag event won't get fired.
    +      if ($flaggable = $flagging->getFlaggable()) {
    

    If $entity is specified, the it's the $flaggable, isn't it? So you don't need to keep loading it.

  3. +++ b/src/FlagService.php
    @@ -272,6 +272,25 @@ class FlagService implements FlagServiceInterface {
    +        $this->unflag($flagging->getFlag(), $flaggable, $account);
    

    ... and if $account wasn't given, you're passing a NULL in here!

  4. +++ b/src/Tests/FlagSimpleTest.php
    @@ -235,36 +237,48 @@ class FlagSimpleTest extends FlagTestBase {
         $node = $this->drupalCreateNode(['type' => $this->nodeType]);
         $node_id = $node->id();
    +    $node2 = $this->drupalCreateNode(['type' => $this->nodeType]);
    

    While we're rerolling... could this be $node1 and $node2? Or $node and $node_to_delete?

    And also $node_id is a bug waiting to happen now :/

  5. +++ b/src/Tests/FlagSimpleTest.php
    @@ -356,4 +370,26 @@ class FlagSimpleTest extends FlagTestBase {
    +   * Count the number of flags of the user over an entity.
    

    This isn't quite right -- it counts flaggings, not flags.

  6. +++ b/src/Tests/FlagSimpleTest.php
    @@ -356,4 +370,26 @@ class FlagSimpleTest extends FlagTestBase {
    +  protected function countFlagging(UserInterface $user, NodeInterface $node) {
    

    countFlaggings? or getFlaggingCount?

edurenye’s picture

Done all those points, also deleted flag count service that I'm loading and not using, I think was result of one rebase.

Berdir’s picture

Status: Needs review » Needs work
+++ b/src/FlagService.php
@@ -272,6 +272,25 @@ class FlagService implements FlagServiceInterface {
+      if ($entity ? $flaggable = $entity : $flaggable = $flagging->getFlaggable()) {
+        $this->unflag($flagging->getFlag(), $flaggable, $account);

As @joachim said, I think the $account behavior is not quite correct yet. This documents that NULL = all users. but unflag() is for the current user if it is NULL. So if have no user, you need to pass the user from $flagging to it.

martin107’s picture

Status: Needs work » Needs review
FileSize
2.65 KB
8.7 KB

I think we can refactor flag_user_account_removal() some more- It is the procedural way of sharing common functionality between hooks.
I have moved the logic into the FlagService::userFlagRemoval()

There is still work todo ... so I am just making this change in isolation ... I want to keep the interdiff simple and easy to follow.

I have had a little review and this look like a good change.

It is out of scope but I am going to mention it here just in case it raises things for others.

I was manually going through the steps to both cancel and delete looking to see if anything caused problems

Using /admin/people to delete a account gives these options.

Disable the account and keep its content.
Disable the account and unpublish its content.
Delete the account and make its content belong to the Anonymous user.
Delete the account and its content.

We need a way for the admin to choose to respond in ways that don't delete in every case.
There is nothing wrong with anonymous users flagging content - I will file an issue for that.

Berdir’s picture

@martin107: I think that .patch.txt file should just be .patch?

martin107’s picture

Nuts ....so much for simple and easy to follow :(

edurenye’s picture

Sorry for add the interdiff with the patch 62, but I could not apply the patch 64 so I added those changes manually.
I fixed the comment 63.

edurenye’s picture

Sorry for deliting your file from the file list, but I didn't want to do that, drupal.org did that when I Saved my comment, and your post was already posted :( And I don't have any option tho make it appear again, I don't like how it works when more than one are publishing at the same time.

And we discused with @Berdir that we should create a followup to remove the flags in predelete instead of in delete, so we have to implement flag_user_predelete

martin107’s picture

The merging of patches looks good to me.

I can see another problem .. with FlagService not the last patch

I am going to create a new side issue but I should talk about it here because if we cannot resolve this independently then it makes the approach taken here bad.

The issue is between

\Drupal\user\UserInterface
\Drupal\Core\Session\AccountInterface;

AccountInterface is the larger superset containing all of UserInterface.

The patch introduces UserInterface as an ugly ducking method parameter to FlagService - all other methods use AccountInterface.

Regarding the flow of a UserInterface variable flowing into the service

flag_user_delete() -> FlagService::userFlagRemoval() -> FlagService::unFlagAll() -> FlagService::getFlagging/FlagService::unflag()

So I think we need to make some flag and flagging calls work with the more limited UserInterface.

Anyway I will create the issue tomorrow.

Berdir’s picture

AccountInterface is the larger superset containing all of UserInterface.

No, it's the other way round. UserInterface extends AccountInterface. A user entity is always an account, but an account can also be something else, like the session object/object for the anonymous user.

So, it is perfectly valid to pass a UserInterface into a method that accepts AccountInterface.

martin107’s picture

Hangs head in shame.... to make up for my mistake.

Here is a fix to ugly duckling problem ...now all FlagServices use the AccountInterface.

Berdir’s picture

Status: Needs review » Needs work

I actually think it was correct before.

+++ b/src/FlagService.php
@@ -272,6 +273,36 @@ class FlagService implements FlagServiceInterface {
+   */
+  public function userFlagRemoval(AccountInterface $account) {
+    // Remove flags by this user.
+    $this->unflagAll(NULL, $account);
+
+    // Remove flags that have been done to this user.
+    $this->unflagAll($account);
+  }

UserInterface was correct.

We are calling two things here, and we pass it both to the first and the second argument. The first expects an EntityInterface.

UserInterface extends from EntityInterface and AccountInterface, and is therefore the only correct type hint.

edurenye’s picture

Status: Needs work » Needs review

Then, no need to set it to needs work, the previous patch was just fine.

Not related with this issue:
I know why my comment deleted your file, because both of the patches had the same name, This is a bug of drupal.org site, not sure where to report it, the files maybe need some kind of unic id.

Berdir’s picture

Status: Needs review » Reviewed & tested by the community

Right. RTBC'ing the patch in #67.

This and #2562971: Flag bookmark view is broken are the two patches that I have still applied in our install profile, would love to get rid of them.

socketwench’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

#67 no longer applies

socketwench’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
9.23 KB
996 bytes

  • socketwench authored e3f99bb on 8.x-4.x
    Issue #2501575 by edurenye, martin107, socketwench, Berdir: Fixed fatal...
socketwench’s picture

Status: Needs review » Fixed

Since the conflicts were only comment changes from another issue, there's no need to re-review. Committing.

Thanks everyone!

Status: Fixed » Closed (fixed)

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