00001 <?php
00002
00017 import('classes.submission.seriesEditor.SeriesEditorSubmission');
00018 import('classes.monograph.MonographDAO');
00019
00020
00021 import('classes.submission.reviewer.ReviewerSubmission');
00022
00023 class SeriesEditorSubmissionDAO extends MonographDAO {
00024 var $authorDao;
00025 var $userDao;
00026 var $reviewAssignmentDao;
00027 var $submissionFileDao;
00028 var $signoffDao;
00029 var $monographEmailLogDao;
00030 var $monographCommentDao;
00031 var $reviewRoundDao;
00032
00036 function SeriesEditorSubmissionDAO() {
00037 parent::MonographDAO();
00038 $this->authorDao =& DAORegistry::getDAO('AuthorDAO');
00039 $this->userDao =& DAORegistry::getDAO('UserDAO');
00040 $this->reviewAssignmentDao =& DAORegistry::getDAO('ReviewAssignmentDAO');
00041 $this->submissionFileDao =& DAORegistry::getDAO('SubmissionFileDAO');
00042 $this->signoffDao =& DAORegistry::getDAO('SignoffDAO');
00043 $this->monographEmailLogDao =& DAORegistry::getDAO('MonographEmailLogDAO');
00044 $this->monographCommentDao =& DAORegistry::getDAO('MonographCommentDAO');
00045 $this->reviewRoundDao =& DAORegistry::getDAO('ReviewRoundDAO');
00046 }
00047
00053 function &getById($monographId) {
00054 $primaryLocale = AppLocale::getPrimaryLocale();
00055 $locale = AppLocale::getLocale();
00056 $result =& $this->retrieve(
00057 'SELECT m.*,
00058 COALESCE(stl.setting_value, stpl.setting_value) AS series_title,
00059 COALESCE(sal.setting_value, sapl.setting_value) AS series_abbrev
00060 FROM monographs m
00061 LEFT JOIN series s ON (s.series_id = m.series_id)
00062 LEFT JOIN series_settings stpl ON (s.series_id = stpl.series_id AND stpl.setting_name = ? AND stpl.locale = ?)
00063 LEFT JOIN series_settings stl ON (s.series_id = stl.series_id AND stl.setting_name = ? AND stl.locale = ?)
00064 LEFT JOIN series_settings sapl ON (s.series_id = sapl.series_id AND sapl.setting_name = ? AND sapl.locale = ?)
00065 LEFT JOIN series_settings sal ON (s.series_id = sal.series_id AND sal.setting_name = ? AND sal.locale = ?)
00066 WHERE m.monograph_id = ?',
00067 array(
00068 'title', $primaryLocale,
00069 'title', $locale,
00070 'abbrev', $primaryLocale,
00071 'abbrev', $locale,
00072 (int) $monographId
00073 )
00074 );
00075
00076 $returner = null;
00077 if ($result->RecordCount() != 0) {
00078 $returner =& $this->_fromRow($result->GetRowAssoc(false));
00079 }
00080
00081 $result->Close();
00082 unset($result);
00083
00084 return $returner;
00085 }
00086
00091 function newDataObject() {
00092 return new SeriesEditorSubmission();
00093 }
00094
00100 function &_fromRow(&$row) {
00101
00102 $seriesEditorSubmission =& parent::_fromRow($row);
00103
00104
00105 $reviewRounds =& $this->reviewRoundDao->getByMonographId($row['monograph_id']);
00106 while ($reviewRound =& $reviewRounds->next()) {
00107 $stageId = $reviewRound->getStageId();
00108 $round = $reviewRound->getRound();
00109 $seriesEditorSubmission->setDecisions(
00110 $this->getEditorDecisions($row['monograph_id'], $stageId, $round),
00111 $stageId,
00112 $round
00113 );
00114 unset($reviewRound);
00115 }
00116
00117
00118 $seriesEditorSubmission->setMostRecentEditorDecisionComment($this->monographCommentDao->getMostRecentMonographComment($row['monograph_id'], COMMENT_TYPE_EDITOR_DECISION, $row['monograph_id']));
00119 $seriesEditorSubmission->setMostRecentCopyeditComment($this->monographCommentDao->getMostRecentMonographComment($row['monograph_id'], COMMENT_TYPE_COPYEDIT, $row['monograph_id']));
00120 $seriesEditorSubmission->setMostRecentLayoutComment($this->monographCommentDao->getMostRecentMonographComment($row['monograph_id'], COMMENT_TYPE_LAYOUT, $row['monograph_id']));
00121 $seriesEditorSubmission->setMostRecentProofreadComment($this->monographCommentDao->getMostRecentMonographComment($row['monograph_id'], COMMENT_TYPE_PROOFREAD, $row['monograph_id']));
00122
00123
00124 $reviewRounds =& $this->reviewRoundDao->getByMonographId($row['monograph_id']);
00125 while ($reviewRound =& $reviewRounds->next()) {
00126 $stageId = $reviewRound->getStageId();
00127 $round = $reviewRound->getRound();
00128 $seriesEditorSubmission->setReviewAssignments(
00129 $this->reviewAssignmentDao->getBySubmissionId($row['monograph_id'], $reviewRound->getId()),
00130 $stageId,
00131 $round
00132 );
00133 unset($reviewRound);
00134 }
00135
00136 HookRegistry::call('SeriesEditorSubmissionDAO::_fromRow', array(&$seriesEditorSubmission, &$row));
00137
00138 return $seriesEditorSubmission;
00139 }
00140
00145 function updateSeriesEditorSubmission(&$seriesEditorSubmission) {
00146 $monographId = $seriesEditorSubmission->getId();
00147
00148
00149 $editorDecisions = $seriesEditorSubmission->getDecisions();
00150
00151
00152 $reviewRoundDao =& DAORegistry::getDAO('ReviewRoundDAO');
00153 $reviewRounds =& $reviewRoundDao->getByMonographId($monographId);
00154
00155 while ($reviewRound =& $reviewRounds->next()) {
00156 $stageId = $reviewRound->getStageId();
00157 $round = $reviewRound->getRound();
00158 $reviewStageEditorDecisions = array();
00159 if (isset($editorDecisions[$stageId][$round])) {
00160 $reviewStageEditorDecisions = $editorDecisions[$stageId][$round];
00161 unset($editorDecisions[$stageId][$round]);
00162 }
00163 foreach ($reviewStageEditorDecisions as $editorDecision) {
00164 $this->_updateEditorDecision($monographId, $editorDecision, $stageId, $reviewRound);
00165 }
00166 unset($reviewRound);
00167 unset($editorDecision);
00168 }
00169
00170
00171 foreach ($editorDecisions as $stageId => $stageEditorDecision) {
00172 if (isset($stageEditorDecision[REVIEW_ROUND_NONE])) {
00173 foreach ($stageEditorDecision[REVIEW_ROUND_NONE] as $editorDecision) {
00174 $this->_updateEditorDecision($monographId, $editorDecision, $stageId);
00175 }
00176 }
00177 }
00178
00179
00180 $removedReviewAssignments =& $seriesEditorSubmission->getRemovedReviewAssignments();
00181
00182 unset($reviewRounds);
00183 $reviewRounds =& $reviewRoundDao->getByMonographId($monographId);
00184
00185 while ($reviewRound =& $reviewRounds->next()) {
00186 $stageId = $reviewRound->getStageId();
00187 $round = $reviewRound->getRound();
00188 foreach ($seriesEditorSubmission->getReviewAssignments($stageId, $round) as $reviewAssignment) {
00189 if (isset($removedReviewAssignments[$reviewAssignment->getId()])) continue;
00190
00191 if ($reviewAssignment->getId() > 0) {
00192 $this->reviewAssignmentDao->updateObject($reviewAssignment);
00193 } else {
00194 $this->reviewAssignmentDao->insertObject($reviewAssignment);
00195 }
00196 }
00197 unset($reviewRound);
00198 }
00199
00200
00201 foreach ($removedReviewAssignments as $removedReviewAssignmentId) {
00202 $this->reviewAssignmentDao->deleteById($removedReviewAssignmentId);
00203 }
00204
00205
00206 if ($seriesEditorSubmission->getId()) {
00207 $monograph =& parent::getById($monographId);
00208
00209
00210 $monograph->setSeriesId($seriesEditorSubmission->getSeriesId());
00211 $monograph->setStatus($seriesEditorSubmission->getStatus());
00212 $monograph->setDateStatusModified($seriesEditorSubmission->getDateStatusModified());
00213 $monograph->setLastModified($seriesEditorSubmission->getLastModified());
00214 $monograph->setCommentsStatus($seriesEditorSubmission->getCommentsStatus());
00215
00216 parent::updateMonograph($monograph);
00217 }
00218 }
00219
00226 function _updateEditorDecision($monographId, $editorDecision, $stageId = null, $reviewRound = null) {
00227 if ($editorDecision['editDecisionId'] == null) {
00228
00229 $this->update(
00230 sprintf(
00231 'INSERT INTO edit_decisions
00232 (monograph_id, review_round_id, stage_id, round, editor_id, decision, date_decided)
00233 VALUES (?, ?, ?, ?, ?, ?, %s)',
00234 $this->datetimeToDB($editorDecision['dateDecided'])
00235 ),
00236 array(
00237 (int) $monographId,
00238 is_a($reviewRound, 'ReviewRound') ? (int) $reviewRound->getId() : 0,
00239 is_a($reviewRound, 'ReviewRound') ? $reviewRound->getStageId() : (int) $stageId,
00240 is_a($reviewRound, 'ReviewRound') ? (int) $reviewRound->getRound() : REVIEW_ROUND_NONE,
00241 (int) $editorDecision['editorId'],
00242 $editorDecision['decision']
00243 )
00244 );
00245 }
00246 }
00247
00248
00249
00250
00251
00257 function deleteDecisionsByMonograph($monographId) {
00258 return $this->update(
00259 'DELETE FROM edit_decisions WHERE monograph_id = ?',
00260 (int) $monographId
00261 );
00262 }
00263
00269 function deleteReviewRoundsByMonograph($monographId) {
00270 return $this->update(
00271 'DELETE FROM review_rounds WHERE submission_id = ?',
00272 (int) $monographId
00273 );
00274 }
00275
00283 function getEditorDecisions($monographId, $stageId = null, $round = null) {
00284 $params = array((int) $monographId);
00285 if ($stageId) $params[] = (int) $stageId;
00286 if ($round) $params[] = (int) $round;
00287
00288 $result =& $this->retrieve(
00289 'SELECT edit_decision_id, editor_id, decision,
00290 date_decided, review_round_id, stage_id, round
00291 FROM edit_decisions
00292 WHERE monograph_id = ?
00293 ' . ($stageId?' AND stage_id = ?':'') . '
00294 ' . ($round?' AND round = ?':'') . '
00295 ORDER BY date_decided ASC',
00296 $params
00297 );
00298
00299 $decisions = array();
00300 while (!$result->EOF) {
00301 $decisions[] = array(
00302 'editDecisionId' => $result->fields['edit_decision_id'],
00303 'reviewRoundId' => $result->fields['review_round_id'],
00304 'stageId' => $result->fields['stage_id'],
00305 'round' => $result->fields['round'],
00306 'editorId' => $result->fields['editor_id'],
00307 'decision' => $result->fields['decision'],
00308 'dateDecided' => $this->datetimeFromDB($result->fields['date_decided'])
00309 );
00310 $result->MoveNext();
00311 }
00312 $result->Close();
00313 unset($result);
00314
00315 return $decisions;
00316 }
00317
00325 function reviewerExists($reviewRoundId, $reviewerId) {
00326 $result =& $this->retrieve(
00327 'SELECT COUNT(*)
00328 FROM review_assignments
00329 WHERE review_round_id = ? AND
00330 reviewer_id = ? AND
00331 cancelled = 0',
00332 array((int) $reviewRoundId, (int) $reviewerId)
00333 );
00334 $returner = isset($result->fields[0]) && $result->fields[0] == 1 ? true : false;
00335
00336 $result->Close();
00337 unset($result);
00338
00339 return $returner;
00340 }
00341
00350 function &getReviewersForMonograph($pressId, $monographId, $round) {
00351 $result =& $this->retrieve(
00352 'SELECT u.*
00353 FROM users u
00354 LEFT JOIN user_user_groups uug ON (uug.user_id = u.user_id)
00355 LEFT JOIN user_groups ug ON (ug.user_group_id = uug.user_group_id)
00356 LEFT JOIN review_assignments r ON (r.reviewer_id = u.user_id)
00357 WHERE ug.context_id = ? AND
00358 ug.role_id = ? AND
00359 r.submission_id = ? AND
00360 r.round = ?
00361 ORDER BY last_name, first_name',
00362 array(
00363 (int) $pressId,
00364 ROLE_ID_REVIEWER,
00365 (int) $monographId,
00366 (int) $round
00367 )
00368 );
00369
00370 $returner = new DAOResultFactory($result, $this, '_returnReviewerUserFromRow');
00371 return $returner;
00372 }
00373
00379 function &_returnReviewerUserFromRow(&$row) {
00380 $user =& $this->userDao->_returnUserFromRowWithData($row);
00381 if (isset($row['review_id'])) $user->review_id = $row['review_id'];
00382
00383 HookRegistry::call('SeriesEditorSubmissionDAO::_returnReviewerUserFromRow', array(&$user, &$row));
00384
00385 return $user;
00386 }
00387
00397 function &getReviewersNotAssignedToMonograph($pressId, $monographId, &$reviewRound, $name = '') {
00398 $reviewAssignmentDao =& DAORegistry::getDAO('ReviewAssignmentDAO');
00399
00400 $params = array((int) $pressId, ROLE_ID_REVIEWER, (int) $reviewRound->getStageId(), (int) $monographId, (int) $reviewRound->getId());
00401 if (!empty($name)) $params[] = $params[] = $params[] = $params[] = "%$name%";
00402
00403 $result =& $this->retrieve(
00404 'SELECT DISTINCT u.*
00405 FROM users u
00406 JOIN user_user_groups uug ON (uug.user_id = u.user_id)
00407 JOIN user_groups ug ON (ug.user_group_id = uug.user_group_id AND ug.context_id = ? AND ug.role_id = ?)
00408 JOIN user_group_stage ugs ON (ugs.user_group_id = ug.user_group_id AND ugs.stage_id = ?)
00409 WHERE 0=(SELECT COUNT(r.reviewer_id)
00410 FROM review_assignments r
00411 WHERE r.submission_id = ? AND r.reviewer_id = u.user_id AND (r.review_round_id = ? OR' .
00412 $reviewAssignmentDao->getIncompleteReviewAssignmentsWhereString() . '))' .
00413 (!empty($name)?' AND (first_name LIKE ? OR last_name LIKE ? OR username LIKE ? OR email LIKE ?)':'') .
00414 ' ORDER BY last_name, first_name',
00415 $params
00416 );
00417
00418 $returner = new DAOResultFactory($result, $this, '_returnReviewerUserFromRow');
00419 return $returner;
00420 }
00421
00428 function &getAllReviewers($pressId) {
00429 $result =& $this->retrieve(
00430 'SELECT u.*
00431 FROM users u
00432 LEFT JOIN user_user_groups uug ON (uug.user_id = u.user_id)
00433 LEFT JOIN user_groups ug ON (ug.user_group_id = uug.user_group_id)
00434 WHERE ug.context_id = ? AND
00435 ug.role_id = ?
00436 ORDER BY last_name, first_name',
00437 array((int) $pressId, ROLE_ID_REVIEWER)
00438 );
00439
00440 $returner = new DAOResultFactory($result, $this, '_returnReviewerUserFromRow');
00441 return $returner;
00442
00443 }
00444
00451 function getAnonymousReviewerStatistics() {
00452
00453 $reviewerValues = array(
00454 'doneMin' => 0,
00455 'doneMax' => 0,
00456 'avgMin' => 0,
00457 'avgMax' => 0,
00458 'lastMin' => 0,
00459 'lastMax' => 0,
00460 'activeMin' => 0,
00461 'activeMax' => 0
00462 );
00463
00464
00465 $result =& $this->retrieve(
00466 'SELECT r.reviewer_id, COUNT(*) as completed_count
00467 FROM review_assignments r
00468 WHERE r.date_completed IS NOT NULL
00469 GROUP BY r.reviewer_id'
00470 );
00471 while (!$result->EOF) {
00472 $row = $result->GetRowAssoc(false);
00473 if ($reviewerValues['doneMax'] < $row['completed_count']) $reviewerValues['doneMax'] = $row['completed_count'];
00474 $result->MoveNext();
00475 }
00476 $result->Close();
00477 unset($result);
00478
00479
00480 $result =& $this->retrieve(
00481 'SELECT r.reviewer_id, r.date_completed, r.date_notified
00482 FROM review_assignments r
00483 WHERE r.date_notified IS NOT NULL AND
00484 r.date_completed IS NOT NULL AND
00485 r.declined = 0'
00486 );
00487 $averageTimeStats = array();
00488 while (!$result->EOF) {
00489 $row = $result->GetRowAssoc(false);
00490 if (!isset($averageTimeStats[$row['reviewer_id']])) $statistics[$row['reviewer_id']] = array();
00491
00492 $completed = strtotime($this->datetimeFromDB($row['date_completed']));
00493 $notified = strtotime($this->datetimeFromDB($row['date_notified']));
00494 $timeSinceNotified = time() - $notified;
00495 if (isset($averageTimeStats[$row['reviewer_id']]['totalSpan'])) {
00496 $averageTimeStats[$row['reviewer_id']]['totalSpan'] += $completed - $notified;
00497 $averageTimeStats[$row['reviewer_id']]['completedReviewCount'] += 1;
00498 } else {
00499 $averageTimeStats[$row['reviewer_id']]['totalSpan'] = $completed - $notified;
00500 $averageTimeStats[$row['reviewer_id']]['completedReviewCount'] = 1;
00501 }
00502
00503
00504 $averageTimeStats[$row['reviewer_id']]['averageSpan'] = (($averageTimeStats[$row['reviewer_id']]['totalSpan'] / $averageTimeStats[$row['reviewer_id']]['completedReviewCount']) / 86400);
00505
00506
00507 if ($reviewerValues['avgMax'] < $averageTimeStats[$row['reviewer_id']]['averageSpan']) $reviewerValues['avgMax'] = round($averageTimeStats[$row['reviewer_id']]['averageSpan']);
00508 if ($timeSinceNotified > $reviewerValues['lastMax']) $reviewerValues['lastMax'] = $timeSinceNotified;
00509
00510 $result->MoveNext();
00511 }
00512 $reviewerValues['lastMax'] = round($reviewerValues['lastMax'] / 86400);
00513 $result->Close();
00514 unset($result);
00515
00516
00517 $result =& $this->retrieve(
00518 'SELECT r.reviewer_id, COUNT(*) AS incomplete
00519 FROM review_assignments r
00520 WHERE r.date_notified IS NOT NULL AND
00521 r.date_completed IS NULL AND
00522 r.cancelled = 0
00523 GROUP BY r.reviewer_id'
00524 );
00525 while (!$result->EOF) {
00526 $row = $result->GetRowAssoc(false);
00527
00528 if ($row['incomplete'] > $reviewerValues['activeMax']) $reviewerValues['activeMax'] = $row['incomplete'];
00529 $result->MoveNext();
00530 }
00531 $result->Close();
00532 unset($result);
00533
00534 return $reviewerValues;
00535 }
00536
00554 function getFilteredReviewers($pressId, $doneMin, $doneMax, $avgMin, $avgMax, $lastMin, $lastMax, $activeMin, $activeMax, $interests, $monographId = null, $reviewRoundId = null) {
00555 $userDao =& DAORegistry::getDAO('UserDAO');
00556 $interestDao =& DAORegistry::getDAO('InterestDAO');
00557 $reviewerStats = $this->getReviewerStatistics($pressId);
00558
00559
00560 $allInterestIds = array();
00561 if(isset($interests)) {
00562 $key = 0;
00563 foreach ($interests as $interest) {
00564 $interestIds = $interestDao->getUserIdsByInterest($interest);
00565 if (!$interestIds) {
00566
00567 continue;
00568 }
00569 if ($key == 0) $allInterestIds = $interestIds;
00570 else $allInterestIds = array_intersect($allInterestIds, $interestIds);
00571 unset($interest);
00572 $key++;
00573 }
00574 }
00575
00576
00577 if($monographId) {
00578 $reviewAssignmentDao =& DAORegistry::getDAO('ReviewAssignmentDAO');
00579 $reviewRoundDao =& DAORegistry::getDAO('ReviewRoundDAO');
00580 $reviewRound =& $reviewRoundDao->getReviewRoundById($reviewRoundId);
00581 $availableReviewerFactory =& $this->getReviewersNotAssignedToMonograph($pressId, $monographId, $reviewRound);
00582 $availableReviewers = $availableReviewerFactory->toAssociativeArray();
00583 }
00584
00585 $filteredReviewers = array();
00586 foreach ($reviewerStats as $userId => $reviewerStat) {
00587
00588 if(!isset($reviewerStat['last_notified'])) {
00589 $lastNotifiedInDays = 0;
00590 } else {
00591 $lastNotifiedInDays = round((time() - strtotime($reviewerStat['last_notified'])) / 86400);
00592 }
00593
00594
00595 if(!empty($allInterestIds)) {
00596 $interestCheck = in_array($userId, $allInterestIds);
00597 } else $interestCheck = true;
00598
00599 if ($interestCheck && $reviewerStat['completed_review_count'] <= $doneMax && $reviewerStat['completed_review_count'] >= $doneMin &&
00600 $reviewerStat['average_span'] <= $avgMax && $reviewerStat['average_span'] >= $avgMin && $lastNotifiedInDays <= $lastMax &&
00601 $lastNotifiedInDays >= $lastMin && $reviewerStat['incomplete'] <= $activeMax && $reviewerStat['incomplete'] >= $activeMin
00602 ) {
00603 if($monographId && !array_key_exists($userId, $availableReviewers)) {
00604 continue;
00605 } else {
00606 $filteredReviewers[] = $userDao->getById($userId);
00607 }
00608 }
00609 }
00610
00611 return $filteredReviewers;
00612 }
00613
00620 function getReviewerStatistics($pressId) {
00621
00622
00623 $statistics = array();
00624 $reviewerStatsPlaceholder = array('last_notified' => null, 'incomplete' => 0, 'total_span' => 0, 'completed_review_count' => 0, 'average_span' => 0);
00625
00626 $allReviewers =& $this->getAllReviewers($pressId);
00627 while($reviewer =& $allReviewers->next()) {
00628 $statistics[$reviewer->getId()] = $reviewerStatsPlaceholder;
00629 unset($reviewer);
00630 }
00631
00632
00633 $result =& $this->retrieve(
00634 'SELECT r.reviewer_id, MAX(r.date_notified) AS last_notified
00635 FROM review_assignments r, monographs m
00636 WHERE r.submission_id = m.monograph_id AND
00637 m.press_id = ?
00638 GROUP BY r.reviewer_id',
00639 (int) $pressId
00640 );
00641 while (!$result->EOF) {
00642 $row = $result->GetRowAssoc(false);
00643 if (!isset($statistics[$row['reviewer_id']])) $statistics[$row['reviewer_id']] = $reviewerStatsPlaceholder;
00644 $statistics[$row['reviewer_id']]['last_notified'] = $this->datetimeFromDB($row['last_notified']);
00645 $result->MoveNext();
00646 }
00647
00648 $result->Close();
00649 unset($result);
00650
00651
00652 $result =& $this->retrieve(
00653 'SELECT r.reviewer_id, COUNT(*) AS incomplete
00654 FROM review_assignments r, monographs m
00655 WHERE r.submission_id = m.monograph_id AND
00656 r.date_notified IS NOT NULL AND
00657 r.date_completed IS NULL AND
00658 r.cancelled = 0 AND
00659 m.press_id = ?
00660 GROUP BY r.reviewer_id',
00661 (int) $pressId
00662 );
00663 while (!$result->EOF) {
00664 $row = $result->GetRowAssoc(false);
00665 if (!isset($statistics[$row['reviewer_id']])) $statistics[$row['reviewer_id']] = $reviewerStatsPlaceholder;
00666 $statistics[$row['reviewer_id']]['incomplete'] = $row['incomplete'];
00667 $result->MoveNext();
00668 }
00669
00670 $result->Close();
00671 unset($result);
00672
00673
00674 $result =& $this->retrieve(
00675 'SELECT r.reviewer_id, r.date_notified, r.date_completed
00676 FROM review_assignments r, monographs m
00677 WHERE r.submission_id = m.monograph_id AND
00678 r.date_notified IS NOT NULL AND
00679 r.date_completed IS NOT NULL AND
00680 r.declined = 0 AND
00681 m.press_id = ?',
00682 (int) $pressId
00683 );
00684 while (!$result->EOF) {
00685 $row = $result->GetRowAssoc(false);
00686 if (!isset($statistics[$row['reviewer_id']])) $statistics[$row['reviewer_id']] = $reviewerStatsPlaceholder;
00687
00688 $completed = strtotime($this->datetimeFromDB($row['date_completed']));
00689 $notified = strtotime($this->datetimeFromDB($row['date_notified']));
00690 if (isset($statistics[$row['reviewer_id']]['total_span'])) {
00691 $statistics[$row['reviewer_id']]['total_span'] += $completed - $notified;
00692 $statistics[$row['reviewer_id']]['completed_review_count'] += 1;
00693 } else {
00694 $statistics[$row['reviewer_id']]['total_span'] = $completed - $notified;
00695 $statistics[$row['reviewer_id']]['completed_review_count'] = 1;
00696 }
00697
00698
00699 $statistics[$row['reviewer_id']]['average_span'] = round(($statistics[$row['reviewer_id']]['total_span'] / $statistics[$row['reviewer_id']]['completed_review_count']) / 86400);
00700 $result->MoveNext();
00701 }
00702
00703 $result->Close();
00704 unset($result);
00705
00706 return $statistics;
00707 }
00708
00714 function transferEditorDecisions($oldUserId, $newUserId) {
00715 $this->update(
00716 'UPDATE edit_decisions SET editor_id = ? WHERE editor_id = ?',
00717 array($newUserId, $oldUserId)
00718 );
00719 }
00720 }
00721
00722 ?>