00001 <?php
00002
00015
00016
00017
00018 define('REPORT_TYPE_JOURNAL', 0x00001);
00019 define('REPORT_TYPE_EDITOR', 0x00002);
00020 define('REPORT_TYPE_REVIEWER', 0x00003);
00021 define('REPORT_TYPE_SECTION', 0x00004);
00022
00023 class JournalStatisticsDAO extends DAO {
00033 function getArticleStatistics($journalId, $sectionIds = null, $dateStart = null, $dateEnd = null) {
00034 $params = array($journalId);
00035 if (!empty($sectionIds)) {
00036 $sectionSql = ' AND (a.section_id = ?';
00037 $params[] = array_shift($sectionIds);
00038 foreach ($sectionIds as $sectionId) {
00039 $sectionSql .= ' OR a.section_id = ?';
00040 $params[] = $sectionId;
00041 }
00042 $sectionSql .= ')';
00043 } else $sectionSql = '';
00044
00045 $sql = 'SELECT a.article_id,
00046 a.date_submitted,
00047 pa.date_published,
00048 pa.pub_id,
00049 d.decision
00050 FROM articles a
00051 LEFT JOIN published_articles pa ON (a.article_id = pa.article_id)
00052 LEFT JOIN edit_decisions d ON (d.article_id = a.article_id)
00053 WHERE a.journal_id = ?' .
00054 ($dateStart !== null ? ' AND a.date_submitted >= ' . $this->datetimeToDB($dateStart) : '') .
00055 ($dateEnd !== null ? ' AND a.date_submitted <= ' . $this->datetimeToDB($dateEnd) : '') .
00056 $sectionSql .
00057 ' ORDER BY a.article_id, d.date_decided DESC';
00058
00059 $result = &$this->retrieve($sql, $params);
00060
00061 $returner = array(
00062 'numSubmissions' => 0,
00063 'numReviewedSubmissions' => 0,
00064 'numPublishedSubmissions' => 0,
00065 'submissionsAccept' => 0,
00066 'submissionsDecline' => 0,
00067 'submissionsRevise' => 0,
00068 'submissionsAcceptPercent' => 0,
00069 'submissionsDeclinePercent' => 0,
00070 'submissionsRevisePercent' => 0,
00071 'daysToPublication' => 0
00072 );
00073
00074
00075 $articleIds = array();
00076
00077 $totalTimeToPublication = 0;
00078 $timeToPublicationCount = 0;
00079
00080 while (!$result->EOF) {
00081 $row = $result->GetRowAssoc(false);
00082
00083
00084
00085
00086
00087 if (!in_array($row['article_id'], $articleIds)) {
00088 $articleIds[] = $row['article_id'];
00089 $returner['numSubmissions']++;
00090
00091 if (!empty($row['pub_id'])) {
00092 $returner['numPublishedSubmissions']++;
00093 }
00094
00095 if (!empty($row['date_submitted']) && !empty($row['date_published'])) {
00096 $timeSubmitted = strtotime($this->datetimeFromDB($row['date_submitted']));
00097 $timePublished = strtotime($this->datetimeFromDB($row['date_published']));
00098 if ($timePublished > $timeSubmitted) {
00099 $totalTimeToPublication += ($timePublished - $timeSubmitted);
00100 $timeToPublicationCount++;
00101 }
00102 }
00103
00104 import('submission.common.Action');
00105 switch ($row['decision']) {
00106 case SUBMISSION_EDITOR_DECISION_ACCEPT:
00107 $returner['submissionsAccept']++;
00108 $returner['numReviewedSubmissions']++;
00109 break;
00110 case SUBMISSION_EDITOR_DECISION_PENDING_REVISIONS:
00111 case SUBMISSION_EDITOR_DECISION_RESUBMIT:
00112 $returner['submissionsRevise']++;
00113 break;
00114 case SUBMISSION_EDITOR_DECISION_DECLINE:
00115 $returner['submissionsDecline']++;
00116 $returner['numReviewedSubmissions']++;
00117 break;
00118 }
00119 }
00120
00121 $result->moveNext();
00122 }
00123
00124 $result->Close();
00125 unset($result);
00126
00127
00128 if ($returner['numReviewedSubmissions'] != 0) {
00129 $returner['submissionsAcceptPercent'] = round($returner['submissionsAccept'] * 100 / $returner['numReviewedSubmissions']);
00130 $returner['submissionsDeclinePercent'] = round($returner['submissionsDecline'] * 100 / $returner['numReviewedSubmissions']);
00131 $returner['submissionsRevisePercent'] = round($returner['submissionsRevise'] * 100 / $returner['numReviewedSubmissions']);
00132 }
00133
00134 if ($timeToPublicationCount != 0) {
00135
00136 $returner['daysToPublication'] = round($totalTimeToPublication / $timeToPublicationCount / 60 / 60 / 24);
00137 }
00138
00139 return $returner;
00140 }
00141
00150 function getUserStatistics($journalId, $dateStart = null, $dateEnd = null) {
00151 $roleDao =& DAORegistry::getDAO('RoleDAO');
00152
00153
00154 $result = &$this->retrieve(
00155 'SELECT COUNT(DISTINCT r.user_id) FROM roles r, users u WHERE r.user_id = u.user_id AND r.journal_id = ?' .
00156 ($dateStart !== null ? ' AND u.date_registered >= ' . $this->datetimeToDB($dateStart) : '') .
00157 ($dateEnd !== null ? ' AND u.date_registered <= ' . $this->datetimeToDB($dateEnd) : ''),
00158 $journalId
00159 );
00160
00161 $returner = array(
00162 'totalUsersCount' => $result->fields[0]
00163 );
00164
00165 $result->Close();
00166 unset($result);
00167
00168
00169 $result = &$this->retrieve(
00170 'SELECT r.role_id, COUNT(r.user_id) AS role_count FROM roles r LEFT JOIN users u ON (r.user_id = u.user_id) WHERE r.journal_id = ?' .
00171 ($dateStart !== null ? ' AND u.date_registered >= ' . $this->datetimeToDB($dateStart) : '') .
00172 ($dateEnd !== null ? ' AND u.date_registered <= ' . $this->datetimeToDB($dateEnd) : '') .
00173 'GROUP BY r.role_id',
00174 $journalId
00175 );
00176
00177 while (!$result->EOF) {
00178 $row = $result->GetRowAssoc(false);
00179 $returner[$roleDao->getRolePath($row['role_id'])] = $row['role_count'];
00180 $result->moveNext();
00181 }
00182
00183 $result->Close();
00184 unset($result);
00185
00186 return $returner;
00187 }
00188
00196 function getSubscriptionStatistics($journalId, $dateStart = null, $dateEnd = null) {
00197 $result = &$this->retrieve(
00198 'SELECT st.type_id,
00199 sts.setting_value AS type_name,
00200 count(s.subscription_id) AS type_count
00201 FROM subscription_types st
00202 LEFT JOIN journals j ON (j.journal_id = st.journal_id)
00203 LEFT JOIN subscription_type_settings sts ON (st.type_id = sts.type_id AND sts.setting_name = ? AND sts.locale = j.primary_locale),
00204 subscriptions s
00205 WHERE st.journal_id = ?
00206 AND s.type_id = st.type_id' .
00207 ($dateStart !== null ? ' AND s.date_start >= ' . $this->datetimeToDB($dateStart) : '') .
00208 ($dateEnd !== null ? ' AND s.date_start <= ' . $this->datetimeToDB($dateEnd) : '') .
00209 ' GROUP BY st.type_id, sts.setting_value',
00210 array('name', $journalId)
00211 );
00212
00213 $returner = array();
00214
00215 while (!$result->EOF) {
00216 $row = $result->getRowAssoc(false);
00217 $returner[$row['type_id']] = array(
00218 'name' => $row['type_name'],
00219 'count' => $row['type_count']
00220 );
00221 $result->moveNext();
00222 }
00223 $result->Close();
00224 unset($result);
00225
00226 return $returner;
00227 }
00228
00237 function getIssueStatistics($journalId, $dateStart = null, $dateEnd = null) {
00238 $result = &$this->retrieve(
00239 'SELECT COUNT(*) AS count, published FROM issues WHERE journal_id = ?' .
00240 ($dateStart !== null ? ' AND date_published >= ' . $this->datetimeToDB($dateStart) : '') .
00241 ($dateEnd !== null ? ' AND date_published <= ' . $this->datetimeToDB($dateEnd) : '') .
00242 ' GROUP BY published',
00243 $journalId
00244 );
00245
00246 $returner = array(
00247 'numPublishedIssues' => 0,
00248 'numUnpublishedIssues' => 0
00249 );
00250
00251 while (!$result->EOF) {
00252 $row = $result->GetRowAssoc(false);
00253
00254 if ($row['published']) {
00255 $returner['numPublishedIssues'] = $row['count'];
00256 } else {
00257 $returner['numUnpublishedIssues'] = $row['count'];
00258 }
00259 $result->moveNext();
00260 }
00261
00262 $result->Close();
00263 unset($result);
00264
00265 $returner['numIssues'] = $returner['numPublishedIssues'] + $returner['numUnpublishedIssues'];
00266
00267 return $returner;
00268 }
00269
00278 function getReviewerStatistics($journalId, $sectionIds, $dateStart = null, $dateEnd = null) {
00279 $params = array($journalId);
00280 if (!empty($sectionIds)) {
00281 $sectionSql = ' AND (a.section_id = ?';
00282 $params[] = array_shift($sectionIds);
00283 foreach ($sectionIds as $sectionId) {
00284 $sectionSql .= ' OR a.section_id = ?';
00285 $params[] = $sectionId;
00286 }
00287 $sectionSql .= ')';
00288 } else $sectionSql = '';
00289
00290 $sql = 'SELECT a.article_id,
00291 af.date_uploaded AS date_rv_uploaded,
00292 r.review_id,
00293 u.date_registered,
00294 r.reviewer_id,
00295 r.quality,
00296 r.date_assigned,
00297 r.date_completed
00298 FROM articles a,
00299 article_files af,
00300 review_assignments r
00301 LEFT JOIN users u ON (u.user_id = r.reviewer_id)
00302 WHERE a.journal_id = ?
00303 AND r.article_id = a.article_id
00304 AND af.article_id = a.article_id
00305 AND af.file_id = a.review_file_id
00306 AND af.revision = 1' .
00307 ($dateStart !== null ? ' AND a.date_submitted >= ' . $this->datetimeToDB($dateStart) : '') .
00308 ($dateEnd !== null ? ' AND a.date_submitted <= ' . $this->datetimeToDB($dateEnd) : '') .
00309 $sectionSql;
00310 $result = &$this->retrieve($sql, $params);
00311
00312 $returner = array(
00313 'reviewsCount' => 0,
00314 'reviewerScore' => 0,
00315 'daysPerReview' => 0,
00316 'reviewerAddedCount' => 0,
00317 'reviewerCount' => 0,
00318 'reviewedSubmissionsCount' => 0
00319 );
00320
00321 $scoredReviewsCount = 0;
00322 $totalScore = 0;
00323 $completedReviewsCount = 0;
00324 $totalElapsedTime = 0;
00325 $reviewerList = array();
00326 $articleIds = array();
00327
00328 while (!$result->EOF) {
00329 $row = $result->GetRowAssoc(false);
00330 $returner['reviewsCount']++;
00331 if (!empty($row['quality'])) {
00332 $scoredReviewsCount++;
00333 $totalScore += $row['quality'];
00334 }
00335
00336 $articleIds[] = $row['article_id'];
00337
00338 if (!empty($row['reviewer_id']) && !in_array($row['reviewer_id'], $reviewerList)) {
00339 $returner['reviewerCount']++;
00340 $dateRegistered = strtotime($this->datetimeFromDB($row['date_registered']));
00341 if (($dateRegistered >= $dateStart || $dateStart === null) && ($dateRegistered <= $dateEnd || $dateEnd == null)) {
00342 $returner['reviewerAddedCount']++;
00343 }
00344 array_push($reviewerList, $row['reviewer_id']);
00345 }
00346
00347 if (!empty($row['date_assigned']) && !empty($row['date_completed'])) {
00348 $timeReviewVersionUploaded = strtotime($this->datetimeFromDB($row['date_rv_uploaded']));
00349 $timeCompleted = strtotime($this->datetimeFromDB($row['date_completed']));
00350 if ($timeCompleted > $timeReviewVersionUploaded) {
00351 $completedReviewsCount++;
00352 $totalElapsedTime += ($timeCompleted - $timeReviewVersionUploaded);
00353 }
00354 }
00355 $result->moveNext();
00356 }
00357
00358 $result->Close();
00359 unset($result);
00360
00361 if ($scoredReviewsCount > 0) {
00362
00363 $returner['reviewerScore'] = round($totalScore * 10 / $scoredReviewsCount) / 10;
00364 }
00365 if ($completedReviewsCount > 0) {
00366 $seconds = $totalElapsedTime / $completedReviewsCount;
00367 $returner['daysPerReview'] = $seconds / 60 / 60 / 24;
00368 }
00369
00370 $articleIds = array_unique($articleIds);
00371 $returner['reviewedSubmissionsCount'] = count($articleIds);
00372
00373 return $returner;
00374 }
00375
00376 function &getCountryDistribution($journalId, $locale = null) {
00377 if ($locale == null) $locale = Locale::getLocale();
00378 $result = &$this->retrieve(
00379 'SELECT DISTINCT u.country AS country FROM users u, roles r WHERE r.journal_id = ? AND r.user_id = u.user_id',
00380 $journalId
00381 );
00382
00383 $countries = array();
00384 $countryDao =& DAORegistry::getDAO('CountryDAO');
00385 while (!$result->EOF) {
00386 $row = $result->GetRowAssoc(false);
00387 array_push($countries, $countryDao->getCountry($row['country'], $locale));
00388 $result->moveNext();
00389 }
00390
00391 $result->Close();
00392 unset($result);
00393
00394 return $countries;
00395 }
00396
00403 function &getJournalReport($journalId, $dateStart = null, $dateEnd = null) {
00404 $result = &$this->retrieve(
00405 'SELECT a.article_id,
00406 pa.pub_id,
00407 pa.date_published,
00408 s.section_id,
00409 a.date_submitted,
00410 a.status
00411 FROM articles a
00412 LEFT JOIN sections s ON (s.section_id = a.section_id)
00413 LEFT JOIN published_articles pa ON (a.article_id = pa.article_id)
00414 WHERE a.journal_id = ? AND s.section_id IS NOT NULL' .
00415 ($dateStart !== null ? ' AND a.date_submitted >= ' . $this->datetimeToDB($dateStart) : '') .
00416 ($dateEnd !== null ? ' AND a.date_submitted <= ' . $this->datetimeToDB($dateEnd) : '') .
00417 ' ORDER BY a.date_submitted',
00418 $journalId
00419 );
00420 import('journal.JournalReportIterator');
00421 $report =& new JournalReportIterator($journalId, $result, $dateStart, $dateEnd, REPORT_TYPE_JOURNAL);
00422 return $report;
00423 }
00424
00431 function &getSectionReport($journalId, $dateStart = null, $dateEnd = null) {
00432 $result = &$this->retrieve(
00433 'SELECT a.article_id,
00434 pa.pub_id,
00435 pa.date_published,
00436 s.section_id,
00437 a.date_submitted,
00438 a.status
00439 FROM articles a
00440 LEFT JOIN sections s ON (s.section_id = a.section_id)
00441 LEFT JOIN published_articles pa ON (a.article_id = pa.article_id)
00442 WHERE a.journal_id = ? AND s.section_id IS NOT NULL' .
00443 ($dateStart !== null ? ' AND a.date_submitted >= ' . $this->datetimeToDB($dateStart) : '') .
00444 ($dateEnd !== null ? ' AND a.date_submitted <= ' . $this->datetimeToDB($dateEnd) : '') .
00445 ' ORDER BY s.section_id, a.date_submitted',
00446 $journalId
00447 );
00448 import('journal.JournalReportIterator');
00449 $report =& new JournalReportIterator($journalId, $result, $dateStart, $dateEnd, REPORT_TYPE_SECTION);
00450 return $report;
00451 }
00452
00459 function &getReviewerReport($journalId, $dateStart = null, $dateEnd = null) {
00460 $result = &$this->retrieve(
00461 'SELECT ra.reviewer_id,
00462 ra.quality,
00463 a.article_id,
00464 pa.pub_id AS pub_id,
00465 pa.date_published AS date_published,
00466 s.section_id,
00467 a.date_submitted AS date_submitted,
00468 a.status AS status
00469 FROM review_assignments ra,
00470 articles a
00471 LEFT JOIN sections s ON (s.section_id = a.section_id)
00472 LEFT JOIN published_articles pa ON (a.article_id = pa.article_id)
00473 WHERE a.journal_id = ? AND s.section_id IS NOT NULL
00474 AND ra.article_id = a.article_id ' .
00475 ($dateStart !== null ? ' AND a.date_submitted >= ' . $this->datetimeToDB($dateStart) : '') .
00476 ($dateEnd !== null ? ' AND a.date_submitted <= ' . $this->datetimeToDB($dateEnd) : '') .
00477 ' ORDER BY ra.reviewer_id, a.date_submitted',
00478 $journalId
00479 );
00480 import('journal.JournalReportIterator');
00481 $report =& new JournalReportIterator($journalId, $result, $dateStart, $dateEnd, REPORT_TYPE_REVIEWER);
00482 return $report;
00483 }
00484
00491 function &getEditorReport($journalId, $dateStart = null, $dateEnd = null) {
00492 $result = &$this->retrieve(
00493 'SELECT ee.editor_id,
00494 a.article_id,
00495 pa.pub_id,
00496 pa.date_published,
00497 s.section_id,
00498 a.date_submitted,
00499 a.status AS status
00500 FROM articles a
00501 LEFT JOIN edit_assignments ee ON (ee.article_id = a.article_id)
00502 LEFT JOIN sections s ON (s.section_id = a.section_id)
00503 LEFT JOIN published_articles pa ON (a.article_id = pa.article_id)
00504 WHERE a.journal_id = ? AND s.section_id IS NOT NULL' .
00505 ($dateStart !== null ? ' AND a.date_submitted >= ' . $this->datetimeToDB($dateStart) : '') .
00506 ($dateEnd !== null ? ' AND a.date_submitted <= ' . $this->datetimeToDB($dateEnd) : '') .
00507 ' ORDER BY ee.editor_id, a.date_submitted',
00508 $journalId
00509 );
00510 import('journal.JournalReportIterator');
00511 $report =& new JournalReportIterator($journalId, $result, $dateStart, $dateEnd, REPORT_TYPE_EDITOR);
00512 return $report;
00513 }
00514
00522 function getMaxAuthorCount($journalId, $dateStart, $dateEnd) {
00523 $result = &$this->retrieve(
00524 'SELECT COUNT(aa.author_id)
00525 FROM articles a,
00526 article_authors aa
00527 WHERE a.journal_id = ?
00528 AND aa.article_id = a.article_id ' .
00529 ($dateStart !== null ? ' AND a.date_submitted >= ' . $this->datetimeToDB($dateStart) : '') .
00530 ($dateEnd !== null ? ' AND a.date_submitted <= ' . $this->datetimeToDB($dateEnd) : '') .
00531 ' GROUP BY a.article_id',
00532 $journalId
00533 );
00534
00535 $max = null;
00536 while (!$result->EOF) {
00537 if ($max === null || $max < $result->fields[0]) {
00538 $max = $result->fields[0];
00539 }
00540 $result->moveNext();
00541 }
00542
00543 $result->Close();
00544 unset($result);
00545
00546 return $max;
00547 }
00548
00556 function getMaxReviewerCount($journalId, $dateStart, $dateEnd) {
00557 $result = &$this->retrieve(
00558 'SELECT COUNT(r.review_id)
00559 FROM articles a,
00560 review_assignments r
00561 WHERE a.journal_id = ?
00562 AND r.article_id = a.article_id ' .
00563 ($dateStart !== null ? ' AND a.date_submitted >= ' . $this->datetimeToDB($dateStart) : '') .
00564 ($dateEnd !== null ? ' AND a.date_submitted <= ' . $this->datetimeToDB($dateEnd) : '') .
00565 ' GROUP BY r.article_id',
00566 $journalId
00567 );
00568
00569 $max = null;
00570 while (!$result->EOF) {
00571 if ($max === null || $max < $result->fields[0]) {
00572 $max = $result->fields[0];
00573 }
00574 $result->moveNext();
00575 }
00576
00577 $result->Close();
00578 unset($result);
00579
00580 return $max;
00581 }
00582
00590 function getMaxEditorCount($journalId, $dateStart, $dateEnd) {
00591 $result = &$this->retrieve(
00592 'SELECT COUNT(e.editor_id)
00593 FROM articles a,
00594 edit_assignments e
00595 WHERE a.journal_id = ?
00596 AND e.article_id = a.article_id ' .
00597 ($dateStart !== null ? ' AND a.date_submitted >= ' . $this->datetimeToDB($dateStart) : '') .
00598 ($dateEnd !== null ? ' AND a.date_submitted <= ' . $this->datetimeToDB($dateEnd) : '') .
00599 ' GROUP BY e.article_id',
00600 $journalId
00601 );
00602
00603 $max = null;
00604 while (!$result->EOF) {
00605 if ($max === null || $max < $result->fields[0]) {
00606 $max = $result->fields[0];
00607 }
00608 $result->moveNext();
00609 }
00610
00611 $result->Close();
00612 unset($result);
00613
00614 return $max;
00615 }
00616 }
00617
00618 ?>