3

I have a Profile form that inherits from sfGuardRegisterForm

I have these fields:

$this->useFields(
    array('first_name', 
          'last_name',
          'email_address',
          'country',
          'language',
          'current_password',
          'new_password',
          'password_again',
    )
);

Required fields are:

email_address, country and language

And the conditions are:

  1. If the email_address is not equal with the current email_address then check if it's unique then save it
  2. If the current_password is the actual password of the user then verify if new_password and password_again are equals and verify that the new_password is not equal to the actual password of the user

I just can't figure out in how implement this

EDIT

Thanks 1ed your example works but the problem is that I load the user Profile and I fill the fields: 'first_name', 'last_name', 'email_address', 'country', 'language' with the actual logged user so the email_address field will show the email address:

//...
$this->widgetSchema['email_address']->setDefault($this->_user->getEmailAddress());
//...

If the user dont change the email it will always show this message:

An object with the same "email_address" already exist.

I just want to skip that

Also this $this->getObject()->checkPassword() does not works, always show this message:

Incorrect current password.

I use:

$this->_user = sfContext::getInstance()->getUser()->getGuardUser();

To get actual user profile

EDIT2

Thanks again 1ed

This is very weird and I'm getting frustated, this is the situation

  1. I have a "workaround" for this but it does not follow the standard, I can make it works but using sfContext::getInstance()->getUser()->getGuardUser(); and it will be more unnecesary code
  2. If I use new ProfileForm($user) automatically fills all the fields, that's very good but I can't setDefault() I can't set null or empty any field so I can't use doUpdateObject() because this function only works when the current data is updated, also I have tested overriding bind(), save() etc. without results

2 Answers 2

5

email_address uniqueness: you should set unique: true in schema, in sfDoctrineGuardPlugin that's the case by default, so in BasesfGuardUserForm you should see a unique validator already: sfValidatorDoctrineUnique(array('model' => 'sfGuardUser', 'column' => array('email_address'))

current_password: you should create a callback type post 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 custom post validator, but I think it's not necessary.

EDIT:

If you would like to display empty email address just like the password fields add these to your 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);
}
Sign up to request clarification or add additional context in comments.

7 Comments

I think the validators dontt works because you don't set the underlying user object. And this $this->_user = sfContext::getInstance()->getUser()->getGuardUser();` is not good idea, always try avoid using sfContext if it's possible. In the action, where you create the form, you should get the user object and pass it to the form and all values will be filled in based on the user. $user = $this->getUser()->getGuardUser(); $this->form = new ProfileForm($user);. The setDefault() calls are not required.
One mote thing... the sfValidatorSchemaCompare validator is not required because it is already in the BasesfGuardUserAdminForm so I removed that.
you right, I have changed $this->form = new ProfileForm($this->getUser()->getGuardUser()); and it works and I'm thinking in not show the email address and put it required = false
I've just fixed the chackPassword() for the "0" input, please update your code and sorry for that.
The password field is a special one because if you give an empty password nothing happens, but if you post your form with an empty email the former email will be deleted from the database. If you really would like to show an empty email field and modify the database just if the email changes take a look my updated answer.
|
0

I'll try and explain this in methodical terms instead of giving you a big block of code.... So first, you want to if (email_addr != current_email) and if that's true, go on to do if (new_pass != current_pass) then follow on to make sure if (new_pass == new_pass_again) Inside all of these IFs, you can return a true/false or some kind of flag, or just //do code inside the brackets :p

EDIT: encase these IFs in: if (country != NULL && language != NULL && email_addr != NULL)

2 Comments

Thanks I have done that, the problem that I'm facing now it's to check if the email_address != actual_email and check if the email its unique in the database
Well for that you'd need to get every email in the DB and put them into an array, then do a foreach() and compare them, then return if it's true or not. & for the current email just go through the DB and select users USERNAME and go through users indexes, get the current_email, and compare it. Logic like this can be confusing, and I don't work with DBs a lot but if you search on Google something like How to search all the indexes of a db in php mysql/sqlite you should come up with somethin'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.