17 import(
'lib.pkp.classes.handler.APIHandler');
18 import(
'classes.core.Services');
19 import(
'classes.statistics.StatisticsHelper');
20 import(
'lib.pkp.classes.submission.PKPSubmission');
28 $this->_handlerPath =
'stats/publications';
29 $roles = array(ROLE_ID_SITE_ADMIN, ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR);
30 $this->_endpoints = array(
34 'handler' => array($this,
'getMany'),
39 'handler' => array($this,
'getManyAbstract'),
44 'handler' => array($this,
'getManyGalley'),
49 'handler' => array($this,
'get'),
54 'handler' => array($this,
'getAbstract'),
59 'handler' => array($this,
'getGalley'),
64 parent::__construct();
70 function authorize($request, &$args, $roleAssignments) {
74 import(
'lib.pkp.classes.security.authorization.ContextAccessPolicy');
77 import(
'lib.pkp.classes.security.authorization.PolicySet');
78 $rolePolicy =
new PolicySet(COMBINING_PERMIT_OVERRIDES);
79 import(
'lib.pkp.classes.security.authorization.RoleBasedHandlerOperationPolicy');
80 foreach ($roleAssignments as $role => $operations) {
85 if (!is_null($slimRequest) && ($route = $slimRequest->getAttribute(
'route'))) {
86 $routeName = $route->getName();
88 if (in_array($routeName, [
'get',
'getAbstract',
'getGalley'])) {
89 import(
'lib.pkp.classes.security.authorization.SubmissionAccessPolicy');
93 return parent::authorize($request, $args, $roleAssignments);
107 public function getMany($slimRequest, $response, $args) {
110 if (!$request->getContext()) {
111 return $response->withStatus(404)->withJsonError(
'api.404.resourceNotFound');
117 'orderDirection' => STATISTICS_ORDER_DESC,
120 $requestParams = array_merge($defaultParams, $slimRequest->getQueryParams());
129 $this->sectionIdsQueryParam,
133 $allowedParams[
'contextIds'] = $request->getContext()->getId();
135 \HookRegistry::call(
'API::stats::publications::params', array(&$allowedParams, $slimRequest));
138 if ($result !==
true) {
139 return $response->withStatus(400)->withJsonError($result);
142 if (!in_array($allowedParams[
'orderDirection'], [STATISTICS_ORDER_ASC, STATISTICS_ORDER_DESC])) {
143 return $response->withStatus(400)->withJsonError(
'api.stats.400.invalidOrderDirection');
147 if (!empty($allowedParams[
'searchPhrase'])) {
148 $allowedSubmissionIds = empty($allowedParams[
'submissionIds']) ? [] : $allowedParams[
'submissionIds'];
149 $allowedParams[
'submissionIds'] = $this->
_processSearchPhrase($allowedParams[
'searchPhrase'], $allowedSubmissionIds);
151 if (empty($allowedParams[
'submissionIds'])) {
152 return $response->withJson([
161 $totals = $statsService->getOrderedObjects(STATISTICS_DIMENSION_SUBMISSION_ID, $allowedParams[
'orderDirection'], array_merge($allowedParams, [
162 'assocTypes' => [ASSOC_TYPE_SUBMISSION, ASSOC_TYPE_SUBMISSION_FILE]
167 foreach ($totals as $total) {
168 if (empty($total[
'id'])) {
172 $galleyRecords = $statsService->getRecords(array_merge($allowedParams, [
173 'assocTypes' => ASSOC_TYPE_SUBMISSION_FILE,
174 'submissionIds' => [$total[
'id']],
178 $galleyViews = array_reduce($galleyRecords, [$statsService,
'sumMetric'], 0);
179 $pdfViews = array_reduce(array_filter($galleyRecords, [$statsService,
'filterRecordPdf']), [$statsService,
'sumMetric'], 0);
180 $htmlViews = array_reduce(array_filter($galleyRecords, [$statsService,
'filterRecordHtml']), [$statsService,
'sumMetric'], 0);
181 $otherViews = array_reduce(array_filter($galleyRecords, [$statsService,
'filterRecordOther']), [$statsService,
'sumMetric'], 0);
184 $abstractRecords = $statsService->getRecords(array_merge($allowedParams, [
185 'assocTypes' => ASSOC_TYPE_SUBMISSION,
186 'submissionIds' => [$total[
'id']],
188 $abstractViews = array_reduce($abstractRecords, [$statsService,
'sumMetric'], 0);
192 $getPropertiesArgs = [
193 'request' => $request,
194 'slimRequest' => $slimRequest,
197 $submissionProps = [
'id' => $total[
'id']];
209 $submissionProps = array_merge(
212 $submission->getCurrentPublication(),
214 'authorsStringShort',
223 'abstractViews' => $abstractViews,
224 'galleyViews' => $galleyViews,
225 'pdfViews' => $pdfViews,
226 'htmlViews' => $htmlViews,
227 'otherViews' => $otherViews,
228 'publication' => $submissionProps,
233 $statsQB = new \PKP\Services\QueryBuilders\PKPStatsQueryBuilder();
236 ->before(isset($allowedParams[
'dateEnd']) ? $allowedParams[
'dateEnd'] : STATISTICS_YESTERDAY)
237 ->after(isset($allowedParams[
'dateStart']) ? $allowedParams[
'dateStart'] : STATISTICS_EARLIEST_DATE);
238 if (isset($allowedParams[$this->sectionIdsQueryParam])) {
239 $statsQB->filterBySections($allowedParams[$this->sectionIdsQueryParam]);
241 if (isset($allowedParams[
'submissionIds'])) {
242 $statsQB->filterBySubmissions($allowedParams[
'submissionIds']);
244 $statsQO = $statsQB->getSubmissionIds();
246 ->retrieve($statsQO->toSql(), $statsQO->getBindings());
247 $itemsMax = $result->RecordCount();
249 return $response->withJson([
251 'itemsMax' => $itemsMax,
267 if (!$request->getContext()) {
268 return $response->withStatus(404)->withJsonError(
'api.404.resourceNotFound');
272 'timelineInterval' => STATISTICS_DIMENSION_MONTH,
275 $requestParams = array_merge($defaultParams, $slimRequest->getQueryParams());
282 $this->sectionIdsQueryParam,
286 \HookRegistry::call(
'API::stats::publications::abstract::params', array(&$allowedParams, $slimRequest));
288 if (!in_array($allowedParams[
'timelineInterval'], [STATISTICS_DIMENSION_DAY, STATISTICS_DIMENSION_MONTH])) {
289 return $response->withStatus(400)->withJsonError(
'api.stats.400.wrongTimelineInterval');
293 if ($result !==
true) {
294 return $response->withStatus(400)->withJsonError($result);
297 $allowedParams[
'contextIds'] = $request->getContext()->getId();
298 $allowedParams[
'assocTypes'] = ASSOC_TYPE_SUBMISSION;
301 if (!empty($allowedParams[
'searchPhrase'])) {
302 $allowedSubmissionIds = empty($allowedParams[
'submissionIds']) ? [] : $allowedParams[
'submissionIds'];
303 $allowedParams[
'submissionIds'] = $this->
_processSearchPhrase($allowedParams[
'searchPhrase'], $allowedSubmissionIds);
305 if (empty($allowedParams[
'submissionIds'])) {
306 $dateStart = empty($allowedParams[
'dateStart']) ? STATISTICS_EARLIEST_DATE : $allowedParams[
'dateStart'];
307 $dateEnd = empty($allowedParams[
'dateEnd']) ? date(
'Ymd', strtotime(
'yesterday')) : $allowedParams[
'dateEnd'];
308 $emptyTimeline =
\Services::get(
'stats')->getEmptyTimelineIntervals($dateStart, $dateEnd, $allowedParams[
'timelineInterval']);
309 return $response->withJson($emptyTimeline, 200);
313 $data =
\Services::get(
'stats')->getTimeline($allowedParams[
'timelineInterval'], $allowedParams);
315 return $response->withJson($data, 200);
330 if (!$request->getContext()) {
331 return $response->withStatus(404)->withJsonError(
'api.404.resourceNotFound');
335 'timelineInterval' => STATISTICS_DIMENSION_MONTH,
338 $requestParams = array_merge($defaultParams, $slimRequest->getQueryParams());
345 $this->sectionIdsQueryParam,
349 \HookRegistry::call(
'API::stats::publications::galley::params', array(&$allowedParams, $slimRequest));
351 if (!in_array($allowedParams[
'timelineInterval'], [STATISTICS_DIMENSION_DAY, STATISTICS_DIMENSION_MONTH])) {
352 return $response->withStatus(400)->withJsonError(
'api.stats.400.wrongTimelineInterval');
356 if ($result !==
true) {
357 return $response->withStatus(400)->withJsonError($result);
360 $allowedParams[
'contextIds'] = $request->getContext()->getId();
361 $allowedParams[
'assocTypes'] = ASSOC_TYPE_SUBMISSION_FILE;
364 if (!empty($allowedParams[
'searchPhrase'])) {
365 $allowedSubmissionIds = empty($allowedParams[
'submissionIds']) ? [] : $allowedParams[
'submissionIds'];
366 $allowedParams[
'submissionIds'] = $this->
_processSearchPhrase($allowedParams[
'searchPhrase'], $allowedSubmissionIds);
368 if (empty($allowedParams[
'submissionIds'])) {
369 $dateStart = empty($allowedParams[
'dateStart']) ? STATISTICS_EARLIEST_DATE : $allowedParams[
'dateStart'];
370 $dateEnd = empty($allowedParams[
'dateEnd']) ? date(
'Ymd', strtotime(
'yesterday')) : $allowedParams[
'dateEnd'];
371 $emptyTimeline =
\Services::get(
'stats')->getEmptyTimelineIntervals($dateStart, $dateEnd, $allowedParams[
'timelineInterval']);
372 return $response->withJson($emptyTimeline, 200);
376 $data =
\Services::get(
'stats')->getTimeline($allowedParams[
'timelineInterval'], $allowedParams);
378 return $response->withJson($data, 200);
388 public function get($slimRequest, $response, $args) {
391 if (!$request->getContext()) {
392 return $response->withStatus(404)->withJsonError(
'api.404.resourceNotFound');
402 \HookRegistry::call(
'API::stats::publication::params', array(&$allowedParams, $slimRequest));
405 if ($result !==
true) {
406 return $response->withStatus(400)->withJsonError($result);
409 $allowedParams[
'submissionIds'] = [$submission->getId()];
410 $allowedParams[
'contextIds'] = $request->getContext()->getId();
414 $abstractRecords = $statsService->getRecords(array_merge($allowedParams, [
415 'assocTypes' => [ASSOC_TYPE_SUBMISSION],
417 $abstractViews = array_reduce($abstractRecords, [$statsService,
'sumMetric'], 0);
420 $galleyRecords = $statsService->getRecords(array_merge($allowedParams, [
421 'assocTypes' => [ASSOC_TYPE_SUBMISSION_FILE],
423 $galleyViews = array_reduce($galleyRecords, [$statsService,
'sumMetric'], 0);
424 $pdfViews = array_reduce(array_filter($galleyRecords, [$statsService,
'filterRecordPdf']), [$statsService,
'sumMetric'], 0);
425 $htmlViews = array_reduce(array_filter($galleyRecords, [$statsService,
'filterRecordHtml']), [$statsService,
'sumMetric'], 0);
426 $otherViews = array_reduce(array_filter($galleyRecords, [$statsService,
'filterRecordOther']), [$statsService,
'sumMetric'], 0);
428 $submissionProps =
Services::get(
'submission')->getProperties(
437 'request' => $request,
438 'slimRequest' => $slimRequest,
441 $submissionProps = array_merge(
444 $submission->getCurrentPublication(),
446 'authorsStringShort',
450 'request' => $request,
451 'slimRequest' => $slimRequest,
456 return $response->withJson([
457 'abstractViews' => $abstractViews,
458 'galleyViews' => $galleyViews,
459 'pdfViews' => $pdfViews,
460 'htmlViews' => $htmlViews,
461 'otherViews' => $otherViews,
462 'publication' => $submissionProps,
478 if (!$request->getContext()) {
479 return $response->withStatus(404)->withJsonError(
'api.404.resourceNotFound');
484 return $response->withStatus(404)->withJsonError(
'api.404.resourceNotFound');
488 'timelineInterval' => STATISTICS_DIMENSION_MONTH,
491 $requestParams = array_merge($defaultParams, $slimRequest->getQueryParams());
499 $allowedParams[
'contextIds'] = $request->getContext()->getId();
500 $allowedParams[
'submissionIds'] = $submission->getId();
501 $allowedParams[
'assocTypes'] = ASSOC_TYPE_SUBMISSION;
502 $allowedParams[
'assocIds'] = $submission->getId();
504 \HookRegistry::call(
'API::stats::publication::abstract::params', array(&$allowedParams, $slimRequest));
507 if ($result !==
true) {
508 return $response->withStatus(400)->withJsonError($result);
512 $data = $statsService->getTimeline($allowedParams[
'timelineInterval'], $allowedParams);
514 return $response->withJson($data, 200);
526 public function getGalley($slimRequest, $response, $args) {
530 if (!$request->getContext()) {
531 return $response->withStatus(404)->withJsonError(
'api.404.resourceNotFound');
536 return $response->withStatus(404)->withJsonError(
'api.404.resourceNotFound');
540 'timelineInterval' => STATISTICS_DIMENSION_MONTH,
543 $requestParams = array_merge($defaultParams, $slimRequest->getQueryParams());
551 $allowedParams[
'contextIds'] = $request->getContext()->getId();
552 $allowedParams[
'submissionIds'] = $submission->getId();
553 $allowedParams[
'assocTypes'] = ASSOC_TYPE_SUBMISSION_FILE;
555 \HookRegistry::call(
'API::stats::publication::galley::params', array(&$allowedParams, $slimRequest));
558 if ($result !==
true) {
559 return $response->withStatus(400)->withJsonError($result);
563 $data = $statsService->getTimeline($allowedParams[
'timelineInterval'], $allowedParams);
565 return $response->withJson($data, 200);
581 foreach ($requestParams as $requestParam => $value) {
582 if (!in_array($requestParam, $allowedParams)) {
585 switch ($requestParam) {
588 case 'timelineInterval':
590 $returnParams[$requestParam] = $value;
594 $returnParams[$requestParam] = min(100, (
int) $value);
598 $returnParams[$requestParam] = (int) $value;
601 case 'orderDirection':
602 $returnParams[$requestParam] = strtoupper($value);
605 case $this->sectionIdsQueryParam:
606 case 'submissionIds':
607 if (is_string($value) && strpos($value,
',') > -1) {
608 $value = explode(
',', $value);
609 } elseif (!is_array($value)) {
610 $value = array($value);
612 $returnParams[$requestParam] = array_map(
'intval', $value);
619 if (in_array(
'dateStart', $allowedParams) && !isset($returnParams[
'dateStart'])) {
621 $returnParams[
'dateStart'] = $dateRange[0];
624 return $returnParams;
639 $searchPhraseSubmissionIds =
\Services::get(
'submission')->getIds([
641 'searchPhrase' => $searchPhrase,
642 'status' => STATUS_PUBLISHED,
645 if (!empty($submissionIds)) {
646 $submissionIds = array_intersect($submissionIds, $searchPhraseSubmissionIds);
648 $submissionIds = $searchPhraseSubmissionIds;
651 return $submissionIds;