Symfony 1.4 conditional validation
I have a form Profile
that inherits fromsfGuardRegisterForm
I have the following fields:
$this->useFields(
array('first_name',
'last_name',
'email_address',
'country',
'language',
'current_password',
'new_password',
'password_again',
)
);
Required fields:
email_address
, country
andlanguage
And conditions:
- If
email_address
not the same as the current oneemail_address
then check if it is unique then save it - If
current_password
is the actual user password, then check ifnew_password
and are equalpassword_again
and make sure it isnew_password
not the same as the actual user password
I just can't figure out how to implement this
EDIT
Thanks 1ed your example works, but the problem is I load the user profile and I fill in the fields: 'first_name', 'last_name', 'email_address', 'country', 'language'
with the actual logged in user, so the field email_address
will show the email
//...
$this->widgetSchema['email_address']->setDefault($this->_user->getEmailAddress());
//...
Unless the user changes their email address, they will always show this message:
An object with the same "email_address" already exists.
I just want to miss that
Also this one $this->getObject()->checkPassword()
doesn't work, always show this message:
Invalid current password.
I use:
$ this -> _ user = sfContext :: getInstance () -> getUser () -> getGuardUser ();
Get the actual user profile
EDIT2
Thanks again 1ed
This is very strange and I get a swirl, this is the situation
- I have a "workaround" for this, but it is not in the standard, I can get it to work, but using
sfContext::getInstance()->getUser()->getGuardUser();
and it will be more unnecessary code. - If I use
new ProfileForm($user)
auto-fills all fields, that's very good , but I can'tsetDefault()
I can't setnull
orempty
any field that I can't usedoUpdateObject()
, because this function only works when the current data is updated, also I checked the overridebind()
,save()
etc. etc. no results
source to share
uniqueness email_address: you must set unique: true
in the schema, in sfDoctrineGuardPlugin
, which is the default case, so in BasesfGuardUserForm
you should see the unique validator already:sfValidatorDoctrineUnique(array('model' => 'sfGuardUser', 'column' => array('email_address'))
current_password: you must create a callback type message validator for this
// in sfGuardRegisterForm::configure()
// these fields can be blank
$this->getValidator('current_password')->setOption('required', false);
$this->getValidator('new_password')->setOption('required', false);
$this->getValidator('password_again')->setOption('required', false);
// check the current password (this validator is not `required` by default)
$this->mergePostValidator(new sfValidatorCallback(array(
'callback' => array($this, 'checkPassword'),
), array(
'invalid' => 'Incorrect current password.'
)));
// add this method to the same form class
public function checkPassword(sfValidatorBase $validator, array $values, array $arguments)
{
// if a new password is given check whether the old one is correct or not and rise an error if not correct
if(0 != strlen($values['new_password']) && !$this->getObject()->checkPassword($values['current_password']))
{
throw new sfValidatorErrorSchema($validator, array(
'current_password' => new sfValidatorError($validator, 'invalid')
));
}
return $values;
}
Alternatively you can create a personalized post validator, but I think this is not necessary.
EDIT:
If you want to display a blank email in the same way as password fields, add them to the form class:
// at form load remove the default value
protected function updateDefaultsFromObject()
{
parent::updateDefaultsFromObject();
if (isset($this['email_address']))
{
$this->setDefault('email_address', '');
}
}
// before save remove empty email address
protected function doUpdateObject($values)
{
if (isset($values['email_address']) && 0 == strlen($values['email_address']))
{
unset($values['email_address']);
}
parent::doUpdateObject($values);
}
source to share
I'll try to explain this in methodical terms instead of giving you a big block of code .... So first you want if (email_addr! = Current_email) , and if that's true, keep doing if (new_pass! = Current_pass) , then do to make sure that if (new_pass == new_pass_again) Inside all these IFs you can return true / false or some kind of flag or just // do the code inside the brackets: p
EDIT: wrap these IFs in: if (country! = NULL && language! = NULL & email_addr! = NULL)
source to share