• Main Page
  • Modules
  • Classes
  • Files
  • File List

controllers/grid/users/reviewer/ReviewerGridHandler.inc.php

00001 <?php
00002 
00015 // import grid base classes
00016 import('lib.pkp.classes.controllers.grid.GridHandler');
00017 
00018 // import reviewer grid specific classes
00019 import('controllers.grid.users.reviewer.ReviewerGridCellProvider');
00020 import('controllers.grid.users.reviewer.ReviewerGridRow');
00021 
00022 // Reviewer selection types
00023 define('REVIEWER_SELECT_SEARCH_BY_NAME',     0x00000001);
00024 define('REVIEWER_SELECT_ADVANCED_SEARCH',    0x00000002);
00025 define('REVIEWER_SELECT_CREATE',          0x00000003);
00026 define('REVIEWER_SELECT_ENROLL_EXISTING',    0x00000004);
00027 
00028 class ReviewerGridHandler extends GridHandler {
00029 
00031    var $_monograph;
00032 
00034    var $_stageId;
00035 
00036 
00040    function ReviewerGridHandler() {
00041       parent::GridHandler();
00042 
00043       $allOperations = array_merge($this->_getReviewAssignmentOps(), $this->_getReviewRoundOps());
00044 
00045       $this->addRoleAssignment(
00046          array(ROLE_ID_PRESS_MANAGER),
00047          $allOperations
00048       );
00049 
00050       // Remove operations related to creation and enrollment of users.
00051       $nonPressManagerOperations = array_flip($allOperations);
00052       unset($nonPressManagerOperations['createReviewer']);
00053       unset($nonPressManagerOperations['enrollReviewer']);
00054       $nonPressManagerOperations = array_flip($nonPressManagerOperations);
00055 
00056       $this->addRoleAssignment(
00057          array(ROLE_ID_SERIES_EDITOR, ROLE_ID_PRESS_ASSISTANT),
00058          $nonPressManagerOperations
00059       );
00060    }
00061 
00062 
00063    //
00064    // Getters and Setters
00065    //
00070    function &getMonograph() {
00071       return $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00072    }
00073 
00078    function getStageId() {
00079       return $this->_stageId;
00080    }
00081 
00086    function &getReviewRound() {
00087       $reviewRound =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ROUND);
00088       if (is_a($reviewRound, 'ReviewRound')) {
00089          return $reviewRound;
00090       } else {
00091          $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00092          $reviewRoundId = $reviewAssignment->getReviewRoundId();
00093          $reviewRoundDao =& DAORegistry::getDAO('ReviewRoundDAO');
00094          return $reviewRoundDao->getReviewRoundById($reviewRoundId);
00095       }
00096    }
00097 
00098 
00099    //
00100    // Overridden methods from PKPHandler
00101    //
00108    function authorize(&$request, $args, $roleAssignments) {
00109       $stageId = $request->getUserVar('stageId'); // This is being validated in OmpWorkflowStageAccessPolicy
00110 
00111       // Not all actions need a stageId. Some work off the reviewAssignment which has the type and round.
00112       $this->_stageId = (int)$stageId;
00113 
00114       // Get the stage access policy
00115       import('classes.security.authorization.OmpWorkflowStageAccessPolicy');
00116       $ompWorkflowStageAccessPolicy = new OmpWorkflowStageAccessPolicy($request, $args, $roleAssignments, 'monographId', $stageId);
00117 
00118       // Add policy to ensure there is a review round id.
00119       import('classes.security.authorization.internal.ReviewRoundRequiredPolicy');
00120       $ompWorkflowStageAccessPolicy->addPolicy(new ReviewRoundRequiredPolicy($request, $args, 'reviewRoundId', $this->_getReviewRoundOps()));
00121 
00122       // Add policy to ensure there is a review assignment for certain operations.
00123       import('classes.security.authorization.internal.ReviewAssignmentRequiredPolicy');
00124       $ompWorkflowStageAccessPolicy->addPolicy(new ReviewAssignmentRequiredPolicy($request, $args, 'reviewAssignmentId', $this->_getReviewAssignmentOps()));
00125       $this->addPolicy($ompWorkflowStageAccessPolicy);
00126 
00127       return parent::authorize($request, $args, $roleAssignments);
00128    }
00129 
00130    /*
00131     * Configure the grid
00132     * @param $request PKPRequest
00133     */
00134    function initialize(&$request) {
00135       parent::initialize($request);
00136 
00137       // Load submission-specific translations
00138       AppLocale::requireComponents(
00139          LOCALE_COMPONENT_PKP_SUBMISSION,
00140          LOCALE_COMPONENT_PKP_MANAGER,
00141          LOCALE_COMPONENT_PKP_USER,
00142          LOCALE_COMPONENT_OMP_EDITOR
00143       );
00144 
00145       $this->setTitle('user.role.reviewers');
00146       $this->setInstructions('editor.monograph.review.reviewersDescription');
00147 
00148       // Grid actions
00149       import('lib.pkp.classes.linkAction.request.AjaxModal');
00150       $router =& $request->getRouter();
00151       $actionArgs = array_merge($this->getRequestArgs(), array('selectionType' => REVIEWER_SELECT_SEARCH_BY_NAME));
00152       $this->addAction(
00153          new LinkAction(
00154             'addReviewer',
00155             new AjaxModal(
00156                $router->url($request, null, null, 'showReviewerForm', null, $actionArgs),
00157                __('editor.monograph.addReviewer'),
00158                'modal_add_user'
00159                ),
00160             __('editor.monograph.addReviewer'),
00161             'add_user'
00162             )
00163          );
00164 
00165       // Columns
00166       $cellProvider = new ReviewerGridCellProvider();
00167       $this->addColumn(
00168          new GridColumn(
00169             'name',
00170             'user.name',
00171             null,
00172             'controllers/grid/gridCell.tpl',
00173             $cellProvider,
00174             array('width' => 60)
00175          )
00176       );
00177 
00178       // Add a column for the status of the review.
00179       $this->addColumn(
00180          new GridColumn(
00181             'considered',
00182             'common.considered',
00183             null,
00184             'controllers/grid/common/cell/statusCell.tpl',
00185             $cellProvider,
00186             array('hoverTitle' => true)
00187          )
00188       );
00189    }
00190 
00191 
00192    //
00193    // Overridden methods from GridHandler
00194    //
00199    function &getRowInstance() {
00200       $row = new ReviewerGridRow();
00201       return $row;
00202    }
00203 
00207    function getRequestArgs() {
00208       $monograph =& $this->getMonograph();
00209       $reviewRound =& $this->getReviewRound();
00210       return array(
00211          'monographId' => $monograph->getId(),
00212          'stageId' => $this->getStageId(),
00213          'reviewRoundId' => $reviewRound->getId()
00214       );
00215    }
00216 
00220    function loadData($request, $filter) {
00221       // Get the existing review assignments for this monograph
00222       $monograph =& $this->getMonograph(); /* @var $monograph SeriesEditorSubmission */
00223       $reviewRound =& $this->getReviewRound();
00224       return $monograph->getReviewAssignments($this->getStageId(), $reviewRound->getRound());
00225    }
00226 
00227 
00228    //
00229    // Public actions
00230    //
00237    function showReviewerForm($args, &$request) {
00238       $json = new JSONMessage(true, $this->_fetchReviewerForm($args, $request));
00239       return $json->getString();
00240    }
00241 
00248    function reloadReviewerForm($args, &$request) {
00249       $json = new JSONMessage(true);
00250       $json->setEvent('refreshForm', $this->_fetchReviewerForm($args, $request));
00251       return $json->getString();
00252    }
00253 
00260    function createReviewer($args, &$request) {
00261       return $this->updateReviewer($args, $request);
00262    }
00263 
00270    function enrollReviewer($args, &$request) {
00271       return $this->updateReviewer($args, $request);
00272    }
00273 
00280    function updateReviewer($args, &$request) {
00281       $selectionType = $request->getUserVar('selectionType');
00282       $formClassName = $this->_getReviewerFormClassName($selectionType);
00283 
00284       // Form handling
00285       import('controllers.grid.users.reviewer.form.' . $formClassName );
00286       $reviewerForm = new $formClassName($this->getMonograph(), $this->getReviewRound());
00287       $reviewerForm->readInputData();
00288       if ($reviewerForm->validate()) {
00289          $reviewAssignment =& $reviewerForm->execute($args, $request);
00290 
00291          return DAO::getDataChangedEvent($reviewAssignment->getId());
00292       } else {
00293          // There was an error, redisplay the form
00294          $json = new JSONMessage(true, $reviewerForm->fetch($request));
00295       }
00296       return $json->getString();
00297    }
00298 
00305    function deleteReviewer($args, &$request) {
00306       // Delete the review assignment.
00307       // NB: SeriesEditorAction::clearReview() will check that this review
00308       // id is actually attached to the monograph so no need for further
00309       // validation here.
00310       $monograph =& $this->getMonograph();
00311       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00312       import('classes.submission.seriesEditor.SeriesEditorAction');
00313       $seriesEditorAction = new SeriesEditorAction();
00314       $result = $seriesEditorAction->clearReview($request, $monograph->getId(), $reviewAssignment->getId());
00315 
00316       // Render the result.
00317       if ($result) {
00318          return DAO::getDataChangedEvent($reviewAssignment->getId());
00319       } else {
00320          $json = new JSONMessage(false, __('editor.review.errorDeletingReviewer'));
00321          return $json->getString();
00322       }
00323    }
00324 
00325 
00332    function getReviewersNotAssignedToMonograph($args, &$request) {
00333       $press =& $request->getPress();
00334       $monograph =& $this->getMonograph();
00335       $stageId = $this->getAuthorizedContextObject(ASSOC_TYPE_WORKFLOW_STAGE);
00336       $reviewRound =& $this->getReviewRound();
00337       $round = $reviewRound->getRound();
00338       $term = $request->getUserVar('term');
00339 
00340       $seriesEditorSubmissionDao =& DAORegistry::getDAO('SeriesEditorSubmissionDAO'); /* @var $seriesEditorSubmissionDao SeriesEditorSubmissionDAO */
00341       $reviewers =& $seriesEditorSubmissionDao->getReviewersNotAssignedToMonograph($press->getId(), $monograph->getId(), $reviewRound, $term);
00342 
00343       $reviewerList = array();
00344       while($reviewer =& $reviewers->next()) {
00345          $reviewerList[] = array('label' => $reviewer->getFullName(), 'value' => $reviewer->getId());
00346          unset($reviewer);
00347       }
00348 
00349       if (count($reviewerList) == 0) {
00350          $reviewerList[] = array('label' => __('common.noMatches'), 'value' => '');
00351       }
00352 
00353       $json = new JSONMessage(true, $reviewerList);
00354       return $json->getString();
00355    }
00356 
00363    function getUsersNotAssignedAsReviewers($args, &$request) {
00364       $press =& $request->getPress();
00365       $term = $request->getUserVar('term');
00366 
00367       $userGroupDao =& DAORegistry::getDAO('UserGroupDAO'); /* @var $userGroupDao UserGroupDAO */
00368       $monograph =& $this->getMonograph();
00369 
00370       $users =& $userGroupDao->getUsersNotInRole(ROLE_ID_REVIEWER, $press->getId(), $term);
00371 
00372       $userList = array();
00373       while ($user =& $users->next()) {
00374          $userList[] = array('label' => $user->getFullName(), 'value' => $user->getId());
00375          unset($user);
00376       }
00377 
00378       if (count($userList) == 0) {
00379          return $this->noAutocompleteResults();
00380       }
00381 
00382       $json = new JSONMessage(true, $userList);
00383       return $json->getString();
00384    }
00385 
00393    function readReview($args, &$request) {
00394       $templateMgr =& TemplateManager::getManager();
00395 
00396       // Retrieve monograph.
00397       $templateMgr->assign_by_ref('monograph', $this->getMonograph());
00398 
00399       // Retrieve review assignment.
00400       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00401       $templateMgr->assign_by_ref('reviewAssignment', $reviewAssignment);
00402 
00403       // Retrieve reviewer comment.
00404       $monographCommentDao =& DAORegistry::getDAO('MonographCommentDAO');
00405       $monographComments =& $monographCommentDao->getReviewerCommentsByReviewerId($reviewAssignment->getReviewerId(), $reviewAssignment->getSubmissionId(), $reviewAssignment->getId());
00406       $templateMgr->assign_by_ref('reviewerComment', $monographComments->next());
00407 
00408       // Render the response.
00409       return $templateMgr->fetchJson('controllers/grid/users/reviewer/readReview.tpl');
00410    }
00411 
00418    function unconsiderReview($args, &$request) {
00419 
00420       // This resets the state of the review to 'unread', but does not delete note history.
00421       $monograph =& $this->getMonograph();
00422       $user =& $request->getUser();
00423       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00424       $reviewAssignmentDao =& DAORegistry::getDAO('ReviewAssignmentDAO');
00425 
00426       $reviewAssignment->setUnconsidered(REVIEW_ASSIGNMENT_UNCONSIDERED);
00427       $result = $reviewAssignmentDao->updateReviewAssignment($reviewAssignment);
00428       $this->_updateReviewRoundStatus($reviewAssignment);
00429 
00430       // log the unconsider.
00431       import('classes.log.MonographLog');
00432       import('classes.log.MonographEventLogEntry');
00433 
00434       $entry = new MonographEventLogEntry();
00435       $entry->setMonographId($reviewAssignment->getSubmissionId());
00436       $entry->setUserId($user->getId());
00437       $entry->setDateLogged(Core::getCurrentDate());
00438       $entry->setEventType(MONOGRAPH_LOG_REVIEW_UNCONSIDERED);
00439 
00440       MonographLog::logEvent(
00441             $request,
00442             $monograph,
00443             MONOGRAPH_LOG_REVIEW_UNCONSIDERED,
00444             'log.review.reviewUnconsidered',
00445             array(
00446                'editorName' => $user->getFullName(),
00447                'monographId' => $monograph->getId(),
00448                'round' => $reviewAssignment->getRound(),
00449             )
00450       );
00451 
00452       // Render the result.
00453       if ($result) {
00454          return DAO::getDataChangedEvent($reviewAssignment->getId());
00455       } else {
00456          $json = new JSONMessage(false, __('editor.review.errorUnconsideringReview'));
00457          return $json->getString();
00458       }
00459    }
00460 
00467    function reviewRead($args, &$request) {
00468       // Retrieve review assignment.
00469       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT); /* @var $reviewAssignment ReviewAssignment */
00470 
00471       // Mark the latest read date of the review by the editor.
00472       $user =& $request->getUser();
00473       $viewsDao =& DAORegistry::getDAO('ViewsDAO');
00474       $viewsDao->recordView(ASSOC_TYPE_REVIEW_RESPONSE, $reviewAssignment->getId(), $user->getId());
00475 
00476       // if the review assignment had been unconsidered, update the flag.
00477       if ($reviewAssignment->getUnconsidered() == REVIEW_ASSIGNMENT_UNCONSIDERED) {
00478          $reviewAssignmentDao =& DAORegistry::getDAO('ReviewAssignmentDAO');
00479          $reviewAssignment->setUnconsidered(REVIEW_ASSIGNMENT_UNCONSIDERED_READ);
00480          $reviewAssignmentDao->updateReviewAssignment($reviewAssignment);
00481       }
00482 
00483       $this->_updateReviewRoundStatus($reviewAssignment);
00484 
00485       return DAO::getDataChangedEvent($reviewAssignment->getId());
00486    }
00487 
00494    function editThankReviewer($args, &$request) {
00495       // Identify the review assignment being updated.
00496       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00497 
00498       // Initialize form.
00499       import('controllers.grid.users.reviewer.form.ThankReviewerForm');
00500       $thankReviewerForm = new ThankReviewerForm($reviewAssignment);
00501       $thankReviewerForm->initData($args, $request);
00502 
00503       // Render form.
00504       $json = new JSONMessage(true, $thankReviewerForm->fetch($request));
00505       return $json->getString();
00506    }
00507 
00514    function thankReviewer($args, &$request) {
00515       // Identify the review assignment being updated.
00516       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00517 
00518       // Form handling
00519       import('controllers.grid.users.reviewer.form.ThankReviewerForm');
00520       $thankReviewerForm = new ThankReviewerForm($reviewAssignment);
00521       $thankReviewerForm->readInputData();
00522       if ($thankReviewerForm->validate()) {
00523          $thankReviewerForm->execute($args, $request);
00524          $json = new JSONMessage(true);
00525          // Insert a trivial notification to indicate the reviewer was reminded successfully.
00526          $currentUser =& $request->getUser();
00527          $notificationMgr = new NotificationManager();
00528          $messageKey = $thankReviewerForm->getData('skipEmail') ? __('notification.reviewAcknowledged') : __('notification.sentNotification');
00529          $notificationMgr->createTrivialNotification($currentUser->getId(), NOTIFICATION_TYPE_SUCCESS, array('contents' => $messageKey));
00530       } else {
00531          $json = new JSONMessage(false, __('editor.review.thankReviewerError'));
00532       }
00533 
00534       $this->_updateReviewRoundStatus($reviewAssignment);
00535       return DAO::getDataChangedEvent($reviewAssignment->getId());
00536    }
00537 
00544    function editReminder($args, &$request) {
00545       // Identify the review assignment being updated.
00546       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00547 
00548       // Initialize form.
00549       import('controllers.grid.users.reviewer.form.ReviewReminderForm');
00550       $reviewReminderForm = new ReviewReminderForm($reviewAssignment);
00551       $reviewReminderForm->initData($args, $request);
00552 
00553       // Render form.
00554       $json = new JSONMessage(true, $reviewReminderForm->fetch($request));
00555       return $json->getString();
00556    }
00557 
00564    function sendReminder($args, &$request) {
00565       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00566 
00567       // Form handling
00568       import('controllers.grid.users.reviewer.form.ReviewReminderForm');
00569       $reviewReminderForm = new ReviewReminderForm($reviewAssignment);
00570       $reviewReminderForm->readInputData();
00571       if ($reviewReminderForm->validate()) {
00572          $reviewReminderForm->execute($args, $request);
00573          $json = new JSONMessage(true);
00574          // Insert a trivial notification to indicate the reviewer was reminded successfully.
00575          $currentUser =& $request->getUser();
00576          $notificationMgr = new NotificationManager();
00577          $notificationMgr->createTrivialNotification($currentUser->getId(), NOTIFICATION_TYPE_SUCCESS, array('contents' => __('notification.sentNotification')));
00578       } else {
00579          $json = new JSONMessage(false, __('editor.review.reminderError'));
00580       }
00581       return $json->getString();
00582    }
00583 
00590    function sendEmail($args, &$request) {
00591       $user =& $request->getUser();
00592 
00593       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00594 
00595       // Form handling.
00596       import('controllers.grid.settings.user.form.UserEmailForm');
00597       $userEmailForm = new UserEmailForm($reviewAssignment->getReviewerId());
00598       $userEmailForm->initData($args, $request);
00599 
00600       $json = new JSONMessage(true, $userEmailForm->display($args, $request));
00601       return $json->getString();
00602    }
00603 
00604 
00611    function reviewHistory($args, &$request) {
00612       $user =& $request->getUser();
00613 
00614       $reviewAssignment =& $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ASSIGNMENT);
00615 
00616       $templateMgr =& TemplateManager::getManager();
00617       $templateMgr->assign_by_ref('reviewAssignment', $reviewAssignment);
00618 
00619 
00620       return $templateMgr->fetchJson('workflow/reviewHistory.tpl');
00621    }
00622 
00623 
00624    //
00625    // Private helper methods
00626    //
00633    function _fetchReviewerForm($args, &$request) {
00634       $selectionType = $request->getUserVar('selectionType');
00635       assert(!empty($selectionType));
00636       $formClassName = $this->_getReviewerFormClassName($selectionType);
00637       $userRoles = $this->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
00638 
00639       // Form handling.
00640       import('controllers.grid.users.reviewer.form.' . $formClassName );
00641       $reviewerForm = new $formClassName($this->getMonograph(), $this->getReviewRound());
00642       $reviewerForm->initData($args, $request);
00643       $reviewerForm->setUserRoles($userRoles);
00644 
00645       return $reviewerForm->fetch($request);
00646    }
00647 
00653    function _getReviewerFormClassName($selectionType) {
00654       switch ($selectionType) {
00655          case REVIEWER_SELECT_SEARCH_BY_NAME:
00656             return 'SearchByNameReviewerForm';
00657          case REVIEWER_SELECT_ADVANCED_SEARCH:
00658             return 'AdvancedSearchReviewerForm';
00659          case REVIEWER_SELECT_CREATE:
00660             return 'CreateReviewerForm';
00661          case REVIEWER_SELECT_ENROLL_EXISTING:
00662             return 'EnrollExistingReviewerForm';
00663       }
00664    }
00665 
00670    function _getReviewAssignmentOps() {
00671       // Define operations that need a review assignment policy.
00672       return array('readReview', 'reviewHistory', 'reviewRead', 'editThankReviewer', 'thankReviewer', 'editReminder', 'sendReminder', 'deleteReviewer', 'sendEmail', 'unconsiderReview');
00673 
00674    }
00675 
00680    function _getReviewRoundOps() {
00681       // Define operations that need a review round policy.
00682       return array('fetchGrid', 'fetchRow', 'showReviewerForm', 'reloadReviewerForm', 'createReviewer', 'enrollReviewer', 'updateReviewer',
00683                         'getReviewersNotAssignedToMonograph', 'getUsersNotAssignedAsReviewers');
00684    }
00685 
00689    function _updateReviewRoundStatus($reviewAssignment) {
00690       // Update the review round status.
00691       $reviewRoundDao =& DAORegistry::getDAO('ReviewRoundDAO');
00692       $reviewRound =& $reviewRoundDao->getReviewRoundById($reviewAssignment->getReviewRoundId());
00693       $seriesEditorSubmission =& $this->getMonograph();
00694       $seriesEditorSubmission->updateReviewAssignment($reviewAssignment);
00695       $reviewAssignments = $seriesEditorSubmission->getReviewAssignments($reviewRound->getStageId(), $reviewRound->getRound());
00696       $reviewRoundDao->updateStatus($reviewRound, $reviewAssignments);
00697    }
00698 }
00699 
00700 ?>

Generated on Mon Sep 17 2012 13:58:56 for Open Monograph Press by  doxygen 1.7.1