Hi everyone,
My first time logging a bug in Drupal core, so aplogies if I get anything wrong here. I've looked through the 7.x issue queue and can't see this listed yet.

Basically, theres a PHP error which results in an error message after a certain sequence of using aggregator blocks.
Steps to reproduce this:
1) Add several feeds to the aggregator with settings to allow say 5 items in their blocks
2) Assign one or more of those feed blocks to a region in your theme
3) Then go back to the aggregator and set the 'News items in block' setting for every feed to zero (to disable their blocks)
4) You see an error message on every page that the blocks previously appeared on. Something like:

Notice: Undefined variable: result in aggregator_block_view() (line 418 of /httpd.www/drupal/modules/aggregator/aggregator.module).
# Warning: Invalid argument supplied for foreach() in aggregator_block_view() (line 418 of /httpd.www/drupal/modules/aggregator/aggregator.module).

The relevant bit of code is the function aggregator_block_view in lines 394-426 in aggregator.module:

function aggregator_block_view($delta = '') {
  if (user_access('access news feeds')) {
    $block = array();
    list($type, $id) = explode('-', $delta);
    switch ($type) {
      case 'feed':
        if ($feed = db_query('SELECT fid, title, block FROM {aggregator_feed} WHERE block <> 0 AND fid = :fid', array(':fid' => $id))->fetchObject()) {
          $block['subject'] = check_plain($feed->title);
          $result = db_query_range("SELECT * FROM {aggregator_item} WHERE fid = :fid ORDER BY timestamp DESC, iid DESC", 0, $feed->block, array(':fid' => $id));
          $read_more = theme('more_link', array('url' => 'aggregator/sources/' . $feed->fid, 'title' => t("View this feed's recent news.")));
        }
        break;

      case 'category':
        if ($category = db_query('SELECT cid, title, block FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $id))->fetchObject()) {
          $block['subject'] = check_plain($category->title);
          $result = db_query_range('SELECT i.* FROM {aggregator_category_item} ci LEFT JOIN {aggregator_item} i ON ci.iid = i.iid WHERE ci.cid = :cid ORDER BY i.timestamp DESC, i.iid DESC', 0, $category->block, array(':cid' => $category->cid));
          $read_more = theme('more_link', array('url' => 'aggregator/categories/' . $category->cid, 'title' => t("View this category's recent news.")));
        }
        break;
    }
    $items = array();
    foreach ($result as $item) {
      $items[] = theme('aggregator_block_item', array('item' => $item));
    }

    // Only display the block if there are items to show.
    if (count($items) > 0) {
      $block['content'] = theme('item_list', array('items' => $items)) . $read_more;
    }
    return $block;
  }
}

I think what is happening here, is that the aggregator_block_view function is still running on those pages, and the SQL is returning no items, since there are no feeds with block items>0. The variable $result is then not set, and on line 416, attempting to loop through the $result array generates an error.

This could be solved with an if(isset($result)) {} wrapper around the for loop?

Comments

grahamgilchrist’s picture

Version: 7.x-dev » 7.0
Yaron Tal’s picture

looks like the value of $type isn't in the switch, because $result should contain "DatabaseStatementInterface A prepared statement object, already executed.", and not like in 6.x a FALSE. A default in the switch could solve this I guess.

What about adding this:

switch ($type) {
  default:
    return array('content' => '', 'subject' => '');
    break;
}

edit: or $id isn't a valid id. Anyhow, the $delta seems corrupt.

grahamgilchrist’s picture

Debugging on my site seems to indicate that the $type switch does get set properly.
It switches into $case 'feed' without any problems, but the issue seems to be if $feed returns nothing, then $result is not set, and then the foreach loop throws an error as $result is not an array.

This only happens if you assign a feed block to a region, and then set the 'News items in block' setting (at admin/config/services/aggregator/edit/feed/#id) to zero for all feed blocks.

Yaron Tal’s picture

StatusFileSize
new636 bytes

oops sorry yeah you are right. I missed the <> 0 in the first sql. I agree that adding if (isset($result)) should be enough to fix the issue. Also this would fix the hypothetical issue of a corrupt $delta.

Yaron Tal’s picture

Status: Active » Needs review
libre fan’s picture

Hello,

I'm getting

Notice: Undefined variable: result in aggregator_block_view() (line 415 of /modules/aggregator/aggregator.module).
    Warning: Invalid argument supplied for foreach() in aggregator_block_view() (line 415 of /modules/aggregator/aggregator.module).

even if I don't assign zero for all feed blocks.

It's a recent error though. It happened after I added a new news feed and a new feed block.

Yaron Tal’s picture

@#6 did you try using the above patch? It looks like the exact same error. Giving only 1 block a 0 should be enough to trigger it.

twistor’s picture

Version: 7.0 » 8.x-dev
Status: Needs review » Needs work

The patch seems fine, but there's a whitespace problem. Moving to 8.x as it exists there.

libre fan’s picture

@#6 Many thanks, Yaron Tal, for your patch. I wasn't sure if it was safe to use for anybody. But appparently it works on my site.

Yaron Tal’s picture

Status: Needs work » Needs review
StatusFileSize
new634 bytes
new634 bytes

I attached a D8 version of the patch and a D7 version with the whitespace problem fixed.

Status: Needs review » Needs work

The last submitted patch, aggregator_isset-1058754-8.patch, failed testing.

Yaron Tal’s picture

Status: Needs work » Needs review

#10: aggregator_isset-1058754-8.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, aggregator_isset-1058754-8.patch, failed testing.

libre fan’s picture

Hello everybody,

Apparently the patch didn't make its way into Drupal 7.9, so I reapplied patch aggregator_1058754.patch

kathyh’s picture

Status: Needs work » Needs review
StatusFileSize
new658 bytes

Updated patch for D8 /core changes.

tamsoftware’s picture

D7 patch worked beautifully here! THANKS!

Details:
Bug surfaced in Drupal 7.8 when setting unused blocs to zero
Upgrading to 7.10 did not clear the issue
Applying the #10 patch like this fixed it:

#cd drupal
#patch -p1 modules/aggregator/aggregator.module  aggregator_isset-1058754-8-D7.patch

Franck Horlaville
TAM Software

libre fan’s picture

hello everybody,

Just wondering why this useful patch hasn't find its way into Drupal 7.12

jody lynn’s picture

Status: Needs review » Reviewed & tested by the community

Looks fine.

catch’s picture

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

This could use a test.

naxoc’s picture

Assigned: Unassigned » naxoc

I'll look at a test for this.

naxoc’s picture

Status: Needs work » Needs review
StatusFileSize
new1.01 KB
new1 KB
new1.05 KB
new1.02 KB

I made the tests separate patches so that the tests can run without the fix and fail on purpose. That way we can "test the test".

I changed the fix a little so we avoid the use of an uninitialized variable.

There are patches for both D7 and D8

Status: Needs review » Needs work

The last submitted patch, aggregator-module-1058754-21-d7.patch, failed testing.

xjm’s picture

Issue tags: -Needs tests
StatusFileSize
new2.07 KB
new1.02 KB

That test looks great. Thanks @naxoc!

Here I've made one small change (removed t() from the assertion message; see http://drupal.org/simpletest-tutorial-drupal7#t). @naxoc's post above demonstrates that the test fails correctly without the fix. I combined the fix with the test in the second patch so we can confirm the fix does fix it.

xjm’s picture

Status: Needs work » Needs review
xjm’s picture

Status: Needs review » Reviewed & tested by the community

And, I think that's RTBC. :)

catch’s picture

Title: Attempt to loop through empty array in Aggregator block view » Attempt to loop through undefined result set in aggregator
Version: 8.x-dev » 7.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)
Issue tags: +Novice, +Needs backport to D7

Committed/pushed to 8.x, thanks!

Moving to D7 for backport. Should be a straightforward backport so tagging novice for that.

tim.plunkett’s picture

Status: Patch (to be ported) » Needs review
StatusFileSize
new2.03 KB
new1 KB

Straight backport with patch -p2, didn't test it myself.

xjm’s picture

Assigned: naxoc » Unassigned
Status: Needs review » Reviewed & tested by the community

Correct diffstat; correct code; nothing D8 specific. I swear! :)

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed to 7.x for parity with 8.x. Thanks!

However, question. Is t($block['title']) kosher? I've always been slapped by Gábor for using t() with dynamic values.

xjm’s picture

Version: 7.x-dev » 8.x-dev
Status: Fixed » Needs work

You're right; that's totally wrong. It should probably be an assertRaw(), I think? It's in any case not matching the correct thing, because the original string is definitely not output as just that value inside its own t(). Reference:
http://drupal.org/simpletest-tutorial-drupal7#t

Novice task: Followup patch change the assertion to something more correct. :)

blackra’s picture

StatusFileSize
new1.64 KB

Here is a patch that includes the following:

  • Changed assertNoText() to assertNoRaw() in the check for the empty feed case
  • Removed the t() from the assertNoRaw() test and the corresponding assertText() test (for where there is content)
  • Added comments to help keep these tests in sync

Things I did not do:

  • Change assertRaw() to assertText() for the content present case. I was not sure whether this was appropriate and leaving it seemed safe since assertText() should be the tougher test.
  • Find a feed name that would differentiate between t() and no t()

In the process of looking for a feed name that would differentiate between t() and no t(), I found that changing $feed_name = $this->randomName(10); to $feed_name = 'hello%20&amp;raw'; in AggregatorTestBase.php produced lots of test failures. I haven't worked out why yet. However, it appears to be possible to set up a feed with this name through the user interface.

blackra’s picture

Status: Needs work » Needs review
cameron tod’s picture

rob.black, thank you very much for your help! Could you roll the patch #27 & #31 together into a combined patch, one with the tests only, and one with the fixes + tests? That way the whole patch can be reviewed, tested by testbot, and if all goes well, committed.

cameron tod’s picture

Status: Needs review » Needs work
blackra’s picture

cam8001, I am confused.

I was attempting to produce a patch to address xjm and webchick's comments in 8.x based on the understanding that the original patch #23 had already been committed and, after it was applied the tests were restructured. Since #23 has already been committed, there is no point rolling my patch together with it; my patch is based on a version of 8.x that already includes that fix.

#27 is a 7.x backport patch (and again, I think it has already been committed). Whilst I could produce a 7.x backport of my patch, shouldn't this wait until the 8.x version has been reviewed?

cameron tod’s picture

Status: Needs work » Needs review

Looks like I was very confused and totally misread the thread. Sorry about that.

ParisLiakos’s picture

Version: 8.x-dev » 7.x-dev

the followup got fixed in another issue in D8, back to D7

mgifford’s picture

Status: Needs review » Closed (fixed)

I think this is already in D7. The changes from aggregator_block_view() are there.