symfony1symfony-1.4sfdoctrineguard

Create new users with the same group(s) as the user logged in


I'm trying to add new users to sfDoctrineGuard table using my own register form. This is the configure function I made:

public function configure() {
    // Remove all widgets we don't want to show
    unset(
            $this['is_super_admin'], $this['updated_at'], $this['groups_list'], $this['permissions_list'], $this['last_login'], $this['created_at'], $this['salt'], $this['algorithm']
    );

    $id_empresa = sfContext::getInstance()->getUser()->getGuardUser()->getSfGuardUserProfile()->getIdempresa();
    $this->setDefault('idempresa', $id_empresa);

    $this->validatorSchema['idempresa'] = new sfValidatorPass();

    $this->widgetSchema['first_name'] = new sfWidgetFormInputText(array(), array('class' => 'input-block-level'));
    $this->widgetSchema['last_name'] = new sfWidgetFormInputText(array(), array('class' => 'input-block-level'));
    $this->widgetSchema['username'] = new sfWidgetFormInputText(array(), array('class' => 'input-block-level'));
    $this->widgetSchema['email_address'] = new sfWidgetFormInputText(array(), array('class' => 'input-block-level'));
    $this->widgetSchema['password'] = new sfWidgetFormInputPassword(array(), array('class' => 'input-block-level'));
    $this->widgetSchema['password_confirmation'] = new sfWidgetFormInputPassword(array(), array('class' => 'input-block-level'));

    // Setup proper password validation with confirmation
    $this->validatorSchema['password']->setOption('required', true);
    $this->validatorSchema['password_confirmation'] = clone $this->validatorSchema['password'];

    $this->widgetSchema->moveField('password_confirmation', 'after', 'password');

    $this->mergePostValidator(new sfValidatorSchemaCompare('password', sfValidatorSchemaCompare::EQUAL, 'password_confirmation', array(), array('invalid' => 'The two passwords must be the same.')));
}

Now I need to create those new users with the same group(s) that the user logged in but I don't know how. I read this post but don't know if using getGroups() will do the job I mean setting groups_list default, any advice? What's the best way to do this?


Solution

  • there are several way you could do this... I'd recommend adding the groups once validation for the other fields has taken place, and the user object has been saved; so you can override the save() function of the form and add them there:

    <?php
    
    class YourUserForm extends PluginsfGuardUserForm
    {
      /**
       * A class variable to store the current user
       * @var sfGuardUser
       */
      protected $current_user;
    
      public function configure()
      {
        // Remove all widgets we don't want to show
        unset(
          $this['is_super_admin'],
          $this['updated_at'],
          $this['groups_list'],
          $this['permissions_list'],
          $this['last_login'],
          $this['created_at'],
          $this['salt'],
          $this['algorithm']
        );
    
        // save the currrent user for use later in the save function
        $this->current_user = sfContext::getInstance()->getUser()->getGuardUser();
    
        $id_empresa = $this->current_user->getSfGuardUserProfile()->getIdempresa();;
        $this->setDefault('idempresa', $id_empresa);
    
        $this->validatorSchema['idempresa'] = new sfValidatorPass();
    
        $this->widgetSchema['first_name'] = new sfWidgetFormInputText(array(), array('class' => 'input-block-level'));
        $this->widgetSchema['last_name'] = new sfWidgetFormInputText(array(), array('class' => 'input-block-level'));
        $this->widgetSchema['username'] = new sfWidgetFormInputText(array(), array('class' => 'input-block-level'));
        $this->widgetSchema['email_address'] = new sfWidgetFormInputText(array(), array('class' => 'input-block-level'));
        $this->widgetSchema['password'] = new sfWidgetFormInputPassword(array(), array('class' => 'input-block-level'));
        $this->widgetSchema['password_confirmation'] = new sfWidgetFormInputPassword(array(), array('class' => 'input-block-level'));
    
        // Setup proper password validation with confirmation
        $this->validatorSchema['password']->setOption('required', true);
        $this->validatorSchema['password_confirmation'] = clone $this->validatorSchema['password'];
    
        $this->widgetSchema->moveField('password_confirmation', 'after', 'password');
    
        $this->mergePostValidator(new sfValidatorSchemaCompare('password', sfValidatorSchemaCompare::EQUAL, 'password_confirmation', array(), array('invalid' => 'The two passwords must be the same.')));
      }
    
      public function save($con = null)
      {
        // call the parent function to perform the save and get the new user object
        $new_user = parent::save($con); /* @var $user sfGuardUser */
    
        // add our groups here by looping the current user's group collection
        foreach($this->current_user->getGroups() as $group) /* @var $group sfGuardGroup */
        {
          // we could use $user->addGroupByName($group->name); here, but it would mean
          // an extra db lookup for each group as it validates the name. we know the
          // group must exist, so can just add directly
    
          // create and save new user group
          $ug = new sfGuardUserGroup();
          $ug->setsfGuardUser($new_user);
          $ug->setsfGuardGroup($group);
    
          $ug->save($con);
        }
    
        // make sure we return the user object
        return $new_user;
      }
    }
    

    You can see I set up a class variable to store the current user, this isn't necessary, but it save having to keep calling sfContext::getInstance()->getUser()->getGuardUser(), and is good practice as your forms get more complex.

    Hopefully this helps! :)