They all use the "0" pager id, so each pager is messing up every other pagers that use the same "0" pager id.

How to recreate the bug:

1) visit path "/node", which is the default front page path
2) Make sure some node_gallery nodes are showing
3) Look at the pager at the very bottom of the front page, it would be wrong

A more obvious way to see the bug:

1) create a test site
2) use devel to generate enough filler content to make the front page show a pager at the bottom
3) create a node_gallery, only upload just a couple of pictures so no pager will be shown
4) now visit the front page, make sure the gallery is shown
5) the pager normally shown at the very bottom of the front page is not shown anymore

The reason for this bug is that the pager id are set at "0" which is what the front page use so they each interfere with other.

This can be fixed by changing the pager id to something other than "0" like "2" in the view settings. But this will break again if more than one nod_gallery teaser is showing because they share the same pager id. What's really needed is somehow make views use a different unique pager id for all the pager on each page. Don't know how this can be done but there may be some call can be made before invoking views_embed_view(). This will solve the problem with node_gallery. But some other pager from some place else can interfere again. But this is a drupal problem that cannot be fixed.

Comments

mattyoung’s picture

or use a display that don't have pager.

scroogie’s picture

Is this bug still visible with Views 3?

scroogie’s picture

Status: Active » Needs review
StatusFileSize
new832 bytes

Could you try out this patch please?

mattyoung’s picture

Status: Needs review » Needs work
StatusFileSize
new876 bytes

Patch does not fix the problem. But after a long debug session looking at Views, I came up with the fix.

Here is the long story: the problem is pager id is not in $view->pager['element']. It's in $view->query->pager->options['id']. But the $view->query field is not initialized when hook_view_pre_build() is called. But the field is initialized when hook_view_pre_execute() called. So I first try setting the value there. All the pagers rendered correctly. But the pager are all stuck at page 1 no matter what page link I click. After a long trek through debugger, I found out the problem: Views sets the current page value using $view->query->pager->options['id'], before calling hook_view_pre_execute() and then render the pager after that hook. So it was using the pager id "0" that was set in the view. There appears to be no suitable hook to change the $view->query->pager->options['id'] before Views make use of it. But I found Views uses $view->display_handler->default_display->options['pager']['options']['id'] to initialize $view->query->pager->options['id']. So I use hook_views_pre_view() to alter that value and let Views do the rest.

The original patch uses this to test whether to change the pager id:

if (!empty($view->tag) && stristr($view->tag, 'node_gallery'))

but this match both "node_gallry_galleries" and "node_gallery_images". Only the second one should be true. Otherwise, the Galleries list page pagers is wrong.

If other views also need changing pager id, the add more to the if statement.

mattyoung’s picture

Status: Needs work » Needs review
StatusFileSize
new845 bytes

Use this patch, it's a little cleaner.

It's very easy to see this bug. Just go to /galleries. Without this patch, all the pagers look the same, all but one will be wrong.

scroogie’s picture

Mhm, interesting. My patch worked for me. What version of Views are you using? This needs some thorough testing. Does your patch also work if the pager options are overridden for a display?

mattyoung’s picture

I am on Views3 alpha3.

>Does your patch also work if the pager options are overridden for a display?
I did look for that but the pager id is not overridable. The overrided settings are in another field. But for the pager id, I don't see anyway to override through the views UI. If it can be overridden, then we can just alter that other field in the view object.

scroogie’s picture

Mhm, weird. Sorry, testing will take a bit longer. I cannot reproduce the original issue anymore. The pager is always there for me. Justin, do you see the issue?

*edit* To explain a bit, the code looks good, but this needs testing with Views 2.x.

mattyoung’s picture

>this needs testing with Views 2.x
Yes, just to be sure, I am using Views3 alpha3 and the original patch does not work. My patch works on Views3 but I didn't test on Views2 (not using it anymore).

scroogie’s picture

Status: Needs review » Needs work

Unfortunately your patch doesn't work with Views 2, so we have to check for the Views version. I hope one of the hooks can implement both ways.

justintime’s picture

Asking for some help from the Views crew - perhaps they know of a clean way to fix this in both versions: #1086524: Best way to avoid pager id collisions in views 2 and views 3?

justintime’s picture

Component: Code » Documentation
Priority: Major » Normal
Issue tags: +Needs documentation

Well, certainly not the answer I was looking for, but if Earl doesn't know how to fix it, I sure as hell don't think I'll come up with a way to.

We need to just document this as a known issue. The patches above may work for some, but they won't work for everyone, and therefore won't be committed.

Changing component to docs, priority down to normal, and adding a tag.

mattyoung’s picture

Status: Needs review » Needs work
StatusFileSize
new2.89 KB

justintime:

Ctools does views pager settings override. Since that's merlin's code, that should be the way. The code is in ctools/views_content/plugins/content_types/views.inc, around line 175-205. In order for this to work, the view object is needed. This means we cannot call views_embed_view() (see the comment in views_embed_view() for hints). This patch is tested with Views 3 "dev" version (don't use 3.0-alpha3, that's too old). If you test this on views2 and works, then this should be it.

There is this comment in node_gallery.module:

// @todo: we should be able to programmatically set some options on the view, such as number of images, imagefield_name, etc.

well this can now be done in _node_gallery_views_embed_view().

EDIT: there is an extra change in the patch:

-      $form['description']['#value'] = format_plural($count, 
+      $form['description']['#value'] = format_plural($count,

that's because the original line has a extra space at the end. I set my IDE to automatically trim trailing spaces.

mattyoung’s picture

Component: Documentation » Code
Priority: Normal » Major
Status: Needs work » Needs review
Issue tags: -Needs documentation

cross posted

mattyoung’s picture

Status: Needs work » Needs review

I just went over to #1086524: Best way to avoid pager id collisions in views 2 and views 3? and saw what merlin has to say.

>And there is no way to handle this the same way between 2 and 3

I don't know why he says that.

if (method_exists($view, 'init_pager')) {
  // this views 3, use pager plugin
}
else {
  // this must be views 2
  // do something else
}

This construct is used in ctools.

>there is simply no way to be aware of what other pager elements are in use on the page

This is true and cannot be overcome with the way drupal pager work as is. But we are not trying to fix this. We just want node_gallery pagers to play nice with themselves.

>Really, when doing this, you almost have to just not use paging

Unfortunately, this is probably the choice we may have to make. In that case, just turn off pager in _node_gallery_views_embed_view().

scroogie’s picture

Status: Needs review » Needs work

Well, I think merlin meant that we can't know if there are any other pagers on the site, which is true (it should be a drupal global implementation registering this). But in our case we just want to control our *own* instances.

I think the code in #13 is good, except that it apparently reverts the "image counting on deletion" patch. Matt, could you reroll? Could you also check if there are other calls to "views_embed_view" in the code?

mattyoung’s picture

Status: Needs work » Needs review

>it apparently reverts the "image counting on deletion" patch

How did that happen? The patch has two lines actual change and the rest is addition. I did a git clone right before I did the change.

Anyway, I'll re-checkout from git and do over later and see.

scroogie’s picture

Sorry, I made a mistake. It just replaces that line with the same line again. Diff playing tricks with me.

mattyoung’s picture

So the patch is okay, right?

>Could you also check if there are other calls to "views_embed_view" in the code?

There is only one other views_embed_view() call in node_gallery.page.inc, node_gallery_list_galleries(). But that uses the "node_gallery_gallery_summaries" view and the pager id is fine there. So there is no need to change that.

justintime’s picture

Hey guys, sorry I haven't had time to apply this. After a full week @ Drupalcon last week, I have a much-needed week's vacation with the wife next week. I might get the time next week to apply and test this, but it's doubtful. @scroogie, if you find the time to apply it and verify it's good, feel free to commit it.

scroogie’s picture

Status: Needs review » Fixed

The code was very well written. For Views 2 compatability, setting the display before the option was required, because the option is saved in the "current display".

Commited to 6.x-3.x.

Thanks mattyoung! Hope to see more contributions of you in the future. If you have any objections to the patch, please reopen.

Cheers
scroogie

Status: Fixed » Closed (fixed)

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