News:

Looking for documentation? Take a look on our wiki

Main Menu

The joy of SEF

Started by doorknob, July 29, 2008, 04:07:13 AM

Previous topic - Next topic

doorknob

I've been busy, of late, trying to introduce my development site to SEF (I looked at the options and eventually settled on sh404sef). The purpose of this post is to share my findings and perhaps help resolve some of the issues. I've got sh404sef working quite well now but I had to fix a couple of problems in that component and quite a few more in VM.

The problems fixed in sh404sef relate to an incompatibility between the way that VM handles the browse sequence and the number of items per page and the way that sh404sef expects them to be handled. VM starts with defaults for both settings but modifies the default during a session, if appropriate, to reflect the way the browse page is used. The values are stored in session variables. sh404sef anticipates the use of defaults but doesn't allow for the possibility that they may change during a session. I have posted a couple of proposed fixes on their web site.

I'll now describe the changes made to VM to accommodate sh404sef but please note that my own site has a number of customisations and so the code may need some tweeking for vanilla VM.

html/shop.browse.php:
The contruction of $search_string was changed to include all fields but only when populated (lines 171 to 184)
if ( $num_rows > 1 && @$_REQUEST['output'] != "pdf") {
if ( $num_rows > $limit  || $num_rows > 5 ) {
$search_string = $mm_action_url."index.php?option=com_virtuemart&page=$modulename.browse&category_id=$category_id&keyword=".urlencode( $keyword )."&manufacturer_id=$manufacturer_id&Itemid=$Itemid";
$search_string .= !empty($orderby) ? "&orderby=".urlencode($orderby) : "";

if (!empty($keyword1)) {
$search_string.="&keyword1=".urlencode($keyword1);
$search_string.="&search_category=$search_category";
$search_string.="&search_limiter=$search_limiter";
if (!empty($keyword2)) {
$search_string.="&keyword2=".urlencode($keyword2);
$search_string.="&search_op=$search_op";
}
}

was replaced with:
if ( $num_rows > 1 && @$_REQUEST['output'] != "pdf") {
if ( $num_rows > 5 ) { // simplified logic
$search_string = $mm_action_url."index.php?option=com_virtuemart&Itemid=$Itemid&category_id=$category_id&page=$modulename.browse";
$search_string .= empty($manufacturer_id) ? '' : "&manufacturer_id=$manufacturer_id";
//$search_string .= !empty($orderby) ? "&orderby=".urlencode($orderby) : ""; // not needed - uses session variable
$search_string .= empty($keyword) ? '' : '&keyword='.urlencode( $keyword );
if (!empty($keyword1)) {
$search_string.="&keyword1=".urlencode($keyword1);
$search_string.="&search_category=".urlencode($search_category);
$search_string.="&search_limiter=$search_limiter";
if (!empty($keyword2)) {
$search_string.="&keyword2=".urlencode($keyword2);
$search_string.="&search_op=".urlencode($search_op);
}
}

classes/pageNavigation.class.php
The navigation links were updated to include the value of $limit so that the sef friendly urls are created
lines 129 & 130
        $html .= "\n<li><a href=\"".vmRoute($link.'&limitstart=0')."\" class=\"pagenav\" title=\"".$VM_LANG->_('PN_START')."\">&laquo;&laquo; ".$VM_LANG->_('PN_START')."</a></li>";
        $html .= "\n<li><a href=\"".vmRoute($link.'&limitstart='.$page)."\" class=\"pagenav\" title=\"".$VM_LANG->_('PN_PREVIOUS')."\">&laquo; ".$VM_LANG->_('PN_PREVIOUS')."</a></li>";

replaced with
        $html .= "\n<li><a href=\"".vmRoute($link.'&limitstart=0&limit='.$this->limit')."\" class=\"pagenav\" title=\"".$VM_LANG->_('PN_START')."\">&laquo;&laquo; ".$VM_LANG->_('PN_START')."</a></li>";
        $html .= "\n<li><a href=\"".vmRoute($link.'&limitstart='.$page.'&limit='.$this->limit)."\" class=\"pagenav\" title=\"".$VM_LANG->_('PN_PREVIOUS')."\">&laquo; ".$VM_LANG->_('PN_PREVIOUS')."</a></li>";

line 157 & 158
        $html .= "\n<li><a href=\"".vmRoute($link.'&limitstart='.$page)."\" class=\"pagenav\" title=\"".$VM_LANG->_('PN_NEXT')."\"> ".$VM_LANG->_('PN_NEXT')." &raquo;</a></li>";
        $html .= "\n<li><a href=\"".vmRoute($link.'&limitstart='.$end_page)."\" class=\"pagenav\" title=\"".$VM_LANG->_('PN_END')."\"> ".$VM_LANG->_('PN_END')." &raquo;&raquo;</a></li>";

replaced with
        $html .= "\n<li><a href=\"".vmRoute($link.'&limitstart='.$page.'&limit='.$this->limit)."\" class=\"pagenav\" title=\"".$VM_LANG->_('PN_NEXT')."\"> ".$VM_LANG->_('PN_NEXT')." &raquo;</a></li>";
        $html .= "\n<li><a href=\"".vmRoute($link.'&limitstart='.$end_page.'&limit='.$this->limit)."\" class=\"pagenav\" title=\"".$VM_LANG->_('PN_END')."\"> ".$VM_LANG->_('PN_END')." &raquo;&raquo;</a></li>";


html/shop.search.php
The form was changed to use the 'get' method rather than 'post' so that the results page can be bookmarked. The second change was to introduce a new hidden field for category_id so that if a category is selected to restrict the search, the sef url will be correct. The hidden field is populated by some javascript. The JS is more sophisticated than strictly needed because it doesn't just copy the value of search_category but strips off the first value from a comma delimited string (works fine with a single value)
I replaced line 37
<form action="<?php echo URL ?>index.php" method="post" name="adv_search">

with
<form action="<?php echo URL ?>index.php" method="get" name="adv_search" onSubmit="var p=new RegExp('(.*?),',['i']);var m=p.exec(this.search_category.value);if(m.length>0){this.category_id.value=m[1];}return true;">
<input type="hidden" name="category_id" value="" />

Finally, the forms embedded in the browse navigation now look like this. Please note that I have left in some markup that is specific to my site, but I'm sure that the principles should be clear.
This is the 'order by' drop down list and the 'ascending/descending' toggle
<form action="" method="get" name="order">
<?php
if( !empty( 
$VM_BROWSE_ORDERBY_FIELDS )) { ?>

<div class="browse-bar-orderby">
<?php
echo $this->fetch'browse/includes/browse_orderbyfields.tpl.php');

// This is the toggle button for Descending / Ascending Order
?>
<a href="<?php echo vmRoute$search_string.'&limitstart='.$pagenav->limitstart.'&limit='.$pagenav->limit.'&DescOrderBy='.$asc_desc[1] ) ?>" class="browse-bar-<?php echo strtolower($asc_desc[0]) ?>" title="<?php echo 'Click for '.$VM_LANG->_('PHPSHOP_PARAMETER_SEARCH_'.$asc_desc[1].'ENDING_ORDER'?>">&nbsp;</a><?php
}
?>

</div>
</form>

and the limit box:
<form action="" method="get" name="limit1">
<div class="browse-bar-limit">
<?php
if( $show_limitbox ) {
$pagenav->writeLimitBox$search_string );
?>
Items per Page
<?php
}
?>

</div>
</form>

No javascript
No submit buttons
No hidden fields
All links are pre-calculated sef friendly urls
BTW the images for the asc/desc toggle are backgrounds provided in the css file

Regards
Phil

korb

Hi,
Anyone tried this fix?
@Darknoob please tell us, this "tiny" fix is ok with J 1.5.6 and VM 1.1.2? and ofcourse sh404SEF.
Danny

korb

#2
sorry to inform but:

Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING in D:\xampp\htdocs\joomla\administrator\components\com_virtuemart\classes\pageNavigation.class.php on line 129



And one more thing: where do you fill the last codes from your post up here?
I mean for limitbox and asc/desc toogle.
Please advise

doorknob

Hi Danny,

I'm using J1.5.3 (still localhost) and vm nightly from 28/7 (at the time this post was made). I updated my development system to 1.5.6 when it was first released but started to get errors because the encoding method was being omitted from the pages so I reverted to the old version. I plan to rebuild from scratch before putting it live (soon, I hope!)

The value for ascending/descending comes from the $asc_desc array, as at present
The values for limit and limitstart come from the $pagenav object

For the sef to work fully, you will need to patch the sh404sef software with a couple of changes that I posted to their forum (they have assumed that the initial default value for 'orderby' and 'limit' remain the defaults throughout a session. Whenever a value equal to the initial default is detected, they delete that value. VM actually applies the most recently specified value as the default. That means that with sh404sef activated, it is not possible to reselect the original sort order or number of items per page because they get deleted before the url is submitted).

Actually, since this post was made, I have now changed the orderby drop down on my system so that it uses the same technique as the limitbox drop down. In brief:
$sef_url = vmRoute( $search_string.'&limitstart='.$pagenav->limitstart.'&limit='.$pagenav->limit );

to prepare the basic user friendly url
<select class="inputbox" name="orderby" onchange="location.href=this.value">

so that the url associated with the selected item will be activated
and then each entry in the drop down updated in a similar way to this:
        <option value="<?php echo $sef_url '&amp;orderby=product_list' ?>"<?php echo $orderby=="product_list" " selected=\"selected\">" ">"; echo $VM_LANG->_('PHPSHOP_DEFAULT'?></option>


I'm not sure why you should get the error you did. It works really well for me, although, to be fair, I have made more changes than those posted. I considered that those changes would stand alone as a useful improvement. I have changed all of my search facilities (simple, advanced and product type (implemented as a module)) to use 'get' throughout. This works really well and, of course, allows the visitor to bookmark all search results. The only reservation I have is that the 'search by product type parameter' depends on a js routine to reformat the data so that it can be passed to php as an array (it also discards unused parameters to minimise the length of the url but that is not essential). Unfortunately, there is no fallback for visitors that do not permit js. Do you have any ideas how I could send the contents of a 'multiple' select box to php using 'get' without using js? Everyting I have tried just results in a string with the value 'Array' being sent. All the js does is take all of the values and string them together into a single value like "param1[]=value1&param1[]=value2"

Let me know if I can help any further. I could send you my programs if it would help.
Regards
Phil

korb

#4
Hi Phil,
Thanks for reply and please lets fix this pageNavigation.class.php issue. I am no power coder to understand you :)

I found a fix that works with J 1.5.6 VM 1.1.2 and sh404SEF it works! with pagination. The only problem is explaine din this tracker

If I try your the codes in your previous post, where should they go? I'm desperate by now, so ask you to tell me at least this.

Regarding default orderby I know and I fixed too.

So first read this topic here. The only problem with this fix is that it includes non integer value for limit and stops sh404SEF to route, everything is explained in the tracker.
Please help fixing this minor minor issue.
Danny

doorknob

Hi Danny,
Let me read the post and think about the issue and then I'll let you know what I make of it. I have made a few changes in my system to include the limit and startlimit values in a few places (e.g. advanced search) to improve sh404sef's chances at making a url that I would like and maybe I have avoided that problem without realising it. I have certainly not seen a problem with a non-integer value. One for tomorrow.
Regards
Phil

korb

Hi Phil,
Please try to make it work with a clean Joomla 1.5.6 and VM 1.1.2 installation.
Thanks

korb

Quote from: doorknob on August 28, 2008, 22:02:12 PM

Actually, since this post was made, I have now changed the orderby drop down on my system so that it uses the same technique as the limitbox drop down. In brief:
$sef_url = vmRoute( $search_string.'&limitstart='.$pagenav->limitstart.'&limit='.$pagenav->limit );

to prepare the basic user friendly url
<select class="inputbox" name="orderby" onchange="location.href=this.value">

so that the url associated with the selected item will be activated
and then each entry in the drop down updated in a similar way to this:
        <option value="<?php echo $sef_url '&amp;orderby=product_list' ?>"<?php echo $orderby=="product_list" " selected=\"selected\">" ">"; echo $VM_LANG->_('PHPSHOP_DEFAULT'?></option>



Where all this code supose to go?
Danny

korb


doorknob

Danny,
I haven't made any progress with the corrupted limit value (can't replicate the problem) but I'm curious to know whether JavaScript was enabled in the browser. This is because VM uses different techniques for submitting the form.
Regards
Phil

korb

#10
Hello Phil,
Please tell me, what exactly you modified in pageNavigation.class.php so you don't have this non integer value? Else, I have to remind you, this happends when browsing multipage product category (at least 20-30 products with a limit of 5-10-15) only when you change the orderby: price, latest, product name AND ASC/DESC. If you don't change anything and just browse pages, you cannot see the issue.

I know that Soeren already did some changes to the code according to my specifications in this traker, and because VM 1.1.3 is very close to be released, I wish you could spend some little more time for this issue and help fix it, please post commments here in this traker and see source core differences.

Please reply,
Thank you


UPDATE: VM 1.1.x Nightly Build and VM 2.x branch still have this issue with limit value on changing orderby.

korb

#11
Limit value is fixed, TESTED WITH BUILD 1520, and a fresh db.
Your fix works perfect.
Thank you Phil, a million

The only thing left now is that asc_desc is not remembered on other pages, it seem to redirect to first page.

bpresent

Quote from: doorknob on August 28, 2008, 22:02:12 PM
Do you have any ideas how I could send the contents of a 'multiple' select box to php using 'get' without using js? Everyting I have tried just results in a string with the value 'Array' being sent.

I am having this same problem. Did you ever work out how to get around it?

If I switch off sh404sef I get the real array (as opposed to &foo=array), if I switch on sh404sef but switch off VM I also get the real array.

I assume therefore that it has something to do with the VM extension for sh404sef but I'm by no means a php coder so I have no idea how to fix it properly.

I did get around it with a hack to components/com_sef/sef.php (hardly ideal) whereby I completely bypass sef for this page - I can do this because I do not need sef on this page anyway.

Sam.
My first Joomla site and VirtueMart catalog http://www.minilps.net

doorknob

Yes.
It is caused by a bug in sh404sef. For a solution, see my post on their forum
Good luck
Phil

korb

Quote
Finally, the forms embedded in the browse navigation now look like this. Please note that I have left in some markup that is specific to my site, but I'm sure that the principles should be clear.
This is the 'order by' drop down list and the 'ascending/descending' toggle
Code:

<form action="" method="get" name="order">
   <?php
   if( !empty( $VM_BROWSE_ORDERBY_FIELDS )) { ?>
      <div class="browse-bar-orderby">
         <?php
         echo $this->fetch( 'browse/includes/browse_orderbyfields.tpl.php');

         // This is the toggle button for Descending / Ascending Order
         ?><a href="<?php echo vmRoute( $search_string.'&limitstart='.$pagenav->limitstart.'&limit='.$pagenav->limit.'&DescOrderBy='.$asc_desc[1] ) ?>" class="browse-bar-<?php echo strtolower($asc_desc[0]) ?>" title="<?php echo 'Click for '.$VM_LANG->_('PHPSHOP_PARAMETER_SEARCH_'.$asc_desc[1].'ENDING_ORDER') ?>">&nbsp;</a><?php
   }
   ?>
   </div>
</form>

and the limit box:
Code:

<form action="" method="get" name="limit1">
   <div class="browse-bar-limit">
      <?php
      if( $show_limitbox ) {
         $pagenav->writeLimitBox( $search_string );
         ?>Items per Page
      <?php
      }
      ?>
   </div>
</form>

ok I got that, I had to modify browse_orderbyfom.tpl.php to include your fix, and the results are excelent! no javascript, perfect URLs.

I think I would like to modify the parameter search to work same way: no javascript and no submit/change/reset buttons.

Can you help me with this?
Tanks a million,
Danny