123 lines
3.9 KiB
PHP
123 lines
3.9 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file classes/services/PKPStatsServiceTrait.php
|
|
*
|
|
* Copyright (c) 2022 Simon Fraser University
|
|
* Copyright (c) 2022 John Willinsky
|
|
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
|
*
|
|
* @class PKPStatsServiceTrait
|
|
*
|
|
* @ingroup services
|
|
*
|
|
* @brief Helper class that encapsulates publication statistics business logic
|
|
*/
|
|
|
|
namespace PKP\services;
|
|
|
|
use APP\core\Application;
|
|
use PKP\core\PKPString;
|
|
use PKP\plugins\Hook;
|
|
use PKP\statistics\PKPStatisticsHelper;
|
|
|
|
trait PKPStatsServiceTrait
|
|
{
|
|
/**
|
|
* Get the sum of a set of metrics broken down by day or month
|
|
*
|
|
* @param string $timelineInterval PKPStatisticsHelper::STATISTICS_DIMENSION_MONTH or PKPStatisticsHelper::STATISTICS_DIMENSION_DAY
|
|
* @param array $args Filter the records to include. See self::getQueryBuilder()
|
|
*
|
|
*/
|
|
public function getTimeline(string $timelineInterval, array $args = []): array
|
|
{
|
|
$defaultArgs = $this->getDefaultArgs();
|
|
$args = array_merge($defaultArgs, $args);
|
|
$timelineQB = $this->getQueryBuilder($args);
|
|
|
|
Hook::call('Stats::getTimeline::queryBuilder', [&$timelineQB, $args]);
|
|
|
|
$orderDirection = 'asc';
|
|
if (array_key_exists('orderDirection', $args)) {
|
|
$orderDirection = strtolower($args['orderDirection']);
|
|
}
|
|
$timelineQO = $timelineQB
|
|
->getSum([$timelineInterval])
|
|
->orderBy($timelineInterval, $orderDirection);
|
|
|
|
$result = $timelineQO->get();
|
|
|
|
$dateValues = [];
|
|
foreach ($result as $row) {
|
|
$date = $row->$timelineInterval;
|
|
if ($timelineInterval === PKPStatisticsHelper::STATISTICS_DIMENSION_MONTH) {
|
|
$date = substr($date, 0, 7);
|
|
}
|
|
$dateValues[$date] = $row->metric;
|
|
}
|
|
|
|
$timeline = $this->getEmptyTimelineIntervals($args['dateStart'], $args['dateEnd'], $timelineInterval);
|
|
|
|
$timeline = array_map(function ($entry) use ($dateValues) {
|
|
foreach ($dateValues as $date => $value) {
|
|
if ($entry['date'] === $date) {
|
|
$entry['value'] = $value;
|
|
break;
|
|
}
|
|
}
|
|
return $entry;
|
|
}, $timeline);
|
|
|
|
return $timeline;
|
|
}
|
|
|
|
/**
|
|
* Get all time segments (months or days) between the start and end date
|
|
* with empty values.
|
|
*
|
|
* @param string $timelineInterval PKPStatisticsHelper::STATISTICS_DIMENSION_MONTH or PKPStatisticsHelper::STATISTICS_DIMENSION_DAY
|
|
*
|
|
* @return array of time segments in ASC order
|
|
*/
|
|
public function getEmptyTimelineIntervals(string $startDate, string $endDate, string $timelineInterval): array
|
|
{
|
|
if ($timelineInterval === PKPStatisticsHelper::STATISTICS_DIMENSION_MONTH) {
|
|
$dateFormat = 'Y-m';
|
|
$labelFormat = 'F Y';
|
|
$interval = 'P1M';
|
|
} elseif ($timelineInterval === PKPStatisticsHelper::STATISTICS_DIMENSION_DAY) {
|
|
$dateFormat = 'Y-m-d';
|
|
$labelFormat = PKPString::convertStrftimeFormat(Application::get()->getRequest()->getContext()->getLocalizedDateFormatLong());
|
|
$interval = 'P1D';
|
|
}
|
|
|
|
$startDate = new \DateTime($startDate);
|
|
$endDate = new \DateTime($endDate);
|
|
|
|
$timelineIntervals = [];
|
|
while ($startDate->format($dateFormat) <= $endDate->format($dateFormat)) {
|
|
$timelineIntervals[] = [
|
|
'date' => $startDate->format($dateFormat),
|
|
'label' => date($labelFormat, $startDate->getTimestamp()),
|
|
'value' => 0,
|
|
];
|
|
$startDate->add(new \DateInterval($interval));
|
|
}
|
|
|
|
return $timelineIntervals;
|
|
}
|
|
|
|
/**
|
|
* Get column names for the timeline CSV report
|
|
*/
|
|
public function getTimelineReportColumnNames(): array
|
|
{
|
|
return [
|
|
__('common.date'),
|
|
__('common.label'),
|
|
__('stats.total')
|
|
];
|
|
}
|
|
}
|