/** * Assigns the selected director to the submission. */ function assignDirector($args, $request) { $this->validate($request); Locale::requireComponents(array(LOCALE_COMPONENT_PKP_MANAGER)); // manager.people.noneEnrolled $schedConf =& $request->getSchedConf(); $paperId = $request->getUserVar('paperId'); $directorId = $request->getUserVar('directorId'); $roleDao =& DAORegistry::getDAO('RoleDAO'); $isDirector = $roleDao->userHasRole($schedConf->getConferenceId(), $schedConf->getId(), $directorId, ROLE_ID_DIRECTOR) || $roleDao->userHasRole($schedConf->getConferenceId(), 0, $directorId, ROLE_ID_DIRECTOR); $isTrackDirector = $roleDao->userHasRole($schedConf->getConferenceId(), $schedConf->getId(), $directorId, ROLE_ID_TRACK_DIRECTOR) || $roleDao->userHasRole($schedConf->getConferenceId(), 0, $directorId, ROLE_ID_TRACK_DIRECTOR); if (isset($directorId) && $directorId != null && ($isDirector || $isTrackDirector)) { // A valid track director has already been chosen; // either prompt with a modifiable email or, if this // has been done, send the email and store the director // selection. $this->setupTemplate($request, DIRECTOR_TRACK_SUBMISSIONS, $paperId, 'summary'); // FIXME: Prompt for due date. if (DirectorAction::assignDirector($paperId, $directorId, $isDirector, $request->getUserVar('send'))) { $request->redirect(null, null, null, 'submission', $paperId); } } else { // Allow the user to choose a track director or director. $this->setupTemplate($request, DIRECTOR_TRACK_SUBMISSIONS, $paperId, 'summary'); $searchType = null; $searchMatch = null; $search = $request->getUserVar('search'); $searchInitial = $request->getUserVar('searchInitial'); if (!empty($search)) { $searchType = $request->getUserVar('searchField'); $searchMatch = $request->getUserVar('searchMatch'); } elseif (!empty($searchInitial)) { $searchInitial = String::strtoupper($searchInitial); $searchType = USER_FIELD_INITIAL; $search = $searchInitial; } $forDirectors = isset($args[0]) && $args[0] === 'director'; $rangeInfo =& Handler::getRangeInfo('directors', array($forDirectors, (string) $searchType, (string) $search, (string) $searchMatch)); $directorSubmissionDao =& DAORegistry::getDAO('DirectorSubmissionDAO'); if ($forDirectors) { $roleName = 'user.role.director'; $rolePath = 'director'; while (true) { $directors =& $directorSubmissionDao->getUsersNotAssignedToPaper($schedConf->getId(), $paperId, RoleDAO::getRoleIdFromPath('director'), $searchType, $search, $searchMatch, $rangeInfo); if ($directors->isInBounds()) { break; } unset($rangeInfo); $rangeInfo =& $directors->getLastPageRangeInfo(); unset($directors); } } else { $roleName = 'user.role.trackDirector'; $rolePath = 'trackDirector'; while (true) { $directors =& $directorSubmissionDao->getUsersNotAssignedToPaper($schedConf->getId(), $paperId, RoleDAO::getRoleIdFromPath('trackDirector'), $searchType, $search, $searchMatch, $rangeInfo); if ($directors->isInBounds()) { break; } unset($rangeInfo); $rangeInfo =& $directors->getLastPageRangeInfo(); unset($directors); } } $templateMgr =& TemplateManager::getManager(); $templateMgr->assign_by_ref('directors', $directors); $templateMgr->assign('roleName', $roleName); $templateMgr->assign('rolePath', $rolePath); $templateMgr->assign('paperId', $paperId); $trackDao =& DAORegistry::getDAO('TrackDAO'); $trackDirectorTracks =& $trackDao->getDirectorTracks($schedConf->getId()); $editAssignmentDao =& DAORegistry::getDAO('EditAssignmentDAO'); $directorStatistics = $editAssignmentDao->getDirectorStatistics($schedConf->getId()); $templateMgr->assign_by_ref('directorTracks', $trackDirectorTracks); $templateMgr->assign('directorStatistics', $directorStatistics); $templateMgr->assign('searchField', $searchType); $templateMgr->assign('searchMatch', $searchMatch); $templateMgr->assign('search', $search); $templateMgr->assign('searchInitial', $request->getUserVar('searchInitial')); $templateMgr->assign('fieldOptions', array(USER_FIELD_FIRSTNAME => 'user.firstName', USER_FIELD_LASTNAME => 'user.lastName', USER_FIELD_USERNAME => 'user.username', USER_FIELD_EMAIL => 'user.email')); $templateMgr->assign('alphaList', explode(' ', Locale::translate('common.alphaList'))); $templateMgr->assign('helpTopicId', 'editorial.directorsRole.summaryPage.submissionManagement'); $templateMgr->display('director/selectTrackDirector.tpl'); } }
/** * Retrieve a list of all reviewers not assigned to the specified paper. * @param $schedConfId int * @param $paperId int * @return array matching Users */ function &getReviewersNotAssignedToPaper($schedConfId, $paperId) { $users = array(); $result =& $this->retrieve('SELECT u.* FROM users u NATURAL JOIN roles r LEFT JOIN review_assignments a ON (a.reviewer_id = u.user_id AND a.paper_id = ?) WHERE r.sched_conf_id = ? AND r.role_id = ? AND a.paper_id IS NULL ORDER BY last_name, first_name', array($paperId, $schedConfId, RoleDAO::getRoleIdFromPath('reviewer'))); while (!$result->EOF) { $users[] =& $this->userDao->_returnUserFromRowWithData($result->GetRowAssoc(false)); $result->moveNext(); } $result->Close(); unset($result); return $users; }
function display(&$args) { $templateMgr =& TemplateManager::getManager(); parent::display($args); $templateMgr->assign('roleOptions', array('' => 'manager.people.doNotEnroll', 'manager' => 'user.role.manager', 'director' => 'user.role.director', 'trackDirector' => 'user.role.trackDirector', 'reviewer' => 'user.role.reviewer', 'author' => 'user.role.author', 'reader' => 'user.role.reader')); $roleDao =& DAORegistry::getDAO('RoleDAO'); $schedConf =& Request::getSchedConf(); switch (array_shift($args)) { case 'confirm': $this->import('UserXMLParser'); $templateMgr->assign('helpTopicId', 'conference.currentConference.importExport'); $sendNotify = (bool) Request::getUserVar('sendNotify'); $continueOnError = (bool) Request::getUserVar('continueOnError'); import('file.FileManager'); if (($userFile = FileManager::getUploadedFilePath('userFile')) !== false) { // Import the uploaded file $parser = new UserXMLParser($schedConf->getConferenceId(), $schedConf->getId()); $users =& $parser->parseData($userFile); $i = 0; $usersRoles = array(); foreach ($users as $user) { $usersRoles[$i] = array(); foreach ($user->getRoles() as $role) { array_push($usersRoles[$i], $role->getRoleName()); } $i++; } $templateMgr->assign_by_ref('users', $users); $templateMgr->assign_by_ref('usersRoles', $usersRoles); $templateMgr->assign('sendNotify', $sendNotify); $templateMgr->assign('continueOnError', $continueOnError); $templateMgr->assign('errors', $parser->errors); // Show confirmation form $templateMgr->display($this->getTemplatePath() . 'importUsersConfirm.tpl'); } break; case 'import': $this->import('UserXMLParser'); $userKeys = Request::getUserVar('userKeys'); if (!is_array($userKeys)) { $userKeys = array(); } $sendNotify = (bool) Request::getUserVar('sendNotify'); $continueOnError = (bool) Request::getUserVar('continueOnError'); $users = array(); foreach ($userKeys as $i) { $newUser = new ImportedUser(); $newUser->setFirstName(Request::getUserVar($i . '_firstName')); $newUser->setMiddleName(Request::getUserVar($i . '_middleName')); $newUser->setLastName(Request::getUserVar($i . '_lastName')); $newUser->setUsername(Request::getUserVar($i . '_username')); $newUser->setEmail(Request::getUserVar($i . '_email')); $locales = array(); if (Request::getUserVar($i . '_locales') != null || is_array(Request::getUserVar($i . '_locales'))) { foreach (Request::getUserVar($i . '_locales') as $locale) { array_push($locales, $locale); } } $newUser->setLocales($locales); $newUser->setSignature(Request::getUserVar($i . '_signature'), null); $newUser->setBiography(Request::getUserVar($i . '_biography'), null); $newUser->setInterests(Request::getUserVar($i . '_interests'), null); $newUser->setCountry(Request::getUserVar($i . '_country')); $newUser->setMailingAddress(Request::getUserVar($i . '_mailingAddress')); $newUser->setFax(Request::getUserVar($i . '_fax')); $newUser->setPhone(Request::getUserVar($i . '_phone')); $newUser->setUrl(Request::getUserVar($i . '_url')); $newUser->setAffiliation(Request::getUserVar($i . '_affiliation')); $newUser->setGender(Request::getUserVar($i . '_gender')); $newUser->setInitials(Request::getUserVar($i . '_initials')); $newUser->setSalutation(Request::getUserVar($i . '_salutation')); $newUser->setPassword(Request::getUserVar($i . '_password')); $newUser->setMustChangePassword(Request::getUserVar($i . '_mustChangePassword')); $newUser->setUnencryptedPassword(Request::getUserVar($i . '_unencryptedPassword')); $newUserRoles = Request::getUserVar($i . '_roles'); if (is_array($newUserRoles) && count($newUserRoles) > 0) { foreach ($newUserRoles as $newUserRole) { if ($newUserRole != '') { $role = new Role(); $role->setRoleId(RoleDAO::getRoleIdFromPath($newUserRole)); $newUser->AddRole($role); } } } array_push($users, $newUser); } $parser = new UserXMLParser($schedConf->getConferenceId(), $schedConf->getId()); $parser->setUsersToImport($users); if (!$parser->importUsers($sendNotify, $continueOnError)) { // Failures occurred $templateMgr->assign('isError', true); $templateMgr->assign('errors', $parser->getErrors()); } $templateMgr->assign('importedUsers', $parser->getImportedUsers()); $templateMgr->display($this->getTemplatePath() . 'importUsersResults.tpl'); break; case 'exportAll': $this->import('UserExportDom'); $users =& $roleDao->getUsersBySchedConfId($schedConf->getId()); $users =& $users->toArray(); $doc =& UserExportDom::exportUsers($schedConf, $users); header("Content-Type: application/xml"); header("Cache-Control: private"); header("Content-Disposition: attachment; filename=\"users.xml\""); echo XMLCustomWriter::getXML($doc); break; case 'exportByRole': $this->import('UserExportDom'); $users = array(); $rolePaths = array(); foreach (Request::getUserVar('roles') as $rolePath) { $roleId = $roleDao->getRoleIdFromPath($rolePath); $thisRoleUsers =& $roleDao->getUsersByRoleId($roleId, $schedConf->getId()); foreach ($thisRoleUsers->toArray() as $user) { $users[$user->getId()] = $user; } $rolePaths[] = $rolePath; } $users = array_values($users); $doc =& UserExportDom::exportUsers($schedConf, $users, $rolePaths); header("Content-Type: application/xml"); header("Cache-Control: private"); header("Content-Disposition: attachment; filename=\"users.xml\""); echo XMLCustomWriter::getXML($doc); break; default: $this->setBreadcrumbs(); $templateMgr->display($this->getTemplatePath() . 'index.tpl'); } }
/** * Assigns the selected editor to the submission. */ function assignEditor($args, $request) { $this->validate(); AppLocale::requireComponents(LOCALE_COMPONENT_PKP_MANAGER); // manager.people.noneEnrolled $journal =& $request->getJournal(); $articleId = $request->getUserVar('articleId'); $editorId = $request->getUserVar('editorId'); $roleDao =& DAORegistry::getDAO('RoleDAO'); $isSectionEditor = $roleDao->userHasRole($journal->getId(), $editorId, ROLE_ID_SECTION_EDITOR); $isEditor = $roleDao->userHasRole($journal->getId(), $editorId, ROLE_ID_EDITOR); if (isset($editorId) && $editorId != null && ($isEditor || $isSectionEditor)) { // A valid section editor has already been chosen; // either prompt with a modifiable email or, if this // has been done, send the email and store the editor // selection. $this->setupTemplate(EDITOR_SECTION_SUBMISSIONS, $articleId, 'summary'); // FIXME: Prompt for due date. if (EditorAction::assignEditor($articleId, $editorId, $isEditor, $request->getUserVar('send'), $request)) { Request::redirect(null, null, 'submission', $articleId); } } else { // Allow the user to choose a section editor or editor. $this->setupTemplate(EDITOR_SECTION_SUBMISSIONS, $articleId, 'summary'); $searchType = null; $searchMatch = null; $search = $request->getUserVar('search'); $searchInitial = $request->getUserVar('searchInitial'); if (!empty($search)) { $searchType = $request->getUserVar('searchField'); $searchMatch = $request->getUserVar('searchMatch'); } elseif (!empty($searchInitial)) { $searchInitial = String::strtoupper($searchInitial); $searchType = USER_FIELD_INITIAL; $search = $searchInitial; } $rangeInfo =& $this->getRangeInfo('editors'); $editorSubmissionDao =& DAORegistry::getDAO('EditorSubmissionDAO'); if (isset($args[0]) && $args[0] === 'editor') { $roleName = 'user.role.editor'; $rolePath = 'editor'; $editors =& $editorSubmissionDao->getUsersNotAssignedToArticle($journal->getId(), $articleId, RoleDAO::getRoleIdFromPath('editor'), $searchType, $search, $searchMatch, $rangeInfo); } else { $roleName = 'user.role.sectionEditor'; $rolePath = 'sectionEditor'; $editors =& $editorSubmissionDao->getUsersNotAssignedToArticle($journal->getId(), $articleId, RoleDAO::getRoleIdFromPath('sectionEditor'), $searchType, $search, $searchMatch, $rangeInfo); } $templateMgr =& TemplateManager::getManager(); $templateMgr->assign_by_ref('editors', $editors); $templateMgr->assign('roleName', $roleName); $templateMgr->assign('rolePath', $rolePath); $templateMgr->assign('articleId', $articleId); $sectionDao =& DAORegistry::getDAO('SectionDAO'); $sectionEditorSections =& $sectionDao->getEditorSections($journal->getId()); $editAssignmentDao =& DAORegistry::getDAO('EditAssignmentDAO'); $editorStatistics = $editAssignmentDao->getEditorStatistics($journal->getId()); $templateMgr->assign_by_ref('editorSections', $sectionEditorSections); $templateMgr->assign('editorStatistics', $editorStatistics); $templateMgr->assign('searchField', $searchType); $templateMgr->assign('searchMatch', $searchMatch); $templateMgr->assign('search', $search); $templateMgr->assign('searchInitial', Request::getUserVar('searchInitial')); $templateMgr->assign('fieldOptions', array(USER_FIELD_FIRSTNAME => 'user.firstName', USER_FIELD_LASTNAME => 'user.lastName', USER_FIELD_USERNAME => 'user.username', USER_FIELD_EMAIL => 'user.email')); $templateMgr->assign('alphaList', explode(' ', __('common.alphaList'))); $templateMgr->assign('helpTopicId', 'editorial.editorsRole.submissionSummary.submissionManagement'); $templateMgr->display('editor/selectSectionEditor.tpl'); } }
/** * Retrieve a list of all copyeditors not assigned to the specified article. * @param $journalId int * @param $articleId int * @return array matching Users */ function &getCopyeditorsNotAssignedToArticle($journalId, $articleId, $searchType = null, $search = null, $searchMatch = null) { $users = array(); $paramArray = array('interests', $articleId, ASSOC_TYPE_ARTICLE, 'SIGNOFF_COPYEDITING_INITIAL', $journalId, RoleDAO::getRoleIdFromPath('copyeditor')); $searchSql = ''; $searchTypeMap = array(USER_FIELD_FIRSTNAME => 'u.first_name', USER_FIELD_LASTNAME => 'u.last_name', USER_FIELD_USERNAME => 'u.username', USER_FIELD_EMAIL => 'u.email', USER_FIELD_INTERESTS => 's.setting_value'); if (isset($search) && isset($searchTypeMap[$searchType])) { $fieldName = $searchTypeMap[$searchType]; switch ($searchMatch) { case 'is': $searchSql = "AND LOWER({$fieldName}) = LOWER(?)"; $paramArray[] = $search; break; case 'contains': $searchSql = "AND LOWER({$fieldName}) LIKE LOWER(?)"; $paramArray[] = '%' . $search . '%'; break; case 'startsWith': $searchSql = "AND LOWER({$fieldName}) LIKE LOWER(?)"; $paramArray[] = $search . '%'; break; } } elseif (isset($search)) { switch ($searchType) { case USER_FIELD_USERID: $searchSql = 'AND user_id=?'; $paramArray[] = $search; break; case USER_FIELD_INITIAL: $searchSql = 'AND (LOWER(last_name) LIKE LOWER(?) OR LOWER(username) LIKE LOWER(?))'; $paramArray[] = $search . '%'; $paramArray[] = $search . '%'; break; } } $result =& $this->retrieve('SELECT u.* FROM users u LEFT JOIN user_settings s ON (u.user_id = s.user_id AND s.setting_name = ?) LEFT JOIN roles r ON (r.user_id = u.user_id) LEFT JOIN signoffs sci ON (sci.user_id = u.user_id AND sci.assoc_id = ? AND sci.assoc_type = ? AND sci.symbolic = ?) WHERE r.journal_id = ? AND r.role_id = ? AND sci.assoc_id IS NULL ' . $searchSql . ' ORDER BY last_name, first_name', $paramArray); while (!$result->EOF) { $users[] =& $this->userDao->_returnUserFromRowWithData($result->GetRowAssoc(false)); $result->moveNext(); } $result->Close(); unset($result); return $users; }
/** * Retrieve a list of all copyeditors not assigned to the specified article. * @param $journalId int * @param $articleId int * @return array matching Users */ function &getCopyeditorsNotAssignedToArticle($journalId, $articleId, $searchType = null, $search = null, $searchMatch = null) { $users = array(); $paramArray = array('interests', $articleId, $journalId, RoleDAO::getRoleIdFromPath('copyeditor')); $searchSql = ''; if (isset($search)) { switch ($searchType) { case USER_FIELD_USERID: $searchSql = 'AND user_id=?'; $paramArray[] = $search; break; case USER_FIELD_FIRSTNAME: $searchSql = 'AND LOWER(first_name) ' . ($searchMatch == 'is' ? '=' : 'LIKE') . ' LOWER(?)'; $paramArray[] = $searchMatch == 'is' ? $search : '%' . $search . '%'; break; case USER_FIELD_LASTNAME: $searchSql = 'AND LOWER(last_name) ' . ($searchMatch == 'is' ? '=' : 'LIKE') . ' LOWER(?)'; $paramArray[] = $searchMatch == 'is' ? $search : '%' . $search . '%'; break; case USER_FIELD_USERNAME: $searchSql = 'AND LOWER(username) ' . ($searchMatch == 'is' ? '=' : 'LIKE') . ' LOWER(?)'; $paramArray[] = $searchMatch == 'is' ? $search : '%' . $search . '%'; break; case USER_FIELD_EMAIL: $searchSql = 'AND LOWER(email) ' . ($searchMatch == 'is' ? '=' : 'LIKE') . ' LOWER(?)'; $paramArray[] = $searchMatch == 'is' ? $search : '%' . $search . '%'; break; case USER_FIELD_INTERESTS: $searchSql = 'AND LOWER(setting_value) ' . ($searchMatch == 'is' ? '=' : 'LIKE') . ' LOWER(?)'; $paramArray[] = $searchMatch == 'is' ? $search : '%' . $search . '%'; break; case USER_FIELD_INITIAL: $searchSql = 'AND (LOWER(last_name) LIKE LOWER(?) OR LOWER(username) LIKE LOWER(?))'; $paramArray[] = $search . '%'; $paramArray[] = $search . '%'; break; } } $result =& $this->retrieve('SELECT u.* FROM users u LEFT JOIN user_settings s ON (u.user_id = s.user_id AND s.setting_name = ?) LEFT JOIN roles r ON (r.user_id = u.user_id) LEFT JOIN copyed_assignments a ON (a.copyeditor_id = u.user_id AND a.article_id = ?) WHERE r.journal_id = ? AND r.role_id = ? AND a.article_id IS NULL ' . $searchSql . ' ORDER BY last_name, first_name', $paramArray); while (!$result->EOF) { $users[] =& $this->userDao->_returnUserFromRowWithData($result->GetRowAssoc(false)); $result->moveNext(); } $result->Close(); unset($result); return $users; }
/** * Retrieve a list of all reviewers along with information about their current status with respect to an article's current decision. * @param $journalId int * @param $decisionId int * @param $extReviewer bool indicate if the kind of reviewers * @param $searchType int USER_FIELD_... * @param $search string * @param $searchMatch string "is" or "contains" or "startsWith" * @param $rangeInfo RangeInfo optional * @return DAOResultFactory containing matching Users * Last Modified: EL on Febraury 16th 2013 * Separation of External Reviewers */ function &getReviewersForArticle($journalId, $decisionId, $sectionId, $extReviewer = false, $searchType = null, $search = null, $searchMatch = null, $rangeInfo = null, $sortBy = 'reviewerName', $sortDirection = SORT_DIRECTION_ASC) { $paramArray = array($decisionId, ASSOC_TYPE_USER, 'interest', $journalId, RoleDAO::getRoleIdFromPath('reviewer')); if ($extReviewer == true) { $searchSql = ' AND er.section_id = 0 '; } else { $searchSql = ' AND er.section_id = ? '; $paramArray[] = $sectionId; } $searchTypeMap = array(USER_FIELD_FIRSTNAME => 'u.first_name', USER_FIELD_LASTNAME => 'u.last_name', USER_FIELD_USERNAME => 'u.username', USER_FIELD_EMAIL => 'u.email', USER_FIELD_INTERESTS => 'cves.setting_value'); if (isset($search) && isset($searchTypeMap[$searchType])) { $fieldName = $searchTypeMap[$searchType]; switch ($searchMatch) { case 'is': $searchSql .= "AND LOWER({$fieldName}) = LOWER(?)"; $paramArray[] = $search; break; case 'contains': $searchSql .= "AND LOWER({$fieldName}) LIKE LOWER(?)"; $paramArray[] = '%' . $search . '%'; break; case 'startsWith': $searchSql .= "AND LOWER({$fieldName}) LIKE LOWER(?)"; $paramArray[] = $search . '%'; break; } } elseif (isset($search)) { switch ($searchType) { case USER_FIELD_USERID: $searchSql .= ' AND user_id=?'; $paramArray[] = $search; break; case USER_FIELD_INITIAL: $searchSql .= ' AND (LOWER(last_name) LIKE LOWER(?) OR LOWER(username) LIKE LOWER(?))'; $paramArray[] = $search . '%'; $paramArray[] = $search . '%'; break; } } $result =& $this->retrieveRange('SELECT DISTINCT u.user_id, u.last_name, ar.review_id, AVG(ra.quality) AS average_quality, COUNT(ac.review_id) AS completed, COUNT(ai.review_id) AS incomplete, MAX(ac.date_notified) AS latest, AVG(ac.date_completed-ac.date_notified) AS average FROM users u LEFT JOIN review_assignments ra ON (ra.reviewer_id = u.user_id) LEFT JOIN review_assignments ac ON (ac.reviewer_id = u.user_id AND ac.date_completed IS NOT NULL) LEFT JOIN review_assignments ai ON (ai.reviewer_id = u.user_id AND ai.date_completed IS NULL) LEFT JOIN review_assignments ar ON (ar.reviewer_id = u.user_id AND ar.cancelled = 0 AND ar.decision_id = ?) LEFT JOIN roles r ON (r.user_id = u.user_id) LEFT JOIN section_decisions sd ON (ra.decision_id = sd.section_decision_id) LEFT JOIN controlled_vocabs cv ON (cv.assoc_type = ? AND cv.assoc_id = u.user_id AND cv.symbolic = ?) LEFT JOIN controlled_vocab_entries cve ON (cve.controlled_vocab_id = cv.controlled_vocab_id) LEFT JOIN controlled_vocab_entry_settings cves ON (cves.controlled_vocab_entry_id = cve.controlled_vocab_entry_id) LEFT JOIN erc_reviewers er ON (er.user_id = u.user_id) WHERE u.user_id = r.user_id AND r.journal_id = ? AND r.role_id = ? ' . $searchSql . ' GROUP BY u.user_id, u.last_name, ar.review_id' . ($sortBy ? ' ORDER BY ' . $this->getSortMapping($sortBy) . ' ' . $this->getDirectionMapping($sortDirection) : ''), $paramArray, $rangeInfo); $returner = new DAOResultFactory($result, $this, '_returnReviewerUserFromRow'); return $returner; }
/** * Retrieve a list of all reviewers not assigned to the specified article. * @param $journalId int * @param $articleId int * @return array matching Users */ function &getReviewersNotAssignedToArticle($journalId, $articleId) { $users = array(); $result =& $this->retrieve('SELECT u.* FROM users u LEFT JOIN roles r ON (r.user_id = u.user_id) LEFT JOIN review_assignments a ON (a.reviewer_id = u.user_id AND a.article_id = ?) WHERE r.journal_id = ? AND r.role_id = ? AND a.article_id IS NULL ORDER BY last_name, first_name', array($articleId, $journalId, RoleDAO::getRoleIdFromPath('reviewer'))); while (!$result->EOF) { $users[] =& $this->userDao->_returnUserFromRowWithData($result->GetRowAssoc(false)); $result->moveNext(); } $result->Close(); unset($result); return $users; }