Jump to content

[SOLVED] Pagination links render but do not work.


FireWire
 Share

Recommended Posts

Hey everyone,

I'm pretty experienced with pagination and haven't seen this before. I have my pages pulled using $pages->find, which is working fine however using renderPager() generates pagination where the links do not work. Here are some details.

  • All templates needing pagination have pagination enabled in the admin.
  • URL Segments are not enabled.
  • Clicking on the "Next" or numbered links merely reloads the current page.
  • The link href values are properly being output with the urls being /page2, /page3, /page4, etc.
  • Manually entering the paginated urls has the same effect of reloading the current page with no new content.
  • Pages are being returned from the ->find function properly and with the proper limit.

A few other details:

  • ProcessWire v3.0.98
  • Multi-language is enabled, 2 languages implemented.
  • Pagination does not work on either language
  • Have very few modules installed (few enough to list), none of which I could see interfering:
    • ProFields, ProDrafts, ListerPro, DB Backups, Cronjob DB Backup, Upgrades, Upgrade Checker, Force Password Change, Markup Sitemap XML

I'm stumped. For the sake of being overly-thorough, here's the code:

<?php
  $articleTemplates = [
    'template_news_article',
    'template_news_video',
    'template_news_press_release'
  ];

  $searchParams = [
    'template=' . implode('|', $articleTemplates),
    'sort=-published',
    'limit=' . $pages->get('template=template_news')->list_count
  ];

  $articles = $pages->find(implode(',', $searchParams));
  
  echo $articles->renderPager();
?>

 

Link to comment
Share on other sites

So I figured out the source of the issue. I wrote some code that detects a user's preferred language either from their browser language setting, or from a cookie that is created when they have visited and chose a language last time.

If a preferred language detected and the current page URL does not match it, it will redirect to the same page but in the proper language.

My problem is finding a way to get the URL that includes the pagination to compare. Right now my idea is to use $input->pageNum to build the URL myself... is there a way to get the URL including the page number?

Lesson learned...

Link to comment
Share on other sites

1 hour ago, usualCommission said:

is there a way to get the URL including the page number?

I'm not 100% I understand your question. Maybe you can try combination of $input->pageNum and $pager->getURL()? E.g.:

$articles->getURL($input->pageNum());

Note the caveat in the $pager->getURL() method at the above link.

Could this topic be of interest?

 

 

Edited by kongondo
Link to comment
Share on other sites

Yeah, I'm not explaining my situation well enough and it's becoming a little more complex.

I'm working on abstracting localization to a class where one of the methods is used to redirect the user to their preferred language. That preferred language is either the language preference they have set in their browser, or a language cookie that was set last time they visited and selected a language via a select dropdown in the nav. That said, since the method is run on page load it will not have any access to specific pagination instances because they don't exist yet.

I read the link above and didn't see a solution that covers all of the bases and the module reference in a link to another post is no longer maintained, so I am going to write a custom implementation.

Here's my solution:

  • Language detection will be tied to a unique session variable.
  • On page load, the script checks for that session variable, if it exists- it exits because the language has been checked/redirected if necessary on ingress already.
  • If no language session variable exists, then compare the destination URL against the URL of that page for their preferred language.
  • If the URLs do not match then build a new URL
  • The destination URL is checked for page numbering using $input->pageNum(), if  > 1 then create a URL string for that. Any GET variables are extracted and rebuilt into a string- this preserves any possible incoming variables like UTM trackers.
  • Get localized URL for user's preferred language, re-add page number, re-add any GET variables that existed.
  • Set unique language session variable, then properly redirect to the localized page using the build URL.

I kind of wish that there was a built in method that could wrap most of this up and preserve URL details while redirecting to a given translated page, but this should work and also only redirect once.

I may be over-complicating this but it's what I've got. I really appreciate your help!

Link to comment
Share on other sites

Something like this would be the easiest way, I can think of, to do what you are doing. Redirect to a another language, including urlSegments, Pagenumber and optional QueryStrings;

if($user->language->isDefault) {
	$user->language = $languages->get("de");
	$session->redirect($input->url($withQueryString = true));
}

 

  • Like 2
Link to comment
Share on other sites

That sets the user language properly but getting the $input->url(true) still gets the non-localized version of the URL so it doesn't redirect to the translated page. It loops and fails the redirect.

Also the language move has been a little rough because using the code below seems to lead to a possible solution but is where I was hitting the paging/GET issues.

$languages->setLanguage(-lang str here-); // Also sets the language as a $user->language assignment does
$page->localHttpUrl($user->language); // Returns the proper localized URL, but does not include pagination or GET vars

I've seen many posts in the forums about redirection to a language and all of them use $page->localUrl($user->langauge) and none consider GET vars. Multi-language documentation says that the $page->localUrl() will automatically adjust to pagination but I haven't seen it. Would still have to manually build GET vars.

 

Link to comment
Share on other sites

Added that to a comparison and that did the trick! Here's the method after adding your trick:

private function doInitLocalization() {
  $page = wire('page');
  $user = wire('user');
  $input = wire('input');

  // Get/set user language from either browser or cookie
  $user->language = $this->getLangFromCookie() ?: $this->getValidBrowserPrefLang();

  $urlSuffix = str_replace($page->url, '', $input->url(true));
  $userUrl = $page->localUrl($user->language) . $urlSuffix;

  if ($_SERVER['REQUEST_URI'] !== $userUrl) {
    header("Location: {$userUrl}");
  }
}

getLangFromCookie() checks if the user has visited previously and selected a language from a dropdown.
getValidBrowserPrefLang() gets the language pref sent by the browser, if it exists as a language in the CMS, returns the value.

By setting the language for the user this checks against what the browser request asked for/server is delivering vs. what the CMS knows it should be delivering. If they differ, then redirect.

This is executed in _init.php so any point of ingress is checked for url vs. preference.

Thanks @kongondo for introducing me to $input->url and the good idea for direction.
Thanks @Soma for concluding my head->desk marathon. Your solution is the simple one I couldn't see.

 

Link to comment
Share on other sites

When you change the $user->language, all following API returns stuff in that language also, the $page->url or $input->url. No need to do str_eplace on something already the same.

So if $this.>getLangFromCookie does return the language object then you can change it to this.

private function doInitLocalization() {
  $user = wire('user');
  $input = wire('input');

  // Get/set user language from either browser or cookie
  $language = $this->getLangFromCookie() ?: $this->getValidBrowserPrefLang();
  if($language !== $user->language) {
    $user->language = $language;
    $this->wire("session")->redirect($input->url(true));
  }
}

 

  • Like 1
Link to comment
Share on other sites

Good to know.

$this->getLangFromCookie() returns a string and is shared by other methods in the same/other classes. I could probably refactor it to work directly with the language object, but I'll have to come back to that sometime. Appreciate that info.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...