Open Monograph Press  3.3.0
PKPStatsEditorialQueryBuilder.inc.php
1 <?php
2 
18 
19 use Illuminate\Database\Capsule\Manager as Capsule;
20 
22 
24  protected $contextIds = [];
25 
27  protected $dateEnd;
28 
30  protected $dateStart;
31 
33  protected $sectionIds = [];
34 
36  public $sectionIdsColumn;
37 
44  public function filterByContexts($contextIds) {
45  $this->contextIds = is_array($contextIds) ? $contextIds : [$contextIds];
46  return $this;
47  }
48 
56  public function filterBySections($sectionIds) {
57  $this->sectionIds = is_array($sectionIds) ? $sectionIds : [$sectionIds];
58  return $this;
59  }
60 
67  public function before($dateEnd) {
68  $this->dateEnd = $dateEnd;
69  return $this;
70  }
71 
78  public function after($dateStart) {
79  $this->dateStart = $dateStart;
80  return $this;
81  }
82 
88  public function countSubmissionsReceived() {
89  $q = $this->_getObject();
90  if ($this->dateStart) {
91  $q->where('s.date_submitted', '>=', $this->dateStart);
92  }
93  if ($this->dateEnd) {
94  $q->where('s.date_submitted', '<=', $this->dateEnd);
95  }
96 
97  return $q->count();
98  }
99 
112  public function countByDecisions($decisions, $forSubmittedDate = false) {
113 
114  $q = $this->_getObject();
115  $q->leftJoin('edit_decisions as ed', 's.submission_id', '=', 'ed.submission_id')
116  ->whereIn('ed.decision', $decisions);
117 
118  if ($forSubmittedDate) {
119  if ($this->dateStart) {
120  $q->where('s.date_submitted', '>=', $this->dateStart);
121  }
122  if ($this->dateEnd) {
123  // Include date time values up to the end of the day
124  $dateTime = new \DateTime($this->dateEnd);
125  $dateTime->add(new \DateInterval('P1D'));
126  $q->where('s.date_submitted', '<', $dateTime->format('Y-m-d'));
127  }
128 
129  } else {
130  if ($this->dateStart) {
131  $q->where('ed.date_decided', '>=', $this->dateStart);
132  }
133  if ($this->dateEnd) {
134  // Include date time values up to the end of the day
135  $dateTime = new \DateTime($this->dateEnd);
136  $dateTime->add(new \DateInterval('P1D'));
137  $q->where('ed.date_decided', '<', $dateTime->format('Y-m-d'));
138  }
139  }
140 
141  // Ensure that the decisions being counted have not been
142  // reversed. For example, a submission may have been accepted
143  // and then later declined. We check the current status to
144  // exclude submissions where the status doesn't match the
145  // decisions we are looking for.
146  $declineDecisions = [SUBMISSION_EDITOR_DECISION_DECLINE, SUBMISSION_EDITOR_DECISION_INITIAL_DECLINE];
147  if (count(array_intersect($declineDecisions, $decisions))) {
148  $q->where('s.status', '=', STATUS_DECLINED);
149  } else {
150  $q->where('s.status', '!=', STATUS_DECLINED);
151  }
152 
153  $q->select(Capsule::raw('COUNT(DISTINCT s.submission_id) as count'));
154 
155  return $q->get()->first()->count;
156  }
157 
164  public function countByStatus($status) {
165  return $this->_getObject()
166  ->whereIn('s.status', (array) $status)
167  ->count();
168  }
169 
176  public function countActiveByStages($stages) {
177  import('lib.pkp.classes.submission.PKPSubmission');
178 
179  return $this->_getObject()
180  ->where('s.status', '=', STATUS_QUEUED)
181  ->whereIn('s.stage_id', $stages)
182  ->count();
183  }
184 
190  public function countPublished() {
191  $q = $this->_getObject()
192  ->where('s.status', '=', STATUS_PUBLISHED);
193 
194  // Only match against the publication date of a
195  // submission's first published publication so
196  // that updated versions are excluded.
197  if ($this->dateStart || $this->dateEnd) {
198  $q->leftJoin('publications as p', function($q) {
199  $q->where('p.publication_id', function($q) {
200  $q->from('publications as p2')
201  ->where('p2.submission_id', '=', Capsule::raw('s.submission_id'))
202  ->where('p2.status', '=', STATUS_PUBLISHED)
203  ->orderBy('p2.date_published', 'ASC')
204  ->limit(1)
205  ->select('p2.publication_id');
206  });
207  });
208  if ($this->dateStart) {
209  $q->where('p.date_published', '>=', $this->dateStart);
210  }
211  if ($this->dateEnd) {
212  $q->where('p.date_published', '<=', $this->dateEnd);
213  }
214  }
215 
216  return $q->count();
217  }
218 
229  public function getDaysToDecisions($decisions) {
230  $q = $this->_getDaysToDecisionsObject($decisions);
231  $dateDiff = $this->_dateDiff('ed.date_decided', 's.date_submitted');
232  $q->select(Capsule::raw($dateDiff . ' as time'));
233  return $q->pluck('time')->toArray();
234  }
235 
247  public function getAverageDaysToDecisions($decisions) {
248  $q = $this->_getDaysToDecisionsObject($decisions);
249  $dateDiff = $this->_dateDiff('ed.date_decided', 's.date_submitted');
250  $q->select(Capsule::raw('AVG(' . $dateDiff . ') as average'));
251  return $q->get()->first()->average;
252  }
253 
259  public function getSubmissionsReceivedDates() {
260  $q = $this->_getObject();
261  return [$q->min('s.date_submitted'), $q->max('s.date_submitted')];
262  }
263 
269  public function getPublishedDates() {
270  import('lib.pkp.classes.submission.PKPSubmission');
271 
272  $q = $this->_getObject()
273  ->where('s.status', '=', STATUS_PUBLISHED)
274  // Only match against the publication date of a
275  // submission's first published publication so
276  // that updated versions are excluded.
277  ->leftJoin('publications as p', function($q) {
278  $q->where('p.publication_id', function($q) {
279  $q->from('publications as p2')
280  ->where('p2.submission_id', '=', Capsule::raw('s.submission_id'))
281  ->where('p2.status', '=', STATUS_PUBLISHED)
282  ->orderBy('p2.date_published', 'ASC')
283  ->limit(1)
284  ->select('p2.publication_id');
285  });
286  });
287 
288  return [$q->min('p.date_published'), $q->max('p.date_published')];
289  }
290 
297  public function getDecisionsDates($decisions) {
298  import('lib.pkp.classes.submission.PKPSubmission');
299  $q = $this->_getObject();
300  $q->leftJoin('edit_decisions as ed', 's.submission_id', '=', 'ed.submission_id')
301  ->whereIn('ed.decision', $decisions);
302 
303  // Ensure that the decisions being counted have not been
304  // reversed. For example, a submission may have been accepted
305  // and then later declined. We check the current status to
306  // exclude submissions where the status doesn't match the
307  // decisions we are looking for.
308  $declineDecisions = [SUBMISSION_EDITOR_DECISION_DECLINE, SUBMISSION_EDITOR_DECISION_INITIAL_DECLINE];
309  if (count(array_intersect($declineDecisions, $decisions))) {
310  $q->where('s.status', '=', STATUS_DECLINED);
311  } else {
312  $q->where('s.status', '!=', STATUS_DECLINED);
313  }
314 
315  return [$q->min('ed.date_decided'), $q->max('ed.date_decided')];
316  }
317 
326  protected function _getObject() {
327  $q = Capsule::table('submissions as s');
328  if (!empty($this->contextIds)) {
329  $q->whereIn('s.context_id', $this->contextIds);
330  }
331  if (!empty($this->sectionIds)) {
332  $q->leftJoin('publications as ps', 's.current_publication_id', '=', 'ps.publication_id')
333  ->whereIn('ps.' . $this->sectionIdsColumn, $this->sectionIds)
334  ->whereNotNull('ps.publication_id');
335  }
336 
337  // Exclude incomplete submissions
338  $q->where('s.submission_progress', '=', 0);
339 
340  // Exclude submissions when the date_submitted is later
341  // than the first date_published. This prevents imported
342  // submissions from being counted in editorial stats.
343  $q->leftJoin('publications as pi', function($q) {
344  $q->where('pi.publication_id', function($q) {
345  $q->from('publications as pi2')
346  ->where('pi2.submission_id', '=', Capsule::raw('s.submission_id'))
347  ->where('pi2.status', '=', STATUS_PUBLISHED)
348  ->orderBy('pi2.date_published', 'ASC')
349  ->limit(1)
350  ->select('pi2.publication_id');
351  });
352  })
353  ->where(function($q) {
354  $q->whereNull('pi.date_published')
355  ->orWhere('s.date_submitted', '<', Capsule::raw('pi.date_published'));
356  });
357 
358  \HookRegistry::call('Stats::editorial::queryObject', array($q, $this));
359 
360  return $q;
361  }
362 
373  protected function _getDaysToDecisionsObject($decisions) {
374 
375  $q = $this->_getObject();
376 
377  $q->leftJoin('edit_decisions as ed', function($q) use ($decisions) {
378  $q->where('ed.edit_decision_id', function($q) use ($decisions) {
379  $q->from('edit_decisions as ed2')
380  ->where('ed2.submission_id', '=', Capsule::raw('s.submission_id'));
381  if (!empty($decisions)) {
382  $q->whereIn('ed2.decision', $decisions);
383  }
384  $q->orderBy('ed2.date_decided', 'ASC')
385  ->limit(1)
386  ->select('ed2.edit_decision_id');
387  });
388  });
389 
390  $q->whereNotNull('ed.submission_id')
391  ->whereNotNull('s.date_submitted');
392 
393  if ($this->dateStart) {
394  $q->where('s.date_submitted', '>=', $this->dateStart);
395  }
396  if ($this->dateEnd) {
397  // Include date time values up to the end of the day
398  $dateTime = new \DateTime($this->dateEnd);
399  $dateTime->add(new \DateInterval('P1D'));
400  $q->where('s.date_submitted', '<=', $dateTime->format('Y-m-d'));
401  }
402 
403  return $q;
404  }
405 
412  private function _dateDiff(string $leftDate, string $rightDate) {
413  switch (\Config::getVar('database', 'driver')) {
414  case 'mysql':
415  case 'mysqli':
416  return 'DATEDIFF(' . $leftDate . ',' . $rightDate . ')';
417  }
418  return "DATE_PART('day', " . $leftDate . " - " . $rightDate . ")";
419  }
420 }
421 
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\getPublishedDates
getPublishedDates()
Definition: PKPStatsEditorialQueryBuilder.inc.php:284
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\countActiveByStages
countActiveByStages($stages)
Definition: PKPStatsEditorialQueryBuilder.inc.php:191
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\getDaysToDecisions
getDaysToDecisions($decisions)
Definition: PKPStatsEditorialQueryBuilder.inc.php:244
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\$sectionIdsColumn
$sectionIdsColumn
Definition: PKPStatsEditorialQueryBuilder.inc.php:51
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\_getObject
_getObject()
Definition: PKPStatsEditorialQueryBuilder.inc.php:341
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\countByDecisions
countByDecisions($decisions, $forSubmittedDate=false)
Definition: PKPStatsEditorialQueryBuilder.inc.php:127
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\before
before($dateEnd)
Definition: PKPStatsEditorialQueryBuilder.inc.php:82
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\$sectionIds
$sectionIds
Definition: PKPStatsEditorialQueryBuilder.inc.php:45
PKP\Services\QueryBuilders
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\$contextIds
$contextIds
Definition: PKPStatsEditorialQueryBuilder.inc.php:27
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder
Definition: PKPStatsEditorialQueryBuilder.inc.php:21
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\countPublished
countPublished()
Definition: PKPStatsEditorialQueryBuilder.inc.php:205
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\_getDaysToDecisionsObject
_getDaysToDecisionsObject($decisions)
Definition: PKPStatsEditorialQueryBuilder.inc.php:388
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\countByStatus
countByStatus($status)
Definition: PKPStatsEditorialQueryBuilder.inc.php:179
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\getSubmissionsReceivedDates
getSubmissionsReceivedDates()
Definition: PKPStatsEditorialQueryBuilder.inc.php:274
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\after
after($dateStart)
Definition: PKPStatsEditorialQueryBuilder.inc.php:93
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\countSubmissionsReceived
countSubmissionsReceived()
Definition: PKPStatsEditorialQueryBuilder.inc.php:103
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\$dateStart
$dateStart
Definition: PKPStatsEditorialQueryBuilder.inc.php:39
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\filterByContexts
filterByContexts($contextIds)
Definition: PKPStatsEditorialQueryBuilder.inc.php:59
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\filterBySections
filterBySections($sectionIds)
Definition: PKPStatsEditorialQueryBuilder.inc.php:71
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\$dateEnd
$dateEnd
Definition: PKPStatsEditorialQueryBuilder.inc.php:33
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\getAverageDaysToDecisions
getAverageDaysToDecisions($decisions)
Definition: PKPStatsEditorialQueryBuilder.inc.php:262
PKP\Services\QueryBuilders\PKPStatsEditorialQueryBuilder\getDecisionsDates
getDecisionsDates($decisions)
Definition: PKPStatsEditorialQueryBuilder.inc.php:312