* @license PHP License * @package WB * @subpackage content */ /** * Load required class */ WBClass::load('WBContent'); /** * Content component: User_Manager * * @version 1.1.0 * @package WB * @subpackage content */ class WBContent_User_Manager extends WBContent { /** * my parameter list * @var array */ protected $config = array( 'action' => 'userlist', 'requiredgroup' => 'admin', 'goto' => '0', 'hideuser' => array(), 'editablecolumns' => array('forename', 'surname'), 'orderfield' => 'surname', 'orderasc' => 1, 'searchfields' => array('nickname', 'forename', 'surname'), 'limit' => '-1' ); /** * table * @var WBDatasource_Table */ protected $table; /** * user object * @var WBUser */ protected $patron; /** * relation table * @var WBDatasource_RelationTable */ private $relTable = null; /** * CSV file to import users * @var WBFile_CSV */ private $csv; /** * current group id, if any * @var string */ private $gid = 0; /** * run * * run component * * @return array parameter list */ public function run() { if (!$this->isUserInGroup($this->config['requiredgroup'])) { $this->loadTemplates('anon'); return $this->config; } $this->table = WBClass::create('WBDatasource_Table'); // try to load user by id $this->patron = WBClass::create('WBUser'); if ($this->config['action'] != 'userlist' && strncmp($this->config['action'], 'user', 4) == 0) { if ($this->patron->load($this->req->get('user', 0))) { $this->tmpl->addGlobalVars($this->patron->getData()); } else { if ('useradd' != $this->config['action']) { $this->config['action'] = 'userlist'; } } // load group by id } else if ($this->config['action'] != 'grouplist' && strncmp($this->config['action'], 'group', 5) == 0) { $this->gid = $this->req->get('group', 0); $group = array(); if ($this->gid) { $group = $this->table->get('group', $this->gid); } if (1 == count($group)) { $group = $group[0]; } else { if ('groupadd' != $this->config['action']) { $this->config['action'] = 'grouplist'; } $this->gid = 0; $group = array(); } } $tmp = array(); foreach ($this->config as $k => $v) { if (is_scalar($v)) { $tmp[$k] = $v; } } $this->tmpl->addGlobalVars($tmp, 'CONFIG_'); switch ($this->config['action']) { case 'groupadd': $group['id'] = '__new'; $this->tmpl->addGlobalVars($group); $this->initRelationTable('group'); $this->processForm('groupEdit', $group); break; case 'groupedit': $this->tmpl->addGlobalVars($group); $this->initRelationTable('group'); if ($this->relTable) { $this->relTable->inject($group); } $this->processForm('groupEdit', $group); break; case 'grouprm': // delete? $this->tmpl->addGlobalVars($group); if ($this->gid && $this->req->get('force', 'no') == 'yes') { $this->table->delete('group', $this->gid); $this->loadTemplates('groupRmDeleted'); break; } $this->loadTemplates('groupRm'); return $this->config; break; case 'grouplist': $this->loadTemplates('groupList'); break; case 'groupmember': if ($this->displayMemberList($group)) { return $this->config; } $this->loadTemplates('groupList'); break; case 'userimport': $list = $this->getFormElementList('userImport'); $this->processForm('userImport'); break; case 'useredit': $this->initRelationTable('user'); $data = $this->patron->getData(); $data['groups'] = array_keys($this->patron->getGroups()); if ($this->relTable) { $this->relTable->inject($data); } $this->processForm('userEdit', $data); break; case 'userrm': $this->tmpl->addGlobalVars($this->patron->getData()); if ($this->req->get('force', 'no') == 'yes') { $this->table->delete('user', $this->patron->getId()); $this->loadTemplates('userRmDeleted'); break; } $this->loadTemplates('userRm'); break; case 'userdisplay': $this->tmpl->addGlobalVars($this->patron->getData()); $this->loadTemplates('userDisplay'); break; case 'userlist': default: $this->loadTemplates('userList'); break; } $this->displayUserList(); $this->displayGroupList(); return $this->config; } /** * display list of records in table * * In case there is a template named "list_entry", it will be filled with paged * rows of table */ protected function displayGroupList() { if (!$this->tmpl->exists('group_list_entry')) { return; } $options = array( 'limit' => 25 ); if ($this->config['limit'] && intval($this->config['limit']) > 0) { $options['limit'] = intval($this->config['limit']); } $clause = array(); $pager = $this->table->getPager($this->part . __CLASS__ . 'group', 'group', null, $clause, $options); $this->tmpl->addGlobalVars($pager->browse($this->config['goto']), 'pager_'); $this->tmpl->addRows('group_list_entry', $pager->get()); } /** * display list of records in table * * In case there is a template named "list_entry", it will be filled with paged * rows of table */ protected function displayUserList() { if (!$this->tmpl->exists('user_list_entry')) { return; } $clause = array(); if (!empty($this->config['hideuser']) && is_array($this->config['hideuser'])) { $clause[] = array( 'field' => $this->table->getIdentifier('user'), 'relation' => 'not_in', 'value' => $this->config['hideuser'] ); } $this->addSearchQuery($clause); $options = array(); if ($this->config['limit'] && intval($this->config['limit']) > 0) { $options['limit'] = intval($this->config['limit']); } // order by if (!empty($this->config['orderfield'])) { $options['order'] = array( 'field' => $this->config['orderfield'], 'asc' => $this->config['orderasc'] ); } $pager = $this->table->getPager($this->part . __CLASS__ . 'user', 'user', null, $clause, $options); $this->tmpl->addGlobalVars($pager->browse($this->config['goto']), 'pager_'); $this->tmpl->addRows('user_list_entry', $pager->get()); } /** * Display Members * * @param array $group * @return bool true if group data is valid */ private function displayMemberList($group) { if (empty($group)) { return false; } $clause = array(); if (!empty($this->config['hideuser']) && is_array($this->config['hideuser'])) { $clause[] = array( 'field' => $this->table->getIdentifier('user'), 'relation' => 'not_in', 'value' => $this->config['hideuser'] ); } $clause[] = array( 'table' => 'usergroup', 'field' => $this->table->getIdentifier('group'), 'value' => $this->gid ); $options = array(); $options['join'] = array(); $options['join'][] = array( 'table' => 'usergroup', 'using' => $this->table->getIdentifier('user') ); if ($this->config['limit'] && intval($this->config['limit']) > 0) { $options['limit'] = intval($this->config['limit']); } // order by if (!empty($this->config['orderfield'])) { $options['order'] = array( 'field' => $this->config['orderfield'], 'asc' => $this->config['orderasc'] ); } $this->loadTemplates('memberList'); $this->tmpl->addGlobalVars($group, 'GROUP_'); $pager = $this->table->getPager($this->part . __CLASS__ . 'member', 'user', null, $clause, $options); $this->tmpl->addGlobalVars($pager->browse($this->config['goto']), 'pager_'); $this->tmpl->addRows('user_list_entry', $pager->get()); return true; } /** * receive output * * fetch output of this content component * * @return string */ public function getString() { return $this->tmpl->getParsedTemplate('snippet'); } /** * Import users from CSV file * * @param patForms $form * @param array $values */ protected function onUserImportValid($form, $values) { $this->csv = WBClass::create('WBFile_CSV'); $els = $this->getFormElementList('userImport'); $dir = substr($els['csv']['attributes']['uploaddir'], strlen(WBParam::get('wb/dir/base'))); if (!$this->csv->exists($dir . '/' . $values['csv'])) { $this->tmpl->addGlobalVar('error', patI18n::dgettext('wombat', 'CSV File not found!')); return true; } $this->csv->open(); if (!$this->csv->guessFormat()) { $this->tmpl->addGlobalVar('error', patI18n::dgettext('wombat', 'CSV file corrupt or format unknown.')); } // need headline $line = $this->csv->read(); // lowercase for ($i = 0; $i < count($line); ++$i) { $line[$i] = strtolower(trim($line[$i])); } // check required columns $required = $this->user->getFieldsRequired(); $errors = array(); foreach ($required as $f) { if ('password' == $f) { continue; } if (!in_array($f, $line)) { $errors[] = WBString::populate(patI18n::dgettext('wombat','CSV file requires column named "{FIELD}"!'), array('field' => $f)); } } $this->tmpl->addGlobalVar('error_count', count($errors)); if (0 < count($errors)) { $this->tmpl->addVar('error_list', 'error', $errors); return true; } $this->csv->setMap(array_flip($line)); $storage = $this->user->getStorageModule(); $editable = $this->user->getFieldsEditable(); $editable = array_merge($editable, $required); $errors = array(); $import = array(); $row = 1; while (!$this->csv->eof()) { $ok = true; $line = $this->csv->read(); if (empty($line)) { continue; } $line = array_merge($line, $values); ++$row; // don't save the password, never ever if (isset($line['password'])) { unset($line['password']); } $save = array( 'approved' => 1, 'enabled' => 1 ); // check all required fields foreach ($required as $f) { if (!isset($line[$f]) || empty($line[$f])) { if ('password' == $f) { continue; } $ok = false; $msg = array( 'field' => $f, 'row' => $row ); $errors[] = WBString::populate(patI18n::dgettext('wombat','Required column "{FIELD}" is empty in line {ROW}!'), $msg); } } // editable fields foreach ($line as $k => $v) { if ('password' == $k) { continue; } // check editable if (!in_array($k, $editable)) { continue; } $save[$k] = trim($v); } if (!$ok) { continue; } $msg = array( 'row' => $row, 'email' => $line['email'], 'id' => null ); // check for existing user if (isset($save['nickname'])) { $check = array('nickname' => $save['nickname']); $msg['id'] = $storage->find($check); if (!empty($msg['id'])) { $ok = false; $import[] = WBString::populate(patI18n::dgettext('wombat','User account (id {ID}) for e-mail-address "{EMAIL}" already exists with nickname. (See line {ROW})'), $msg); } } if (isset($save['email'])) { $check = array('email' => $save['email']); $msg['id'] = $storage->find($check); if (!empty($msg['id'])) { $ok = false; $import[] = WBString::populate(patI18n::dgettext('wombat','User account (id {ID}) for e-mail address "{EMAIL}" already exists. (See line {ROW})'), $msg); } } if (!$ok) { continue; } $msg['id'] = $storage->set($save, true); $import[] = WBString::populate(patI18n::dgettext('wombat','Created user account (id {ID}) for e-mail address "{EMAIL}". (See line {ROW})'), $msg); $eData = $line; $eData['id'] = $msg['id']; WBEvent::trigger('user:imported', 'Created new user account {ID}', $eData); } $this->tmpl->addGlobalVar('error_count', count($errors)); if (0 < count($errors)) { $this->tmpl->addVar('error_list', 'error', $errors); } $this->tmpl->addGlobalVar('import_count', count($import)); if (0 < count($import)) { $this->tmpl->addVar('import_list', 'import', $import); } $this->csv->close(); $this->csv->unlink(); return true; } /** * Save user's primary data * * Update user's forename and surname * * @param patForms $form * @param array $values */ public function onUserEditValid($form, $values) { // enable, disable user if (isset($values['enabled'])) { if ($values['enabled']) { $this->patron->enable(); } else { $this->patron->disable(); } } if (isset($values['groups'])) { $this->patron->setGroups($values['groups']); } $save = array(); $keys = $this->config['editablecolumns']; foreach ($keys as $key) { if (!isset($values[$key])) { continue; } $save[$key] = $values[$key]; } $this->patron->set($save); if ($this->relTable) { $this->relTable->extract($values); $this->relTable->delete($this->patron->getId()); $this->relTable->add($this->patron->getId()); } return true; } /** * Save group's primary data * * Update group data * * @param patForms $form * @param array $values */ public function onGroupEditValid($form, $values) { // don't save groupname by default if ('useredit' == $this->config['action']) { if (!isset($values['changegroupname']) || empty($values['changegroupname']) && isset($values['groupname'])) { unset($values['groupname']); } } if ($this->relTable) { $this->relTable->extract($values); if ('__new' != $this->gid) { $this->relTable->delete($this->gid); } } if (isset($values['changegroupname'])) { unset($values['changegroupname']); } unset($values['id']); unset($values[$this->table->getIdentifier('group')]); $this->gid = $this->table->save('group', $this->gid, $values); if ($this->relTable) { $this->relTable->add($this->gid); } $this->tmpl->addGlobalVar('id', $this->gid); return true; } /** * location of form config * * Return sub directory where form element definitions are located * * @return string folder */ protected function getFormConfigDir() { return 'user/manager'; } /** * Add form rules to just created form * * @param patForms $form object * @param string name of the xml- and template-filename * @param array $elements list of elements current form * @return bool true on success */ protected function insertFormRules(&$form, $name, $elements) { return true; } /** * Add search criteria to clause * * See whether search options are set and add LIKE statements to clause. * Actually check in current request and configuration of search fields * * @param array $clause */ private function addSearchQuery(&$clause) { if (empty($this->config['searchfields'])) { return; } if ('' == $this->req->get('searchsubmit', '')) { return; } $search = array( 'submit' => 1, 'query' => $this->req->get('searchquery') ); if (empty($search['query'])) { return; } // add user input to template $this->tmpl->addGlobalVars($search, 'search_'); // normalize searchfields if (!is_array($this->config['searchfields'])) { $this->config['searchfields'] = array($this->config['searchfields']); } $query = trim($search['query']); $query = array_map('trim', explode(' ', $query)); foreach ($query as $q) { if (strlen($q) < 3) { continue; } $c = array(); foreach ($this->config['searchfields'] as $f) { $c[] = array( 'field' => $f, 'relation' => 'like', 'value' => $q ); } $clause[] = array( 'type' => 'complex', 'bond' => 'or', 'clause' => $c ); } } /** * start up relation table object * * See whether relations are needed and start relations table * object if neccessary. */ private function initRelationTable($type = 'user') { // load relation config $config = WBClass::create('WBConfig'); $config->load(sprintf('%s/%sEdit', $this->getFormConfigDir(), $type)); $conf = $config->get('relation', array()); if (empty($conf)) { return; } $this->relTable = WBClass::create('WBDatasource_RelationTable'); $this->relTable->setTable($this->table); $this->relTable->setConfig($type, $conf); } } ?>