File Manager
Upload
Current Directory: /home/lartcid/public_html/journal.lartc.id
[Back]
..
[Open]
Hapus
Rename
.htaccess
[Edit]
Hapus
Rename
.well-known
[Open]
Hapus
Rename
README.md
[Edit]
Hapus
Rename
api
[Open]
Hapus
Rename
cache
[Open]
Hapus
Rename
cgi-bin
[Open]
Hapus
Rename
classes
[Open]
Hapus
Rename
config.TEMPLATE.inc.php
[Edit]
Hapus
Rename
config.inc.php
[Edit]
Hapus
Rename
controllers
[Open]
Hapus
Rename
cypress.json
[Edit]
Hapus
Rename
dbscripts
[Open]
Hapus
Rename
docs
[Open]
Hapus
Rename
error_log
[Edit]
Hapus
Rename
favicon.ico
[Edit]
Hapus
Rename
index.php
[Edit]
Hapus
Rename
js
[Open]
Hapus
Rename
lib
[Open]
Hapus
Rename
locale
[Open]
Hapus
Rename
mini.php
[Edit]
Hapus
Rename
pages
[Open]
Hapus
Rename
php.ini
[Edit]
Hapus
Rename
plugins
[Open]
Hapus
Rename
public
[Open]
Hapus
Rename
registry
[Open]
Hapus
Rename
scheduledTaskLogs
[Open]
Hapus
Rename
schemas
[Open]
Hapus
Rename
styles
[Open]
Hapus
Rename
templates
[Open]
Hapus
Rename
tools
[Open]
Hapus
Rename
Edit File
<?php /** * @file classes/services/PKPStatsService.inc.php * * Copyright (c) 2014-2021 Simon Fraser University * Copyright (c) 2000-2021 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class PKPStatsService * @ingroup services * * @brief Helper class that encapsulates statistics business logic */ namespace PKP\Services; use function PHP81_BC\strftime; class PKPStatsService { /** * Get all statistics records that match the passed arguments * * @param array $args [ * @option array contextIds Return records for these contexts * @option array submissionIds Return records for these submissions * @option array sectionIds Return records for these sections * @option string dateEnd Return records on or before this date * @option string dateStart Return records on or after this date * @option array assocTypes Return records for these types of objects. One of ASSOC_TYPE_* * @option array assocIds Return records for these objects. Only used when assocTypes is set. * @option array fileTypes Return records for these file types. One of STATISTICS_FILE_TYPE_* * ] * @return array */ public function getRecords($args = []) { // Get the stats constants import('classes.statistics.StatisticsHelper'); $defaultArgs = [ 'dateStart' => STATISTICS_EARLIEST_DATE, 'dateEnd' => date('Y-m-d', strtotime('yesterday')), // Require a context to be specified to prevent unwanted data leakage // if someone forgets to specify the context. 'contextIds' => [CONTEXT_ID_NONE], ]; $args = array_merge($defaultArgs, $args); $statsQB = $this->getQueryBuilder($args); \HookRegistry::call('Stats::getRecords::queryBuilder', array(&$statsQB, $args)); $statsQO = $statsQB->getRecords(); $result = \DAORegistry::getDAO('MetricsDAO') ->retrieve($statsQO->toSql(), $statsQO->getBindings()); $records = []; foreach ($result as $row) { $records[] = [ 'loadId' => $row->load_id, 'contextId' => (int) $row->context_id, 'submissionId' => (int) $row->submission_id, 'assocType' => (int) $row->assoc_type, 'assocId' => (int) $row->assoc_id, 'day' => (int) $row->day, 'month' => (int) $row->month, 'fileType' => (int) $row->file_type, 'countryId' => $row->country_id, 'region' => $row->region, 'city' => $row->city, 'metric' => (int) $row->metric, 'metricType' => $row->metric_type, 'pkpSectionId' => (int) $row->pkp_section_id, 'assocObjectType' => (int) $row->assoc_object_type, 'assocObjectTId' => (int) $row->assoc_object_id, 'representation_id' => (int) $row->representation_id, ]; } return $records; } /** * Get the sum of a set of metrics broken down by day or month * * @param string $timelineInterval STATISTICS_DIMENSION_MONTH or STATISTICS_DIMENSION_DAY * @param array $args Filter the records to include. See self::getRecords() * @return array */ public function getTimeline($timelineInterval, $args = []) { $defaultArgs = [ 'dateStart' => STATISTICS_EARLIEST_DATE, 'dateEnd' => date('Y-m-d', strtotime('yesterday')), // Require a context to be specified to prevent unwanted data leakage // if someone forgets to specify the context. If you really want to // get data across all contexts, pass an empty `contextId` arg. 'contextIds' => [CONTEXT_ID_NONE], ]; $args = array_merge($defaultArgs, $args); $timelineQB = $this->getQueryBuilder($args); \HookRegistry::call('Stats::getTimeline::queryBuilder', array(&$timelineQB, $args)); $timelineQO = $timelineQB ->getSum([$timelineInterval]) ->orderBy($timelineInterval); $result = \DAORegistry::getDAO('MetricsDAO') ->retrieve($timelineQO->toSql(), $timelineQO->getBindings()); $dateValues = []; foreach ($result as $row) { $row = (array) $row; $date = substr($row[$timelineInterval], 0, 4) . '-' . substr($row[$timelineInterval], 4, 2); if ($timelineInterval === STATISTICS_DIMENSION_DAY) { $date = substr($date, 0, 7) . '-' . substr($row[$timelineInterval], 6, 2); } $dateValues[$date] = (int) $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 a list of objects ordered by their total stats * * The $args argument is used to determine what records to include in * the results. The $groupBy argument is used to group these records. * * For example, to get a list of submissions ordered by their total PDF * galley views: * * // Get all records with the PDF file type * $args = ['fileType' => STATISTICS_FILE_TYPE_PDF] * * // Group them by their submission ID * $groupBy = STATISTICS_DIMENSION_SUBMISSION_ID * * @param string $groupBy The column to sum the stats by. * @param string $orderDirection STATISTICS_ORDER_ASC or STATISTICS_ORDER_DESC * @param array $args Filter the records to include. See self::getRecords() */ public function getOrderedObjects($groupBy, $orderDirection, $args = []) { $defaultArgs = [ 'dateStart' => STATISTICS_EARLIEST_DATE, 'dateEnd' => date('Y-m-d', strtotime('yesterday')), // Require a context to be specified to prevent unwanted data leakage // if someone forgets to specify the context. If you really want to // get data across all contexts, pass an empty `contextId` arg. 'contextIds' => [CONTEXT_ID_NONE], ]; $args = array_merge($defaultArgs, $args); $orderedQB = $this->getQueryBuilder($args); \HookRegistry::call('Stats::getOrderedObjects::queryBuilder', array(&$orderedQB, $args)); $orderedQO = $orderedQB ->getSum([$groupBy]) ->orderBy('metric', $orderDirection === STATISTICS_ORDER_ASC ? 'asc' : 'desc'); $range = null; if (isset($args['count'])) { import('lib.pkp.classes.db.DBResultRange'); $range = new \DBResultRange($args['count'], null, isset($args['offset']) ? $args['offset'] : 0); } $result = \DAORegistry::getDAO('MetricsDAO') ->retrieveRange($orderedQO->toSql(), $orderedQO->getBindings(), $range); $objects = []; foreach ($result as $row) { $row = (array) $row; $objects[] = [ 'id' => (int) $row[$groupBy], 'total' => (int) $row['metric'], ]; } return $objects; } /** * A callback to be used with array_reduce() to add up the metric value * for a record * * @param array $record * @return integer */ public function sumMetric($total, $record) { $total += $record['metric']; return $total; } /** * A callback to be used with array_filter() to return records for * a file (galley, representation). * * @param array $record * @return array */ public function filterRecordFile($record) { return !empty($record['fileType']); } /** * A callback to be used with array_filter() to return records for * a pdf file. * * @param array $record * @return array */ public function filterRecordPdf($record) { return $record['fileType'] === STATISTICS_FILE_TYPE_PDF; } /** * A callback to be used with array_filter() to return records for * a HTML file. * * @param array $record * @return array */ public function filterRecordHtml($record) { return $record['fileType'] === STATISTICS_FILE_TYPE_HTML; } /** * A callback to be used with array_filter() to return records for * any Other files (all files that are not PDF or HTML). * * @param array $record * @return array */ public function filterRecordOther($record) { return $record['fileType'] === STATISTICS_FILE_TYPE_OTHER; } /** * Get all time segments (months or days) between the start and end date * with empty values. * * @param $startDate string * @param $endDate string * @param $timelineInterval string STATISTICS_DIMENSION_MONTH or STATISTICS_DIMENSION_DAY * @return array of time segments in ASC order */ public function getEmptyTimelineIntervals($startDate, $endDate, $timelineInterval) { if ($timelineInterval === STATISTICS_DIMENSION_MONTH) { $dateFormat = 'Y-m'; $labelFormat = '%B %Y'; $interval = 'P1M'; } elseif ($timelineInterval === STATISTICS_DIMENSION_DAY) { $dateFormat = 'Y-m-d'; $labelFormat = \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' => strftime($labelFormat, $startDate->getTimestamp()), 'value' => 0, ]; $startDate->add(new \DateInterval($interval)); } return $timelineIntervals; } /** * Get a QueryBuilder object with the passed args * * @param array $args See self::getRecords() * @return \PKP\Services\QueryBuilders\PKPStatsQueryBuilder */ protected function getQueryBuilder($args = []) { $statsQB = new \PKP\Services\QueryBuilders\PKPStatsQueryBuilder(); $statsQB ->filterByContexts($args['contextIds']) ->before($args['dateEnd']) ->after($args['dateStart']); if (!empty(($args['submissionIds']))) { $statsQB->filterBySubmissions($args['submissionIds']); } if (!empty($args['assocTypes'])) { $statsQB->filterByAssocTypes($args['assocTypes']); if (!empty($args['assocIds'])) { $statsQB->filterByAssocIds($args['assocIds']); } } if (!empty($args['fileTypes'])) { $statsQB->filterByFileTypes(($args['fileTypes'])); } \HookRegistry::call('Stats::queryBuilder', array(&$statsQB, $args)); return $statsQB; } }
Simpan