00001 <?php
00002
00015 import('classes.handler.Handler');
00016
00017
00018 import('lib.pkp.classes.linkAction.LinkAction');
00019 import('lib.pkp.classes.linkAction.request.AjaxModal');
00020
00021
00022 import('classes.workflow.EditorDecisionActionsManager');
00023
00024
00025 class WorkflowHandler extends Handler {
00029 function WorkflowHandler() {
00030 parent::Handler();
00031
00032 $this->addRoleAssignment(
00033 array(ROLE_ID_SERIES_EDITOR, ROLE_ID_PRESS_MANAGER, ROLE_ID_PRESS_ASSISTANT),
00034 array(
00035 'access', 'submission',
00036 'editorDecisionActions',
00037 'internalReview',
00038 'externalReview',
00039 'editorial',
00040 'production', 'productionFormatsTab',
00041 'submissionProgressBar'
00042 )
00043 );
00044 }
00045
00046
00047
00048
00049
00053 function authorize(&$request, $args, $roleAssignments) {
00054 $router =& $request->getRouter();
00055 $operation = $router->getRequestedOp($request);
00056
00057 if ($operation == 'access') {
00058
00059 import('classes.security.authorization.internal.MonographRequiredPolicy');
00060 $this->addPolicy(new MonographRequiredPolicy($request, $args, 'monographId'));
00061
00062
00063
00064
00065 import('classes.security.authorization.internal.UserAccessibleWorkflowStageRequiredPolicy');
00066 $this->addPolicy(new UserAccessibleWorkflowStageRequiredPolicy($request));
00067 } else {
00068 import('classes.security.authorization.OmpWorkflowStageAccessPolicy');
00069 $this->addPolicy(new OmpWorkflowStageAccessPolicy($request, $args, $roleAssignments, 'monographId', $this->_identifyStageId($request)));
00070 }
00071
00072 return parent::authorize($request, $args, $roleAssignments);
00073 }
00074
00078 function initialize(&$request, $args) {
00079 $router =& $request->getRouter();
00080 $operation = $router->getRequestedOp($request);
00081
00082 if ($operation != 'access') {
00083 $this->setupTemplate($request);
00084 }
00085
00086
00087 parent::initialize($request, $args);
00088 }
00089
00094 function setupTemplate(&$request) {
00095 parent::setupTemplate();
00096 AppLocale::requireComponents(LOCALE_COMPONENT_PKP_SUBMISSION, LOCALE_COMPONENT_OMP_SUBMISSION, LOCALE_COMPONENT_OMP_EDITOR, LOCALE_COMPONENT_PKP_GRID);
00097
00098 $router =& $request->getRouter();
00099
00100 $monograph =& $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00101 $stageId = $this->getAuthorizedContextObject(ASSOC_TYPE_WORKFLOW_STAGE);
00102
00103
00104 $userGroupDao =& DAORegistry::getDAO('UserGroupDAO');
00105 $workflowStages = $userGroupDao->getWorkflowStageKeysAndPaths();
00106
00107 $templateMgr =& TemplateManager::getManager();
00108
00109
00110 $templateMgr->assign_by_ref('monograph', $monograph);
00111
00112
00113 $templateMgr->assign('stageId', $stageId);
00114 $templateMgr->assign('monographStageId', $monograph->getStageId());
00115 $templateMgr->assign('workflowStages', $workflowStages);
00116
00117
00118 $notificationMgr = new NotificationManager();
00119 $editorAssignmentNotificationType = $notificationMgr->getEditorAssignmentNotificationTypeByStageId($stageId);
00120
00121
00122 $notificationRequestOptions = array(
00123 NOTIFICATION_LEVEL_TASK => array(
00124 $editorAssignmentNotificationType => array(ASSOC_TYPE_MONOGRAPH, $monograph->getId())
00125 ),
00126 NOTIFICATION_LEVEL_TRIVIAL => array()
00127 );
00128
00129 $signoffNotificationType = $notificationMgr->getSignoffNotificationTypeByStageId($stageId);
00130 if (!is_null($signoffNotificationType)) {
00131 $notificationRequestOptions[NOTIFICATION_LEVEL_TASK][$signoffNotificationType] = array(ASSOC_TYPE_MONOGRAPH, $monograph->getId());
00132 }
00133
00134 $templateMgr->assign('workflowNotificationRequestOptions', $notificationRequestOptions);
00135
00136 import('controllers.modals.submissionMetadata.linkAction.CatalogEntryLinkAction');
00137 $templateMgr->assign(
00138 'catalogEntryAction',
00139 new CatalogEntryLinkAction($request, $monograph->getId(), $stageId)
00140 );
00141
00142 import('controllers.informationCenter.linkAction.SubmissionInfoCenterLinkAction');
00143 $templateMgr->assign(
00144 'submissionInformationCenterAction',
00145 new SubmissionInfoCenterLinkAction($request, $monograph->getId())
00146 );
00147 }
00148
00149
00150
00151
00152
00157 function access($args, &$request) {
00158 $monograph =& $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00159 $userGroupDao =& DAORegistry::getDAO('UserGroupDAO');
00160 $reviewRoundDao =& DAORegistry::getDAO('ReviewRoundDAO');
00161
00162 $stageId = $monograph->getStageId();
00163 $accessibleWorkflowStages = $this->getAuthorizedContextObject(ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES);
00164
00165
00166 $stagePath = null;
00167 for ($workingStageId = $stageId; $workingStageId >= WORKFLOW_STAGE_ID_SUBMISSION; $workingStageId--) {
00168 if (array_key_exists($workingStageId, $accessibleWorkflowStages)) {
00169 $stagePath = $userGroupDao->getPathFromId($workingStageId);
00170 break;
00171 }
00172 }
00173
00174
00175
00176 if (!$stagePath) {
00177 for ($workingStageId = $stageId; $workingStageId <= WORKFLOW_STAGE_ID_PRODUCTION; $workingStageId++) {
00178 if (array_key_exists($workingStageId, $accessibleWorkflowStages)) {
00179 $stagePath = $userGroupDao->getPathFromId($workingStageId);
00180 break;
00181 }
00182 }
00183 }
00184
00185 assert(!is_null($stagePath));
00186
00187 $router =& $request->getRouter();
00188 $request->redirectUrl($router->url($request, null, 'workflow', $stagePath, $monograph->getId()));
00189 }
00195 function submission($args, &$request) {
00196
00197 $templateMgr =& TemplateManager::getManager();
00198 $templateMgr->display('workflow/submission.tpl');
00199 }
00200
00206 function internalReview($args, &$request) {
00207
00208 $templateMgr =& TemplateManager::getManager();
00209 $templateMgr->assign('reviewRoundOp', 'internalReviewRound');
00210 return $this->_review($args, $request);
00211 }
00212
00218 function externalReview($args, &$request) {
00219
00220 $templateMgr =& TemplateManager::getManager();
00221 $templateMgr->assign('reviewRoundOp', 'externalReviewRound');
00222 return $this->_review($args, $request);
00223 }
00224
00230 function editorial(&$args, &$request) {
00231
00232 $templateMgr =& TemplateManager::getManager();
00233 $templateMgr->display('workflow/editorial.tpl');
00234 }
00235
00241 function production(&$args, &$request) {
00242 $templateMgr =& TemplateManager::getManager();
00243 $monograph =& $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00244 $notificationRequestOptions = array(
00245 NOTIFICATION_LEVEL_NORMAL => array(
00246 NOTIFICATION_TYPE_VISIT_CATALOG => array(ASSOC_TYPE_MONOGRAPH, $monograph->getId()),
00247 NOTIFICATION_TYPE_APPROVE_SUBMISSION => array(ASSOC_TYPE_MONOGRAPH, $monograph->getId()),
00248 ),
00249 NOTIFICATION_LEVEL_TRIVIAL => array()
00250 );
00251
00252 $publicationFormatDao =& DAORegistry::getDAO('PublicationFormatDAO');
00253 $monograph =& $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00254 $publicationFormats =& $publicationFormatDao->getByMonographId($monograph->getId());
00255 $templateMgr->assign_by_ref('publicationFormats', $publicationFormats->toAssociativeArray());
00256
00257 $templateMgr->assign('productionNotificationRequestOptions', $notificationRequestOptions);
00258 $templateMgr->display('workflow/production.tpl');
00259 }
00260
00266 function productionFormatsTab(&$args, &$request) {
00267 $templateMgr =& TemplateManager::getManager();
00268 $publicationFormatDao =& DAORegistry::getDAO('PublicationFormatDAO');
00269 $monograph =& $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00270 $publicationFormats =& $publicationFormatDao->getByMonographId($monograph->getId());
00271 $templateMgr->assign_by_ref('$monograph', $monograph);
00272 $templateMgr->assign_by_ref('publicationFormats', $publicationFormats->toAssociativeArray());
00273 $templateMgr->assign('currentFormatTabId', (int) $request->getUserVar('currentFormatTabId'));
00274
00275 return $templateMgr->fetchJson('workflow/productionFormatsTab.tpl');
00276 }
00277
00283 function editorDecisionActions($args, &$request) {
00284 AppLocale::requireComponents(LOCALE_COMPONENT_OMP_EDITOR);
00285 $reviewRoundId = (int) $request->getUserVar('reviewRoundId');
00286
00287
00288 $monograph =& $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00289 $stageId = $this->getAuthorizedContextObject(ASSOC_TYPE_WORKFLOW_STAGE);
00290
00291 $actionArgs = array(
00292 'monographId' => $monograph->getId(),
00293 'stageId' => (int) $stageId,
00294 );
00295
00296
00297
00298 if ($reviewRoundId) {
00299 $actionArgs['reviewRoundId'] = $reviewRoundId;
00300 $reviewRoundDao =& DAORegistry::getDAO('ReviewRoundDAO');
00301 $lastReviewRound =& $reviewRoundDao->getLastReviewRoundByMonographId($monograph->getId(), $stageId);
00302 }
00303
00304
00305
00306
00307 $stageAssignmentDao =& DAORegistry::getDAO('StageAssignmentDAO');
00308 if ($stageAssignmentDao->editorAssignedToStage($monograph->getId(), $stageId) && (!$reviewRoundId || $reviewRoundId == $lastReviewRound->getId())) {
00309 import('classes.workflow.EditorDecisionActionsManager');
00310 $decisions = EditorDecisionActionsManager::getStageDecisions($stageId);
00311 } else {
00312 $decisions = array();
00313 }
00314
00315
00316 $editorActions = array();
00317 $dispatcher =& $request->getDispatcher();
00318 import('classes.linkAction.request.AjaxModal');
00319 foreach($decisions as $decision => $action) {
00320 $actionArgs['decision'] = $decision;
00321 $editorActions[] = new LinkAction(
00322 $action['name'],
00323 new AjaxModal(
00324 $dispatcher->url(
00325 $request, ROUTE_COMPONENT, null,
00326 'modals.editorDecision.EditorDecisionHandler',
00327 $action['operation'], null, $actionArgs
00328 ),
00329 __($action['title']),
00330 $action['titleIcon']
00331 ),
00332 __($action['title'])
00333 );
00334 }
00335
00336
00337 $templateMgr =& TemplateManager::getManager();
00338 $templateMgr->assign('editorActions', $editorActions);
00339 $templateMgr->assign('stageId', $stageId);
00340 return $templateMgr->fetchJson('workflow/editorialLinkActions.tpl');
00341 }
00342
00348 function submissionProgressBar($args, &$request) {
00349
00350 $templateMgr =& TemplateManager::getManager();
00351 $press =& $request->getPress();
00352
00353 $userGroupDao =& DAORegistry::getDAO('UserGroupDAO');
00354 $workflowStages = $userGroupDao->getWorkflowStageKeysAndPaths();
00355 $stageNotifications = array();
00356 foreach (array_keys($workflowStages) as $stageId) {
00357 $stageNotifications[$stageId] = $this->_notificationOptionsByStage($request->getUser(), $stageId, $press->getId());
00358 }
00359
00360 $templateMgr->assign('stageNotifications', $stageNotifications);
00361
00362 $monograph =& $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00363 $publishedMonographDao =& DAORegistry::getDAO('PublishedMonographDAO');
00364 $publishedMonograph =& $publishedMonographDao->getById($monograph->getId());
00365 if ($publishedMonograph) {
00366 $publicationFormats =& $publishedMonograph->getPublicationFormats(true);
00367 $submissionFileDao =& DAORegistry::getDAO('SubmissionFileDAO');
00368 import('classes.monograph.MonographFile');
00369
00370 foreach ($publicationFormats as $format) {
00371 if ($format->getIsApproved()) {
00372
00373 $monographFiles =& $submissionFileDao->getLatestRevisionsByAssocId(
00374 ASSOC_TYPE_PUBLICATION_FORMAT, $format->getId(),
00375 $publishedMonograph->getId()
00376 );
00377
00378 foreach ($monographFiles as $file) {
00379 if ($file->getViewable() && !is_null($file->getDirectSalesPrice())) {
00380 $templateMgr->assign('submissionIsReady', true);
00381 }
00382 }
00383 }
00384 }
00385 }
00386 return $templateMgr->fetchJson('workflow/submissionProgressBar.tpl');
00387 }
00388
00395 function _notificationOptionsByStage(&$user, $stageId, $contextId) {
00396
00397 $monograph =& $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00398 $notificationDao =& DAORegistry::getDAO('NotificationDAO');
00399 $notificationMgr = new NotificationManager();
00400
00401 $signOffNotificationType = $notificationMgr->getSignoffNotificationTypeByStageId($stageId);
00402 $editorAssignmentNotificationType = $notificationMgr->getEditorAssignmentNotificationTypeByStageId($stageId);
00403
00404 $editorAssignments =& $notificationDao->getByAssoc(ASSOC_TYPE_MONOGRAPH, $monograph->getId(), null, $editorAssignmentNotificationType, $contextId);
00405 if (isset($signOffNotificationType)) {
00406 $signoffAssignments =& $notificationDao->getByAssoc(ASSOC_TYPE_MONOGRAPH, $monograph->getId(), $user->getUserId(), $signOffNotificationType, $contextId);
00407 }
00408
00409
00410 if (!$editorAssignments->wasEmpty() || (isset($signoffAssignments) && !$signoffAssignments->wasEmpty())) {
00411 return true;
00412 }
00413
00414
00415 if ($stageId == WORKFLOW_STAGE_ID_PRODUCTION) {
00416 $submissionApprovalNotification =& $notificationDao->getByAssoc(ASSOC_TYPE_MONOGRAPH, $monograph->getId(), null, NOTIFICATION_TYPE_APPROVE_SUBMISSION, $contextId);
00417 if (!$submissionApprovalNotification->wasEmpty()) {
00418 return true;
00419 }
00420 }
00421
00422 if ($stageId == WORKFLOW_STAGE_ID_INTERNAL_REVIEW || $stageId == WORKFLOW_STAGE_ID_EXTERNAL_REVIEW) {
00423 $reviewRoundDao =& DAORegistry::getDAO('ReviewRoundDAO');
00424 $reviewRounds =& $reviewRoundDao->getByMonographId($monograph->getId(), $stageId);
00425 $notificationTypes = array(NOTIFICATION_TYPE_REVIEW_ROUND_STATUS, NOTIFICATION_TYPE_ALL_REVIEWS_IN);
00426 while ($reviewRound =& $reviewRounds->next()) {
00427 foreach ($notificationTypes as $type) {
00428 $notifications =& $notificationDao->getByAssoc(ASSOC_TYPE_REVIEW_ROUND, $reviewRound->getId(), null, $type, $contextId);
00429 if (!$notifications->wasEmpty()) {
00430 return true;
00431 }
00432 }
00433 unset($reviewRound);
00434 }
00435 }
00436
00437 return false;
00438 }
00439
00440
00441
00442
00448 function _review($args, &$request) {
00449
00450 $monograph =& $this->getAuthorizedContextObject(ASSOC_TYPE_MONOGRAPH);
00451 $selectedStageId = $this->getAuthorizedContextObject(ASSOC_TYPE_WORKFLOW_STAGE);
00452
00453 $templateMgr =& TemplateManager::getManager();
00454
00455
00456 $reviewRoundDao =& DAORegistry::getDAO('ReviewRoundDAO');
00457 $reviewRoundsFactory =& $reviewRoundDao->getByMonographId($monograph->getId(), $selectedStageId);
00458 if (!$reviewRoundsFactory->wasEmpty()) {
00459 $reviewRoundsArray =& $reviewRoundsFactory->toAssociativeArray();
00460
00461
00462
00463 $lastReviewRoundNumber = end($reviewRoundsArray)->getRound();
00464 $lastReviewRoundId = end($reviewRoundsArray)->getId();
00465 reset($reviewRoundsArray);
00466
00467
00468 $templateMgr->assign_by_ref('reviewRounds', $reviewRoundsArray);
00469 $templateMgr->assign('lastReviewRoundNumber', $lastReviewRoundNumber);
00470
00471 if ($monograph->getStageId() == $selectedStageId) {
00472 $dispatcher =& $request->getDispatcher();
00473 $newRoundAction = new LinkAction(
00474 'newRound',
00475 new AjaxModal(
00476 $dispatcher->url(
00477 $request, ROUTE_COMPONENT, null,
00478 'modals.editorDecision.EditorDecisionHandler',
00479 'newReviewRound', null, array(
00480 'monographId' => $monograph->getId(),
00481 'decision' => SUBMISSION_EDITOR_DECISION_RESUBMIT,
00482 'stageId' => $selectedStageId,
00483 'reviewRoundId' => $lastReviewRoundId
00484 )
00485 ),
00486 __('editor.monograph.newRound'),
00487 'modal_add_item'
00488 ),
00489 __('editor.monograph.newRound'),
00490 'add_item_small'
00491 );
00492 $templateMgr->assign_by_ref('newRoundAction', $newRoundAction);
00493 }
00494 }
00495
00496
00497 $templateMgr->display('workflow/review.tpl');
00498 }
00499
00505 function _identifyStageId(&$request) {
00506 if ($stageId = $request->getUserVar('stageId')) {
00507 return (int) $stageId;
00508 }
00509
00510
00511 $router =& $request->getRouter();
00512 $operation = $router->getRequestedOp($request);
00513
00514
00515 $userGroupDao =& DAORegistry::getDAO('UserGroupDAO');
00516 return $userGroupDao->getIdFromPath($operation);
00517 }
00518 }
00519
00520 ?>