Hi, after a little debugging in the VM 2.6.10 code I found several bugs in the Terms Of Service mechanism.
First of all, I'm attaching a zip with patched files and a patch file to review the changes.
After analysing the TOS mechanism, I think no user may get registered without accepting TOS, because the agreed user field is set as a core field and can't be edited (ie: you can't set the required state for it). Until a config option like "Must agree to TOS at registration" gets implemented, agreed must be required! at registration.
So first, the "I agree to the Terms of Service" registration field should get a star indicating it's required!
administrator/components/com_virtuemart/models/userfields.php function getCoreFields line 233, agreed should be removed from the array.
Change from this
static function getCoreFields(){
return array( 'name','username', 'email', 'password', 'password2' , 'agreed','language');
}
to this...
static function getCoreFields(){
return array( 'name','username', 'email', 'password', 'password2', 'language');
}
And the agreed form field should be marked as required in its HTML code (form field should be evaluated for "required" mark)
administrator/components/com_virtuemart/models/userfields.php function getUserFieldsFilled line 873
Change from this
case 'agreed':
$_return['fields'][$_fld->name]['formcode'] = '<input type="checkbox" name="'
. $_prefix.$_fld->name . '" id="' . $_prefix.$_fld->name . '_field" value="1" '
. ($_return['fields'][$_fld->name]['value'] ? 'checked="checked"' : '') .'/>';
break;
to this...
case 'agreed':
$_return['fields'][$_fld->name]['formcode'] = '<input type="checkbox" name="'
. $_prefix.$_fld->name . '" id="' . $_prefix.$_fld->name . '_field" value="1" '
. ($_return['fields'][$_fld->name]['value'] ? 'checked="checked"' : '')
. ($_fld->required ? ' class="required"' : '') . ' />';
break;
Despite agreed form field being marked as required, it needs to get validated at saveData to check if no 'agreed' post variable is sent, that's the case of forced user registration using some kind of method to avoid the form javascript validation
components/com_virtuemart/controllers/user.php funciton saveData line 216
Add theese lines
if(empty($data['agreed'])) {
$msg = JText::_('COM_VIRTUEMART_USER_FORM_BILLTO_TOS_NO');
vmInfo($msg);
return $this->redirect(JRoute::_('index.php?option=com_virtuemart&view=user&task=editaddresscheckout&addrtype=BT',$this->useXHTML,$this->useSSL), $msg);
}
At checkout, the config option "Must agree to Terms of Service on EVERY ORDER?" is not taken into account. Also, if you disable that option, the Agree to TOS check input is still displayed in the view and thats's not right. For that to work properly, theese are the changes that need to be done
administrator/components/com_virtuemart/models/userfields.php function getUserfield line 187 name parameter overrided because of bad logic (IE: agreed gets allways "required" = 0)
Change from this
if (empty($this->_data)) {
$this->_data = $this->getTable('userfields');
if($name !==0){
$this->_data->load($id, $name);
}
$this->_data->load($id);
}
To this...
if (empty($this->_data)) {
$this->_data = $this->getTable('userfields');
if($name !==0){
$this->_data->load($id, $name);
} else {
$this->_data->load($id);
}
}
Config Parameter agree_to_tos_onorder (Must agree to Terms of Service on EVERY ORDER?) should be evaluated here, because if it's turned on in config by VM administrator, it doesn't matter if the user agreed to TOS, he must agree on every order because of that VM config setting.
components/com_virtuemart/helpers/cart.php function saveAddressInCart line 1255
Change from this
if(!empty($data['agreed'])){
$this->tosAccepted = $data['agreed'];
}
To this...
if(!empty($data['agreed']) && !VmConfig::get('agree_to_tos_onorder',0)){
$this->tosAccepted = $data['agreed'];
}
Terms Of Service Checkbox should be visible in cart only if "Must agree to Terms of Service on EVERY ORDER?" is checked in VM configuration. For this to happen, the string COM_VIRTUEMART_CART_TOS_READ_AND_ACCEPTED should be splitted into two strings just in case the VM administrator wants to show TOS at cart and not require TOS agreement on every order. Theese are the new strings that should be placed in language/en-GB/en-GB.com_virtuemart.ini
COM_VIRTUEMART_CART_TOS_READ="Click here to read terms of service"
COM_VIRTUEMART_CART_TOS_ACCEPT="and check the box to accept them"
The cart view should be changed too
components/com_virtuemart/views/cart/tmpl/default.php arround line 182
Change from this
if ($userFieldsModel->getIfRequired ('agreed')) {
if (!class_exists ('VmHtml')) {
require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'html.php');
}
echo VmHtml::checkbox ('tosAccepted', $this->cart->tosAccepted, 1, 0, 'class="terms-of-service"');
if (VmConfig::get ('oncheckout_show_legal_info', 1)) {
?>
<div class="terms-of-service">
<label for="tosAccepted">
<a href="<?php JRoute::_ ('index.php?option=com_virtuemart&view=vendor&layout=tos&virtuemart_vendor_id=1', FALSE) ?>" class="terms-of-service" id="terms-of-service" rel="facebox"
target="_blank">
<span class="vmicon vm2-termsofservice-icon"></span>
<?php echo JText::_ ('COM_VIRTUEMART_CART_TOS_READ_AND_ACCEPTED'); ?>
</a>
</label>
<div id="full-tos">
<h2><?php echo JText::_ ('COM_VIRTUEMART_CART_TOS'); ?></h2>
<?php echo $this->cart->vendor->vendor_terms_of_service; ?>
</div>
</div>
<?php
}
}
To this...
if(VmConfig::get('agree_to_tos_onorder',0)) {
if ($userFieldsModel->getIfRequired ('agreed')) {
if (!class_exists ('VmHtml')) {
require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'html.php');
}
echo VmHtml::checkbox ('tosAccepted', $this->cart->tosAccepted, 1, 0, 'class="terms-of-service"');
}
}
if (VmConfig::get ('oncheckout_show_legal_info', 1)) {
?>
<div class="terms-of-service">
<label for="tosAccepted">
<a href="<?php JRoute::_ ('index.php?option=com_virtuemart&view=vendor&layout=tos&virtuemart_vendor_id=1', FALSE) ?>" class="terms-of-service" id="terms-of-service" rel="facebox"
target="_blank">
<span class="vmicon vm2-termsofservice-icon"></span>
<?php
$tosText = VmConfig::get('agree_to_tos_onorder',0) ? JText::_('COM_VIRTUEMART_CART_TOS_READ').' '.JText::_('COM_VIRTUEMART_CART_TOS_ACCEPT') : JText::_('COM_VIRTUEMART_CART_TOS_READ');
echo $tosText; ?>
</a>
</label>
<div id="full-tos">
<h2><?php echo JText::_ ('COM_VIRTUEMART_CART_TOS'); ?></h2>
<?php echo $this->cart->vendor->vendor_terms_of_service; ?>
</div>
</div>
<?php
}
Well, that's all, hope it gets implemented ASAP.
Best regards!
[attachment cleanup by admin]