Limitstart is lost with SEF enabled causing pagination and cache problems

Started by Peter Pillen, January 15, 2013, 21:05:20 PM

Previous topic - Next topic

Peter Pillen

Joomla 2.5.8
Virtuemart 2.018a

I will try to explain the best I can. The problem is complicated.

problem
With the joomla core SEF enabled I experience problems with the pagination and because of that, also with the cache. Because the wrong page get cached with every navigational click. The problems vary from not being able to return to the first page or for example page 4 always showing page 1 from the cache.

observed problems
1. The core joomla sef url is inconsisent. Navigating through your products with the pagination (meaning << start previous 1 2 3 4 5 ... next end>>) you see (in my case) ?start=30 ... ?start=60 ... but returning to "1", you see ?limitstart=0. In includes/router.php I found that adapting the code @ line 408 and 448 makes the 1st page become ?start=0
<?php //line 408
if (($start $uri->getVar('start')) !== null) {
$uri->delVar('start');
$vars['limitstart'] = $start;
}
//and line 448
if (($limitstart $uri->getVar('limitstart')) !== null) {
$uri->setVar('start', (int) $limitstart);
$uri->delVar('limitstart');
}
?>


2. The pagination is handled different for each language. No idea why. In dutch (the default language) the ?start=0... ?start=30 ... ?start=60 and so on is performed. In french results,31-30...results,61-60... is used. But it is impossible to return to the first page.

3. In the file modules/mod_virtuemart_category/tmpl/default.php , current.php and all.php adding &limitstart=0 to the $caturl makes VM2 run like a charm with SEF disabled.
<?php 
$caturl 
JRoute::_('index.php?option=com_virtuemart&view=category&virtuemart_category_id='.$child->virtuemart_category_id.'&limitstart=0')
?>


But with sef enabled, this limitstart is erased and there is no way I can find to add ?start=0 to the links in the module menu.

So two questions to fix this.
1. How can I add ?start=0 to the category links in the VM menu module?
or
2. How can I force the limitstart=0 into the userstate when clicking on the links in the VM menu module?

I currently need to make a choice... SEF urls or cache... can't have both apparantly.

jjk

Not shure if this is a problem with the VM code, because it works on my site (Will send you a PM with a link where you can see it working). Did you configure the limits in your categories and subcategories and do you have identical limits in your foreign language categories? As far as I can see (just googled your name to locate your website), the pagination is working correctly in your manufacturers view.
Two differences compared to my own shop are that I disabled Joomla cache (to avoid problems with the cart) and at present I don't use subcategories.

BTW - the Firefox error console says:
Timestamp: 15.01.2013 21:37:18
Error: Image corrupt or truncated: ...net/templates/explore/images/slideshow/bunker.jpg
Source File: ...net/templates/explore/images/slideshow/bunker.jpg
Line: 0
Non-English Shops: Are your language files up to date?
http://virtuemart.net/community/translations

Peter Pillen

thanks for the heads up about the file error, but that doens't affect the browse experience for my visitors.

Does anyone know why the start and limitstart is different per language? On the site from jjk, this is not the case, so probably I'm doing something wrong. The setting for the categories are identical.

jjk

One thing I noticed on my site is that the pagination link display is different when I click a page from the categories menu and when I click a page after using the list limit dropdown box.

For example, in the first case the link to the first category page ends with ...domain/en/category-name?limitstart=0
After selecting a pagination sequence from the list limit box, the link to the first category page ends with ...domain/en/category-name/results,1-16?language=en-GB

PS: Looks to me like you forgot to set the language tags in your dutch and french menus. I think on a multilingual site EVERY published menu item should have a language tag.
Non-English Shops: Are your language files up to date?
http://virtuemart.net/community/translations

Peter Pillen

I found that the endstring for my url is created in components/com_virtuemart/router.php @ line 115

<?php if ($start !== null &&  $limitstart!== null ) {
//$segments[] = $helper->lang('results') .',1-'.$start ;
} else if ( $start>0 ) {
// using general limit if $limit is not set
if ($limit === null) $limit= vmrouterHelper::$limit ;

$segments[] = $helper->lang('results') .','. ($start+1).'-'.($start+$limit);
} else if ($limit !== null && $limit != vmrouterHelper::$limit ) $segments[] = $helper->lang('results') .',1-'.$limit ;//limit change

return $segments;
?>


i'll test some more, but could there be a reason why the sef version of this is translated in the default language and not in the other languages?

Peter Pillen

I got tired looking for the answer/solution, but I found a dirty workaround.

* settings : sef and url rewrite enabled + VM seo activated
* checked the language settings for all my vm menu and those are OK

I did two changes.

includes/router.php --> added "!==NULL" to make the sef url consitent. ?limitstart=0 has now become ?start=0

<?php 
//line 408
           
if (($start $uri->getVar('start')) !== null) {

//and line 448
   if (($limitstart $uri->getVar('limitstart')) !== null) {
?>


components/com_virtuemart/router.php --> code change to force VM to use the zero value for limitstart and start. So...
<?php if ($start !== null &&  $limitstart!== null ) {
//$segments[] = $helper->lang('results') .',1-'.$start ;
} else if ( $start>0 ) {
// using general limit if $limit is not set
if ($limit === null) $limit= vmrouterHelper::$limit ;

$segments[] = $helper->lang('results') .','. ($start+1).'-'.($start+$limit);
} else if ($limit !== null && $limit != vmrouterHelper::$limit ) $segments[] = $helper->lang('results') .',1-'.$limit ;//limit change

return $segments;
?>

has become
<?php
if ($start !== null &&  $limitstart!== null ) {
//$segments[] = $helper->lang('results') .',1-'.$start ;
} else if ( $start>) {
$segments[] = '?start='.($start);
} else if ( $start==null && $limitstart==null){
$segments[] = '?start=0';
} else if ($limit !== null && $limit != vmrouterHelper::$limit $segments[] = $helper->lang('results') .',1-'.$limit ;//limit change

return $segments;
?>


Now the navigation works correctly, but with somewhat ugly url endings. But at least when you're on page 5 of a category and clicking on the same category in the VM menu, you go back to page 1. This solves the caching problem.

It remains a strange fact that in the pagination, the links for the first page is built in al different ways

www.site.com/category --> in the menu
www.site.com/category?limitstart=0 --> in the pagination
www.site.com/category?start=30 --> for the second page of that category

then clicking on the www.site.com/category with the vm menu, shows you page 2 but with www.site.com/category in the url.

Peter Pillen

mmmm... it did not solve the caching problem completly. I still found some page where the start=x is cached incorrect.

Peter Pillen


franzpeter

I do not think that it is a cache problem. The problem is, that the previous/next pagination has a configuration bug. VM 2 does allow to change the default sort order for products in the backend. But the product navigation only works if the default sort order for products is set to product name. I see that problem too if products in the same category have the same name, say you name five products with '2013' but those products may have different sku.
VM 2 has a nasty bug there. You can define the product order setting in the backend configuration, but the previous/next thing only works if the default product sort order is set to product name. As soon as you set the default product order setting to something else like sku or product id, the forward/previous navigation disappears in the frontend. So there is obviously a VM 2 bug between the configuration->Product Order Setting: Default product sort order and the previous/next navigation.

Peter Pillen

@franzpeter... I also noticed that problem before. I had a fix made for myself (see topic https://forum.virtuemart.net/index.php?topic=101208.msg371632#msg371632) and I also pointed out the problem. Milbo had a fix for it, but testing it in 2.0.18a, it is still not completely OK. But the productnavigation (productdetail level) is a different issue than the limitstart (category view level).

franzpeter

@P2 Peter,

the category navigation has the same problem as the product navigation. As you did post in your other message, the BE configuration does not work well together with the FE view. There are no 'case' implementations, not for product details and not for category list view. You can configure in the BE whatever you want, it has no relevance for the pagination (that what is shown by using the links for previous or next). So if it is true that for now only the slug is used, which may even work against the BE configuration for ordering products and categories, it cannot work as expected.

I hope that it produces not the same problems in category product list view as in product details view that if you select another way in BE to order something that the pagination links disappear completely.

Peter Pillen

I think I solved it. It only has one drawback ... you can't use the $limit change anymore, but because I don't use it in my frontend, it does not affect me. But... I can't guarantee this will work for everybody  :-\

First of all ... the caching problem. It seems that Joomla 2.5.8 has a bug that is not yet fixed, but will be in a next version. Joomla cache does not create an unique id for each cache file. So it is possible that two different urls can point to the same cached page. If found this fix on the joomla forum for file: \modificaties\libraries\joomla\cache\controller\view.php  @bottom of the file. It adds JURI::current to the id.

<?php protected function _makeId(&$view, $method)
{
//return md5(serialize(array(JCache::makeId(), get_class($view), $method)));
return md5(serialize(array(JCache::makeId(), get_class($view), $method, JURI::current())));
}
?>


Next... joomla and virtuemart have their own pagination system. This causes problems because &limitstart=x is handled by joomla as well as virtuemart and the url output is different. Resulting in two possible urls for the same content, depending whether you enter the virtuemart category view from a virtuemart menu module or a joomla menu module. Solution ... delete the lines that handle the $start and $limitstart from the file \components\com_virtuemart\router.php so that virtuemart uses the standard joomla pagination and is consistent for each language.

comment out @line 100
<?php
// Joomla replace before route limitstart by start but without SEF this is start !
/*
if ( isset($query['limitstart'] ) ) {
$limitstart = $query['limitstart'] ;
unset($query['limitstart']);
}
if ( isset($query['start'] ) ) {
$start = $query['start'] ;
unset($query['start']);
}
if ( isset($query['limit'] ) ) {
$limit = $query['limit'] ;
unset($query['limit']);
}
if ($start !== null &&  $limitstart!== null ) {
//$segments[] = $helper->lang('results') .',1-'.$start ;
} else if ( $start>0 ) {
// using general limit if $limit is not set
if ($limit === null) $limit= vmrouterHelper::$limit ;
$segments[] = $helper->lang('results') .','. ($start+1).'-'.($start+$limit);
} else if ( $start==null && $limitstart==null){
$limit= vmrouterHelper::$limit ;
$segments[] = $helper->lang('results') .','. ($start+1).'-'.($start+$limit);
} else if ($limit !== null && $limit != vmrouterHelper::$limit ) $segments[] = $helper->lang('results') .',1-'.$limit ;//limit change
*/
?>


and @line 325
<?php
/*
if ( $helper->compareKey($splitted[0] ,'results')){
// array_shift($segments);
array_pop($segments);
$results = explode('-',$splitted[1],2);
//Pagination has changed, removed the -1 note by Max Milbers NOTE: Works on j1.5, but NOT j1.7
// limitstart is swapped by joomla to start ! See includes/route.php
if ($start = $results[0]-1) {
$vars['limitstart'] = $start;
$vars['start'] = $start;
}else{
$vars['limitstart'] = 0 ;
$vars['start'] = 0 ;
$vars['limit'] = $results[1]-$results[0]+1;
}

} else {
//$vars['limitstart'] = 0 ;
//$vars['limit'] = vmrouterHelper::$limit;
}
*/
?>


Next... url consitency ... when using pagination <<start previous 1 2 3 4 next end>>, if you're on page 2, the url says ?start=30 if you have sef enabled. But going back to the first page, gives you ?limitstart=0. To make joomla use ?start=0, which is consistent with the rest of your pagination, change the file includes\router.php @ lines 412 and 445 and add the !==NULL operator. I also added a check for when an empty &limitstart= is passed, that the value 0 is added for cache purpose.

<?php
//if ($start = $uri->getVar('start')) {
if (($start $uri->getVar('start')) !== NULL) {

//if ($limitstart = $uri->getVar('limitstart')) {
if (($limitstart $uri->getVar('limitstart')) !== NULL) {
                                
//also added a check when limitstart is empty, that a zero value is added
if ($limitstart == NULL){
$uri->setVar('start'0);
}else{
$uri->setVar('start', (int) $limitstart);
}
$uri->delVar('limitstart');
}
?>


And final ... just to be safe ... adding &limitstart=0 to your non sef urls for joomla menus pointing to virtuemart categories. Using phpmyadmin -> go to menu table and edit the field "link" (this can't be edited from administrator backend). Just add &limitstart=0 to the end of the url, example index.php?option=com_virtuemart&view=category&virtuemart_category_id=2&limitstart=0. By doing this you always go back to the first results of a category view when clicking on a joomla menu item that links to a virtuemart category.

This still needs some testing because i'm running this code just for one day in this way and I'm not sure if this causes problems elsewhere. I'm now running standard joomla conservative caching, sef and url rewrite enabled and using Jotcache to exclude dynamic content like the cart and others.

rosen4o