In some cases, flag_get_content_flags() causes a notice:

Notice: Undefined offset: 30 in flag_get_content_flags() (regel 1753 van /www/sites/all/modules/flag/flag.module).

Situation:
In a custom module, I want to get information about the flags on a number of nodes. I'm using an individual flag that can be set and unset by all logged-in users. Some nodes are flagged, some are not; in my test site, node 20 is flagged, node 30 is not. The code below is enough to trigger the notice. (With Devel installed you can test this on example.com/devel/php.)

$flag20 = flag_get_content_flags('node', 20, 'myflag');
$flag30 = flag_get_content_flags('node', 30, 'myflag');

It's interesting that this only occurs after running flag_get_content_flags for a flagged node. Just calling $flag30 = flag_get_content_flags('node', 30, 'myflag'); does not result in a notice.

Comments

marcvangend’s picture

I don't know if this is the best way to solve it, but this is the temporary quick-fix I'm using right now:

<?php
function flag_get_content_flags($content_type, $content_id, $flag_name = NULL, $reset = FALSE) {
  static $content_flags;

  if (!isset($content_flags[$content_type][$content_id]) || $reset) {
    $flag_names = _flag_get_flag_names();
    $result = db_select('flag_content', 'fc')
      ->fields('fc')
      ->condition('content_type', $content_type)
      ->condition('content_id', $content_id)
      ->orderBy('timestamp', 'DESC')
      ->execute();
    foreach ($result as $flag_content) {
      // Build a list of flaggings for all flags by user.
      $content_flags[$content_type][$content_id]['users'][$flag_content->uid][$flag_names[$flag_content->fid]] = $flag_content;
      // Build a list of flaggings for each individual flag.
      $content_flags[$content_type][$content_id]['flags'][$flag_names[$flag_content->fid]][$flag_content->uid] = $flag_content;
    }
  }

/* Quick-fix starts here. */
  if (isset($content_flags[$content_type][$content_id])) {
    return isset($flag_name) ? $content_flags[$content_type][$content_id]['flags'][$flag_name] : $content_flags[$content_type][$content_id]['users']; // Quick-fix: this line is now wrapped in an if-statement, but otherwise unchanged.
  }
  else {
    return;
  }
/* Quick-fix ends here. */
  
}
?>

I'd be happy to roll a patch if you think this is the right direction.

arnoldbird’s picture

To avoid hacking the module, I did this in my module...

$result = db_select('flag_content', 'fc')
    ->fields('fc')
    ->condition('content_type', 'node')
    ->condition('content_id', $nid)
    ->execute()
    ->fetchAll();
  
if (!empty($result)) {
    $flags = flag_get_content_flags('node', $nid, 'myflagname');
    etcetera

Though that adds a query that wouldn't be necessary with marcvangend's fix.

joachim’s picture

Version: 7.x-2.0-beta6 » 7.x-3.x-dev

Could someone pinpoint how the second call for node 30 causes the error when the first does not?

I think it would be more elegant to prefill the $entity_flags[$entity_type][$entity_id] array with 'users' and 'flags' and empty arrays before the results are fetched into it, but I'm not entirely sure what's going wrong.

naxoc’s picture

I have the same problem no matter what node I call it on. I have flags in features (ie. not it the database), so the query to the database will never give me my flag I think?

joachim’s picture

Flags in features get saved to the DB immediately. Check if yours is there!

naxoc’s picture

Woops, yeah sorry. Was too fast there. Not features at all.

But the query in flag_get_content_flags() returns nothing for me - I guess that means the user or node has no flags. The return statement is assuming that that there is always data.

joachim’s picture

Ah yes, you're right, that's the problem.

The foreach $result loop assumes there's going to be data, and if there isn't, $entity_flags[$entity_type][$entity_id] will not be set.

socketwench’s picture

Is the function still called flag_get_content_flags() in 3.x? Or should this issue be tagged 2.x?

joachim’s picture

Title: Notice: Undefined index: in flag_get_content_flags() » Notice: Undefined index: in flag_get_entity_flags() / flag_get_content_flags()

It's flag_get_entity_flags() in 3x, but it has the same problem.

naxoc’s picture

Status: Active » Needs review
StatusFileSize
new639 bytes
new621 bytes

Here are patches for both versions.

Status: Needs review » Needs work

The last submitted patch, 1351124-10-7_2_x.patch, failed testing.

naxoc’s picture

Status: Needs work » Needs review
StatusFileSize
new621 bytes
new639 bytes

Woops. Didn't realize there was a testbot here. That is super cool. Patch for 7.2.x from #10 renamed so the tests will not be run on the wrong branch.

joachim’s picture

Status: Needs review » Needs work

Should we not rather prepare $entity_flags[$entity_type][$entity_id] as an empty array() just before the foreach ($result)?

That way, the query that returns no results won't get run a second time because the empty array goes in the statically cached $entity_flags.

naxoc’s picture

Status: Needs work » Needs review
StatusFileSize
new1.18 KB

That makes a lot of sense. New patch. I return array() rather than $entity_flags[$entity_type][$entity_id] for readability even though the value would be the same.

socketwench’s picture

+++ b/flag.moduleundefined
@@ -2079,8 +2080,10 @@ function flag_get_entity_flags($entity_type, $entity_id, $flag_name = NULL) {
+  if (!empty($entity_flags[$entity_type][$entity_id])) {
+    return isset($flag_name) ? $entity_flags[$entity_type][$entity_id]['flags'][$flag_name] : $entity_flags[$entity_type][$entity_id]['users'];
+  }
+  return array();
 }
 
 /**

Can you rewrite the ternary if into a standard if? It's a really long line, and the standard syntax would be a bit more readable.

(I swear I've asked this in another issue somewhere...)

naxoc’s picture

StatusFileSize
new1.21 KB

Agreed. I like the ternary returns, but not when they get that long. I rewrote them.

Now I am just unhappy with the docblock for the function.. I am not sure about the wording for returning an empty array.

joachim’s picture

Status: Needs review » Fixed

I don't quite follow what the @return is telling me as it is. (admittedly it's the end of a long day.)

I'm happy for it to be improved as part of a follow-on docs issue, and if you felt like tackling that, that would be great :)

> (I swear I've asked this in another issue somewhere...)

Yes, you did. Quite rightly so in both cases IMO. socketwench, ternary-killer!!! :D

Issue #1351124 by naxoc: Fixed undefined index in flag_get_entity_flags() when the given entity has no flaggings.

joachim’s picture

Version: 7.x-3.x-dev » 7.x-2.x-dev
Status: Fixed » Patch (to be ported)
naxoc’s picture

Status: Patch (to be ported) » Needs review

Here is a short doc-update to the 7.x.3.x branch. I am not a great doc-writer :)

naxoc’s picture

Status: Needs review » Needs work
StatusFileSize
new634 bytes

Aaand here is the patch.

naxoc’s picture

Status: Needs work » Needs review
StatusFileSize
new1.77 KB

And here is a backport including the small doc-line.

joachim’s picture

Status: Needs review » Fixed

Committed the docs fix and the 2.x fix too.

joachim’s picture

Version: 7.x-2.x-dev » 6.x-2.x-dev
Status: Fixed » Needs review
StatusFileSize
new1.92 KB

Untested backport patch.

nafmarcus’s picture

Any chance of getting quick instructions on applying this patch for Drupal 6.0 and 7.0? Just looking for 2 lines, where to put the file and the command use to apply the patch.

joachim’s picture

*sigh*

I keep having to say to people: try googling 'drupal apply patch'.

BTW, also this patch is for 6.x-2.x only. The issue version tells you that. You can see from earlier comments that it's already been committed to 7.

naxoc’s picture

Version: 6.x-2.x-dev » 7.x-3.x-dev
StatusFileSize
new586 bytes

Sorry to bump the version to back to 7.x.3.x, but i realized that my patches for this issue does not solve the problem in all situations.

I now have a use case where, on the same page, I had two flags potentially active. If one of them had flagged entites I would get an undefined index error because when I ask for the other flag there is no check.

So, to reproduce: have two flags on a entity and have one be flagged and one be unflagged.

Patch attached.

joachim’s picture

Status: Needs review » Fixed

Committed to 7-3.

Status: Fixed » Closed (fixed)

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

joachim’s picture

Version: 7.x-3.x-dev » 7.x-2.x-dev
Status: Closed (fixed) » Patch (to be ported)

Oops. Do bits of the last patch need backporting?

nafmarcus’s picture

To answer you question from 3 months ago, yes, I seem to need the backport for 7x2x.

Flags 3.0 isn't out yet and I'm having the problem.

I tried the patch from #23 and I still have the problem. Is that because that patch isn't complete?
Also, could you explain when this error happens?
You wrote "

The foreach $result loop assumes there's going to be data, and if there isn't, $entity_flags[$entity_type][$entity_id] will not be set."

but what's the situation that causes this?

Thanks,

nafmarcus’s picture

Also, when I try to apply the patch with patch < ./1351124-21.7x2x.patch
in the /flag directory, I get:
"Reversed (or previously applied) patch detected! Assume -R? [n]"
I haven't applied any patches as far as I know.

corvus_ch’s picture

I am a little bit confused. As far as I can tell the patch in comment #26 was committed in the commits #61edfa2 #bc81820 to both 2.x and 3.x month ago. So my question is. What needs to be ported here?

By my understanding this is fixed.

joachim’s picture

No, that was the earlier patch -- compare the date on the git commit and the date on the comment.

#26 contains an additional fix, which from a cursory read of the comments looks like it was only applied to 7--3.

So the situation is:

- 7-3: got original patch + fixup patch. All done.
- 7-2: got original patch backport. Fixup patch needs backporting -- this is where work should be done now.
- 6-2: got nothing. original patch is sitting at #23, but would need the fixup adding to it, as we should do them both in one go. This is where we'll work after 7-2 is done.

corvus_ch’s picture

Thanks for clarification.

blueminds’s picture

Status: Patch (to be ported) » Needs review
StatusFileSize
new601 bytes

Please see attached backport to 7.x-2.x

corvus_ch’s picture

Status: Needs review » Reviewed & tested by the community

The patch looks fine and I can confirm that the notice does not show up with this patch applied.

Thanks.

joachim’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 7x2x. Thanks!

git commit -m "Issue #1351124 by naxoc, blueminds: (Follow-up) Fixed undefined index in flag_get_entity_flags() when the given entity has no flaggings." --author="divamys
"

Status: Fixed » Closed (fixed)

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