/**
  *  This method adds/saves a permission system
  *
  *  @param $id           If we are editing, $id is the group id. If we are adding, $id is the user id
  *  @param $edit         Boolean flag that defines if we are editing $id or adding to $id
  *  @param $formvalues   (Optional) Custom array with user attributes
  *  @param $group_id     Node id used when inserting permissions. nodeID is the node where permissions are applyed
  *
  *  @returns    INT: total of rows affected
  */
 function _saveFormDetails($id, $edit, $formvalues = null, $group_id = 0)
 {
     // validate with custom values
     if (!is_null($formvalues)) {
         $this->_form->validate($formvalues);
     }
     // get form values EXCLUDING spans
     $values = $this->_form->getValues();
     // if this group is not a root group we must get the parent group permissions to check the ones we can use
     $userobject = new YDCMUserobject();
     $groups = $userobject->getElements(array('ydcmgroup', 'ydcmuser'));
     $parent_id = $groups[$id]['parent_id'];
     // when adding a new group, parent of $id is the master group. when editing a group, parent is a user.. so the master group is the parent of the parent
     if ($edit == true) {
         $parent_id = $groups[$parent_id]['parent_id'];
     }
     // if parent of this group is root, parentgroup permissions are ALL (read: null), otherwise we must get permissions of that parent
     if ($parent_id == 1) {
         $parentgroup_perms = null;
     } else {
         $parentgroup_perms = $this->getPermissions($parent_id);
     }
     // if we are editing, we must get the current group permissions. if we are adding, current permissions are empty
     if ($edit == true) {
         $perms = $this->getPermissions($id);
     } else {
         $perms = array();
     }
     $actions_to_add = array();
     $actions_to_del = array();
     // get all possible actions to compute actions we must add and actions we must delete
     foreach ($this->getRegisteredActions() as $class => $actions) {
         foreach ($actions as $action) {
             // if action is selected by the user AND
             // this is a root group OR the action belogs to the parent group
             // we can add it
             if (isset($values['pclass_' . $class][$action]) && ($values['pclass_' . $class][$action] == 1 || $values['pclass_' . $class][$action] == 'on')) {
                 // check if action is valid:
                 // if parent group is a root a group OR the parent group has this action
                 if (is_null($parentgroup_perms) || isset($parentgroup_perms[$class][$action])) {
                     // if action is valid we must check if we must add it or the user already has it
                     if (!isset($perms[$class][$action])) {
                         $actions_to_add[] = array($class, $action);
                     }
                     continue;
                 }
                 // if action selected is not valid we must delete it
                 $actions_to_del[] = array($class, $action);
             }
             // if action is not set, we will always delete it (even if is not in bd)
             $actions_to_del[] = array($class, $action);
         }
     }
     // if we are adding permissions we must add to group_id recently created (not to parent)
     if ($edit == false) {
         $id = $group_id;
     }
     $rows_deleted = 0;
     // delete actions and count rows affected
     foreach ($actions_to_del as $ac) {
         $this->resetValues();
         $this->set('permission_id', $id);
         $this->set('class', $ac[0]);
         $this->set('action', $ac[1]);
         $rows_deleted += $this->delete();
     }
     $rows_added = 0;
     // add actions and count total of action added
     foreach ($actions_to_add as $ac) {
         $this->resetValues();
         $this->set('permission_id', $id);
         $this->set('class', $ac[0]);
         $this->set('action', $ac[1]);
         $this->insert();
         $rows_added++;
     }
     // TODO: currently YDDatabaseObject don't have a mechanism to control the above deletes and inserts
     return $rows_deleted + $rows_added;
 }
 /**
  *  Helper method for user management
  *
  * @param $id           If you will EDIT some user this is the user id to edit.
  *                      If you will ADD a new user this is the group id (parent_id) of the new user.
  * @param $edit         The edit parameter. TRUE if form is form editing, FALSE if form is for a new user creation
  * @param $noneditable  Array with form element names that are NOT editable
  *
  * @returns    YDForm object pointer         
  */
 function &_addFormDetails($id, $edit, $noneditable)
 {
     YDInclude('YDForm.php');
     // init form
     $this->_form = new YDForm('YDCMUsers');
     // check arguments
     if (!is_array($noneditable)) {
         $noneditable = array($noneditable);
     }
     // add username
     if (in_array('username', $noneditable)) {
         $this->_form->addElement('span', 'username', t('ydcmuser label username'));
     } else {
         $this->_form->addElement('text', 'username', t('ydcmuser label username'));
         $this->_form->addFormRule(array(&$this, '_checkuser'), array($edit, $id));
     }
     // add password box for new users
     if ($edit == false) {
         $this->_form->addElement('password', 'password', t('ydcmuser label password'));
         $this->_form->addElement('password', 'password2', t('ydcmuser label password2'));
     }
     // add state
     if (in_array('state', $noneditable)) {
         $this->_form->addElement('span', 'state', t('ydcmuser label state'));
         $this->_form->addElement('span', 'login_start', t('ydcmuser label login_start'));
         $this->_form->addElement('span', 'login_end', t('ydcmuser label login_end'));
     } else {
         $this->_form->addElement('select', 'state', t('ydcmuser label state'), array(), array(1 => t('yes'), 0 => t('no'), 2 => t('schedule')));
         $this->_form->addElement('datetimeselect', 'login_start', t('ydcmuser label login_start'));
         $this->_form->addElement('datetimeselect', 'login_end', t('ydcmuser label login_end'));
     }
     // add common user details
     if (in_array('details', $noneditable)) {
         $this->_form->addElement('span', 'name', t('ydcmuser label name'));
         $this->_form->addElement('span', 'email', t('ydcmuser label email'));
         $this->_form->addElement('span', 'other', t('ydcmuser label other'));
         $this->_form->addElement('span', 'lang_id', t('ydcmuser label language'));
         $this->_form->addElement('span', 'template', t('ydcmuser label template'));
     } else {
         $this->_form->addElement('text', 'name', t('ydcmuser label name'), array('size' => 50, 'maxlength' => 255));
         $this->_form->addElement('text', 'email', t('ydcmuser label email'));
         $this->_form->addElement('textarea', 'other', t('ydcmuser label other'), array('rows' => 15, 'cols' => 40));
         $languages = new YDCMLanguages();
         $languages = $languages->active();
         $this->_form->addElement('select', 'lang_id', t('ydcmuser label language'), array(), $languages);
         $templates = YDCMTemplates::getNames();
         // get url to templates and set shot.png as filename
         $attributes = array('border' => 1, 'src' => YDConfig::get('YDCMTEMPLATES_ADMIN_URL'), 'ext' => YDConfig::get('YDCMTEMPLATES_ADMIN_EXT'));
         $this->_form->addElement('selectimage', 'template', t('ydcmuser label template'), $attributes, $templates);
         $this->_form->addRule('name', 'maxlength', t('ydcmuser mess name too big'), 255);
         $this->_form->addRule('email', 'email', t('ydcmuser mess email not valid'));
         $this->_form->addRule('other', 'maxlength', t('ydcmuser mess other too big'), 5000);
         $this->_form->addRule('language_id', 'in_array', t('ydcmuser mess language not valid'), array_keys($languages));
         $this->_form->addRule('template', 'in_array', t('ydcmuser mess template not valid'), array_keys($templates));
     }
     // add access information when editing
     if ($edit) {
         $this->_form->addElement('span', 'login_counter', t('ydcmuser label login_counter'));
         $this->_form->addElement('span', 'login_last', t('ydcmuser label login_last'));
         $this->_form->addElement('span', 'login_current', t('ydcmuser label login_current'));
     }
     // if we are editing a user it's a good idea to set form defaults with user node attributes
     if ($edit) {
         // add submit button
         $this->_form->addElement('submit', '_cmdSubmit', t('ydcmuser label save'));
         // set form defaults based on user attributes
         $this->_form->setDefaults($this->getUser($id));
     } else {
         // if id argument is not set its because we want a select box (with groups) so choose
         if (is_null($id)) {
             // get groups from userobject
             $obj = new YDCMUserobject();
             $this->_form->addElement('select', 'group', t('ydcmuser label group'), array(), $obj->getElements('YDCMGroup', 'reference'));
         }
         // add submit button
         $this->_form->addElement('submit', '_cmdSubmit', t('ydcmuser label new'));
         // when adding a user, if login_end date exists we setup 7 days interval
         if ($this->_form->isElement('login_end')) {
             $this->_form->setDefault('login_end', time() + 7 * 24 * 3600);
         }
     }
     return $this->_form;
 }