Users can change value of User Field, of type: Date or Radio or Select, in front end account maintenance even though Read-Only? is set to Yes.
VirtueMart Version: 1.1.3
Joomla Version: 1.5.12
Steps to replicate:
Create a user field of type "Date", "Radio" or "Select" - Read-Only? Yes
Go to front end account maintenance change the value and save.
Birth date is "grey" - click on the date button - pick a date and it will change.
Return - change will have been accepted.
Proposed fix(es): No idea.
Bugtracker task #:
Enter the bugtracker task #/url when submitted.
System info: Linux, Apache 2.2.11, PHP 5.2.9, MySQL 5.0.67, Firefox 3.5.1
[attachment cleanup by admin]
Known issue - Tracker URL http://dev.virtuemart.net/cb/issue/1578
Thanks for the reply Peter.
I really wish the bug could be fixed. I use VM not only as a shop but also as an extended membership database (rather than CB or Juser or phpBB3 ....) and I only want shopadmins to update certain fields.
Anyway, I guess I'll have to change the fields to text boxes and pray the admins all use the same "value". :-\
Matthew.
Hello,
Has there been any progress for this issue, or should I just be patient?
Thanks for everything,
Eddie
I am using version 1.1.3 and found that the readonly setting for the form controls was not working. Basically I only want to be able to change the setting from the administration area. Here is what I changed to fix it. Please make backups of the original files before you change them.
/administrator/components/com_virtuemart/classes/ps_userfield.php
change the following function
function listUserFields( $rowFields, $skipFields=array(), $db = null, $startForm = true ) {
global $mm_action_url, $ps_html, $VM_LANG, $my, $default, $mainframe, $vm_mainframe,
$vendor_country_3_code, $mosConfig_live_site, $mosConfig_absolute_path, $page;
if (strpos($_SERVER['REQUEST_URI'] , 'administrator'))
$no_edit = false;
else
$no_edit = true;
$dbf = new ps_DB();
if( $db === null ) {
$db = new ps_DB();
}
$default['country'] = $vendor_country_3_code;
$missing = vmGet( $_REQUEST, 'missing', '' );
// collect all required fields
$required_fields = Array();
foreach( $rowFields as $field ) {
if( $field->required == 1 ) {
$required_fields[$field->name] = $field->type;
}
$allfields[$field->name] = $field->name;
}
foreach( $skipFields as $skip ) {
unset($required_fields[$skip]);
}
// Form validation function
if( !vmIsAdminMode() ) {
ps_userfield::printJS_formvalidation( $required_fields, $rowFields );
} else {
echo vmCommonHTML::scriptTag('', 'function submitregistration() { return true }');
}
if( file_exists( $mosConfig_absolute_path .'/includes/js/mambojavascript.js') ) {
$vm_mainframe->addScript( 'includes/js/mambojavascript.js' );
}
if( $startForm ) {
echo '<form action="'. $mm_action_url .basename($_SERVER['PHP_SELF']) .'" method="post" name="adminForm">';
}
echo '
<div style="width:90%;">';
if( !empty( $required_fields )) {
echo '<div style="padding:5px;text-align:center;"><strong>(* = '.$VM_LANG->_('CMN_REQUIRED').')</strong></div>';
}
$delimiter = 0;
foreach( $rowFields as $field) {
if( !isset( $default[$field->name] )) {
$default[$field->name] = $field->default;
}
if ($field->readonly && $no_edit)
{
$name = 'readonly'.rand(); // don't disclose the real name
//$readonly = ' readonly="readonly"';
$readonly = ' disabled';
}
else
{
$name=$field->name;
$readonly ='';
}
if( in_array( $field->name, $skipFields )) {
continue;
}
// Title handling.
$key = $field->title;
if( $key[0] == '_') {
$key = substr($key, 1, strlen($key)-1);
}
if( $VM_LANG->exists($key) ) {
$field->title = $VM_LANG->_($key);
}
if( $field->name == 'agreed') {
$field->title = '<script type="text/javascript">//<![CDATA[
document.write(\'<label for="agreed_field">'. str_replace("'","\\'",$VM_LANG->_('PHPSHOP_I_AGREE_TO_TOS')) .'</label><a href="javascript:void window.open(\\\''. $mosConfig_live_site .'/index2.php?option=com_virtuemart&page=shop.tos&pop=1\\\', \\\'win2\\\', \\\'status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=480,directories=no,location=no\\\');">\');
document.write(\' ('.$VM_LANG->_('PHPSHOP_STORE_FORM_TOS') .')</a>\');
//]]></script>
<noscript>
<label for="agreed_field">'. $VM_LANG->_('PHPSHOP_I_AGREE_TO_TOS') .'</label>
<a target="_blank" href="'. $mosConfig_live_site .'/index.php?option=com_virtuemart&page=shop.tos" title="'. $VM_LANG->_('PHPSHOP_I_AGREE_TO_TOS') .'">
('.$VM_LANG->_('PHPSHOP_STORE_FORM_TOS').')
</a></noscript>';
}
if( $field->name == 'username' && VM_REGISTRATION_TYPE == 'OPTIONAL_REGISTRATION' ) {
echo '<div class="formLabel">
<input type="checkbox" id="register_account" name="register_account" value="1" class="inputbox" onchange="showFields( this.checked, new Array(\'username\', \'password\', \'password2\') );if( this.checked ) { document.adminForm.remember.value=\'yes\'; } else { document.adminForm.remember.value=\'yes\'; }" checked="checked" />
</div>
<div class="formField">
<label for="register_account">Optional: '.$VM_LANG->_('VM_REGISTER_ACCOUNT').'</label>
</div>
';
} elseif( $field->name == 'username' ) {
echo '<input type="hidden" id="register_account" name="register_account" value="1" />';
}
// a delimiter marks the beginning of a new fieldset and
// the end of a previous fieldset
if( $field->type == 'delimiter') {
if( $delimiter > 0) {
echo "</fieldset>\n";
}
if( VM_REGISTRATION_TYPE == 'SILENT_REGISTRATION' && $field->title == $VM_LANG->_('PHPSHOP_ORDER_PRINT_CUST_INFO_LBL') && $page == 'checkout.index' ) {
continue;
}
echo '<fieldset>
<legend class="sectiontableheader">'.$field->title.'</legend>
';
$delimiter++;
continue;
}
//echo '<div id="'.$field->name.'_div" class="formLabel ';
echo '<div id="'.$name.'_div" class="formLabel ';
if (stristr($missing,$field->name)) {
echo 'missing';
}
echo '">';
//echo '<label for="'.$field->name.'_field">'.$field->title.'</label>';
echo '<label for="'.$name.'_field">'.$field->title.'</label>';
if( isset( $required_fields[$field->name] )) {
echo '<strong>* </strong>';
}
echo ' </div>
<div class="formField" id="'.$name.'_input">'."\n";
/**
* This is the most important part of this file
* Here we print the field & its contents!
*/
switch( $field->name ) {
case 'title':
$ps_html->list_user_title($db->sf('title'), "id=\"title_field\"");
break;
case 'country':
if( in_array('state', $allfields ) ) {
$onchange = "onchange=\"changeStateList();\"";
}
else {
$onchange = "";
}
$ps_html->list_country("country", $db->sf('country'), "id=\"country_field\" $onchange");
break;
case 'state':
echo $ps_html->dynamic_state_lists( "country", "state", $db->sf('country'), $db->sf('state') );
echo "<noscript>\n";
$ps_html->list_states("state", $db->sf('state'), "", "id=\"state_field\"");
echo "</noscript>\n";
break;
case 'agreed':
echo '<input type="checkbox" id="agreed_field" name="agreed" value="1" class="inputbox" />';
break;
case 'password':
echo '<input type="password" id="'.$field->name.'_field" name="'.$field->name.'" size="30" class="inputbox" />'."\n";
break;
case 'password2':
echo '<input type="password" id="'.$field->name.'_field" name="'.$field->name.'" size="30" class="inputbox" />'."\n";
echo '<label><br><br>Note: Once you have entered your account information, we will e-mail you a security link. Clicking on the link will activate your account and allow you to log in using your user name and password.</label>';
break;
default:
switch( $field->type ) {
case 'date':
echo vmCommonHTML::scriptTag( $mosConfig_live_site .'/includes/js/calendar/calendar.js');
if( vmIsJoomla( '1.5', '>=' ) ) {
// in Joomla 1.5, the name of calendar lang file is changed...
echo vmCommonHTML::scriptTag( $mosConfig_live_site .'/includes/js/calendar/lang/calendar-en-GB.js');
} else {
echo vmCommonHTML::scriptTag( $mosConfig_live_site .'/includes/js/calendar/lang/calendar-en.js');
}
echo vmCommonHTML::linkTag( $mosConfig_live_site .'/includes/js/calendar/calendar-mos.css');
$maxlength = $field->maxlength ? 'maxlength="'.$field->maxlength.'"' : '';
//echo '<input type="text" id="'.$field->name.'_field" name="'.$field->name.'" size="'.$field->size.'" value="'. ($db->sf($field->name)?$db->sf($field->name):'') .'" class="inputbox" '.$maxlength . $readonly . ' />'."\n";
//echo '<input name="reset" type="reset" class="button" onclick="return showCalendar(\''.$field->name.'_field\', \'y-mm-dd\');" value="..." />';
echo '<input type="text" id="'.$name.'_field" name="'.$name.'" size="'.$field->size.'" value="'. ($db->sf($field->name)?$db->sf($field->name):'') .'" class="inputbox" '.$maxlength . $readonly . ' />'."\n";
if ($name==$field->name)
echo '<input name="reset" type="reset" class="button" onclick="return showCalendar(\''.$field->name.'_field\', \'y-mm-dd\');" value="..." />';
break;
case 'text':
case 'emailaddress':
case 'webaddress':
case 'euvatid':
$maxlength = $field->maxlength ? 'maxlength="'.$field->maxlength.'"' : '';
//echo '<input type="text" id="'.$field->name.'_field" name="'.$field->name.'" size="'.$field->size.'" value="'. ($db->sf($field->name)?$db->sf($field->name):'') .'" class="inputbox" '.$maxlength . $readonly . ' />'."\n";
echo '<input type="text" id="'.$name.'_field" name="'.$name.'" size="'.$field->size.'" value="'. ($db->sf($field->name)?$db->sf($field->name):'') .'" class="inputbox" '.$maxlength . $readonly . ' />'."\n";
break;
case 'textarea':
//echo '<textarea name="'.$field->name.'" id="'.$field->name.'_field" cols="'.$field->cols.'" rows="'.$field->rows.'" '.$readonly.'>'.$db->sf($field->name).'</textarea>';
echo '<textarea name="'.$name.'" id="'.$name.'_field" cols="'.$field->cols.'" rows="'.$field->rows.'" '.$readonly.'>'.$db->sf($field->name).'</textarea>';
break;
case 'editorta':
//editorArea( $field->name, $db->sf($field->name), $field->name, '300', '150', $field->cols, $field->rows );
if ($name==$field->name)
editorArea( $field->name, $db->sf($field->name), $field->name, '300', '150', $field->cols, $field->rows );
else
echo '<textarea name="'.$name.'" id="'.$name.'_field" cols="'.$field->cols.'" rows="'.$field->rows.'" '.$readonly.'>'.$db->sf($field->name).'</textarea>';
break;
case 'checkbox':
//echo '<input type="checkbox" name="'.$field->name.'" id="'.$field->name.'_field" value="1" '. ($db->sf($field->name) ? 'checked="checked"' : '') .$readonly.'/>';
echo '<input type="checkbox" name="'.$name.'" id="'.$name.'_field" value="1" '. ($db->sf($field->name) ? 'checked="checked"' : '') .$readonly.'/>';
break;
case 'age_verification':
$year = vmRequest::getInt('birthday_selector_year', date('Y'));
if( $db->f($field->name) ) {
$birthday = $db->f($field->name);
$date_array = explode('-', $birthday );
$year = $date_array[0];
$month = $date_array[1];
$day = $date_array[2];
}
ps_html::list_days('birthday_selector_day', vmRequest::getInt('birthday_selector_day', @$day));
ps_html::list_month('birthday_selector_month', vmRequest::getInt('birthday_selector_month', @$month));
ps_html::list_year('birthday_selector_year', $year, $year-100, $year);
break;
case 'captcha':
if (file_exists($mosConfig_absolute_path.'/administrator/components/com_securityimages/client.php')) {
include ($mosConfig_absolute_path.'/administrator/components/com_securityimages/client.php');
// Note that this package name must be used on the validation side too! If both are not equal, validation will fail
$packageName = 'securityVMRegistrationCheck';
echo insertSecurityImage($packageName);
echo getSecurityImageText($packageName);
}
else if (file_exists($mosConfig_absolute_path.'/plugins/system/securityimages.php')) {
echo "<script type=\"text/javascript\" src=\"".JURI :: root()."/components/com_securityimages/js/securityImages.js\"></script>";
echo "<img id='captchaSecurityImages' name='captchaSecurityImages' src=\"".JURI :: root()."/index.php?option=com_securityimages&task=displayCaptcha\" />";
echo "<a href=\"javascript:askNewSecurityImages('captchaSecurityImages');\">";
echo "<img src=\"".JURI :: root()."/components/com_securityimages/buttons/reload.gif\" id=\"securityImagesContactCaptchaReload\" name=\"securityImagesContactCaptchaReload\" border=\"0\">";
echo "</a>";
echo "<input type=\"text\" name=\"securityVMRegistrationCheck_try\" />";
}
break;
// Begin of a fallthrough
case 'multicheckbox':
case 'select':
case 'multiselect':
case 'radio': //I have not tested this with readonly name change
$k = $db->f($field->name);
$dbf->setQuery( "SELECT fieldtitle,fieldvalue FROM #__{vm}_userfield_values"
. "\n WHERE fieldid = ".$field->fieldid
. "\n ORDER BY ordering" );
$Values = $dbf->loadObjectList();
$multi="";
$rowFieldValues['lst_'.$name] = '';
if($field->type=='multiselect') $multi="multiple='multiple'";
if(count($Values) > 0) {
if($field->type=='radio') {
$rowFieldValues['lst_'.$name] = vmCommonHTML::radioListTable( $Values, $name,
$readonly.' class="inputbox" size="1" ',
'fieldvalue', 'fieldtitle', $k, $field->cols, $field->rows, $field->size, $field->required);
} else {
$ks=explode("|*|",$k);
$k = array();
foreach($ks as $kv) {
$k[]->fieldvalue=$kv;
}
if($field->type=='multicheckbox') {
$rowFieldValues['lst_'.$name] = vmCommonHTML::checkboxListTable( $Values, $name."[]",
$readonly.' class="inputbox" size="'.$field->size.'" '.$multi,
'fieldvalue', 'fieldtitle', $k, $field->cols, $field->rows, $field->size, $field->required);
} else {
$rowFieldValues['lst_'.$name] = vmCommonHTML::selectList( $Values, $name."[]",
$readonly.' class="inputbox" size="'.$field->size.'" '.$multi,
'fieldvalue', 'fieldtitle', $k);
}
}
}
// no break! still a fallthrough
echo $rowFieldValues['lst_'.$name];
break;
case 'originalradio': //did not modify these radio with readonly name change
$k = $db->f($field->name);
$dbf->setQuery( "SELECT fieldtitle,fieldvalue FROM #__{vm}_userfield_values"
. "\n WHERE fieldid = ".$field->fieldid
. "\n ORDER BY ordering" );
$Values = $dbf->loadObjectList();
$multi="";
$rowFieldValues['lst_'.$field->name] = '';
if($field->type=='multiselect') $multi="multiple='multiple'";
if(count($Values) > 0) {
if($field->type=='radio') {
$rowFieldValues['lst_'.$field->name] = vmCommonHTML::radioListTable( $Values, $field->name,
$readonly.'class="inputbox" size="1" ',
'fieldvalue', 'fieldtitle', $k, $field->cols, $field->rows, $field->size, $field->required);
} else {
$ks=explode("|*|",$k);
$k = array();
foreach($ks as $kv) {
$k[]->fieldvalue=$kv;
}
if($field->type=='multicheckbox') {
$rowFieldValues['lst_'.$field->name] = vmCommonHTML::checkboxListTable( $Values, $field->name."[]",
$readonly.'class="inputbox" size="'.$field->size.'" '.$multi,
'fieldvalue', 'fieldtitle', $k, $field->cols, $field->rows, $field->size, $field->required);
} else {
$rowFieldValues['lst_'.$field->name] = vmCommonHTML::selectList( $Values, $field->name."[]",
$readonly.'class="inputbox" size="'.$field->size.'" '.$multi,
'fieldvalue', 'fieldtitle', $k);
}
}
}
// no break! still a fallthrough
echo $rowFieldValues['lst_'.$field->name];
break;
}
break;
}
if( $field->description != '') {
echo vmToolTip( $field->description );
}
echo '<br /></div>
<br style="clear:both;" />';
}
if( $delimiter > 0) {
echo "</fieldset>\n";
}
echo '</div>';
if( VM_REGISTRATION_TYPE == 'OPTIONAL_REGISTRATION') {
echo '<script type="text/javascript">
function showFields( show, fields ) {
if( fields ) {
for (i=0; i<fields.length;i++) {
if( show ) {
document.getElementById( fields[i] + \'_div\' ).style.display = \'\';
document.getElementById( fields[i] + \'_input\' ).style.display = \'\';
} else {
document.getElementById( fields[i] + \'_div\' ).style.display = \'none\';
document.getElementById( fields[i] + \'_input\' ).style.display = \'none\';
}
}
}
}
try {
showFields( document.getElementById( \'register_account\').checked, new Array(\'username\', \'password\', \'password2\') );
} catch(e){}
</script>';
}
}
Then is the
/administrator/components/com_virtuemart/html/checkout_register_form.php
file comment out the
//foreach( $fields as $field ) $field->readonly = 0;
and if you want to hide these fields during registration then add the following code after the $skip_fields array.
foreach( $fields as $field )
{
if ($field->readonly)
$skip_fields[] = $field->name;
}
Hope this helps,
Craig
PS Virtuemart is great!