yearsOfPublication = $yearsOfPublication; return $this; } /** * Set the submissions to get records for */ public function filterBySubmissions(array $submissionIds): self { $this->submissionIds = $submissionIds; return $this; } /** * Set the institution to get records for */ public function filterByInstitution(int $institutionId): self { $this->institutionId = $institutionId; return $this; } /** * @copydoc PKPStatsQueryBuilder::getSum() */ public function getSum(array $groupBy = []): Builder { $selectColumns = $groupBy; $q = $this->_getObject(); // consider YOP if (in_array('YOP', $selectColumns)) { // left join the table publications, if the filter is not set i.e. the left join is not considered yet in _getObject() if (empty($this->yearsOfPublication)) { $q->leftJoin('publications as p', function ($q) { $q->on('p.submission_id', '=', 'm.submission_id') ->whereIn('p.publication_id', function ($q) { $q->selectRaw('MIN(p2.publication_id)') ->from('publications as p2') ->where('p2.status', Submission::STATUS_PUBLISHED) ->where('p2.submission_id', '=', DB::raw('m.submission_id')); }); }); } foreach ($selectColumns as $i => $selectColumn) { if ($selectColumn == 'YOP') { if (substr(Config::getVar('database', 'driver'), 0, strlen('postgres')) === 'postgres') { $selectColumns[$i] = DB::raw('EXTRACT(YEAR FROM p.date_published) as "YOP"'); } else { $selectColumns[$i] = DB::raw('YEAR(STR_TO_DATE(p.date_published, "%Y-%m-%d")) as YOP'); } break; } } } // Build the select and group by clauses. if (!empty($selectColumns)) { $q->select($selectColumns); if (!empty($groupBy)) { $q->groupBy($groupBy); } } $counterMetricsColumns = StatisticsHelper::getCounterMetricsColumns(); foreach ($counterMetricsColumns as $counterMetricsColumn) { $q->addSelect(DB::raw("SUM({$counterMetricsColumn}) AS {$counterMetricsColumn}")); } return $q; } /** * @copydoc PKPStatsQueryBuilder::_getObject() */ protected function _getObject(): Builder { if ($this->institutionId === 0) { $q = DB::table('metrics_counter_submission_monthly as m'); } else { $q = DB::table('metrics_counter_submission_institution_monthly as m'); } if (!empty($this->yearsOfPublication)) { $q->leftJoin('publications as p', function ($q) { $q->on('p.submission_id', '=', 'm.submission_id') ->whereIn('p.publication_id', function ($q) { $q->selectRaw('MIN(p2.publication_id)') ->from('publications as p2') ->where('p2.status', Submission::STATUS_PUBLISHED) ->where('p2.submission_id', '=', DB::raw('m.submission_id')); }); }); foreach ($this->yearsOfPublication as $yop) { if (preg_match('/\d{4}/', $yop)) { if (substr(Config::getVar('database', 'driver'), 0, strlen('postgres')) === 'postgres') { $q->where(DB::raw('EXTRACT(YEAR FROM p.date_published)'), '=', $yop); } else { $q->where(DB::raw('YEAR(STR_TO_DATE(p.date_published, "%Y-%m-%d"))'), '=', $yop); } } elseif (preg_match('/\d{4}-\d{4}/', $yop)) { $years = explode('-', $yop); if (substr(Config::getVar('database', 'driver'), 0, strlen('postgres')) === 'postgres') { $q->whereBetween(DB::raw('EXTRACT(YEAR FROM p.date_published)'), $years); } else { $q->whereBetween(DB::raw('YEAR(STR_TO_DATE(p.date_published, "%Y-%m-%d"))'), $years); } } } } if (!empty($this->contextIds)) { $q->whereIn('m.' . StatisticsHelper::STATISTICS_DIMENSION_CONTEXT_ID, $this->contextIds); } if (!empty($this->submissionIds)) { $q->whereIn('m.' . StatisticsHelper::STATISTICS_DIMENSION_SUBMISSION_ID, $this->submissionIds); } $q->whereBetween('m.' . StatisticsHelper::STATISTICS_DIMENSION_MONTH, [date_format(date_create($this->dateStart), 'Ym'), date_format(date_create($this->dateEnd), 'Ym')]); Hook::call('StatsSushi::queryObject', [&$q, $this]); return $q; } /** * Do usage stats data already exist for the given month * Consider only the table metrics_counter_submission_monthly, because * it always contains data, while metrics_counter_submission_institution_monthly * could not contain data. * * @param string $month Month in the form YYYYMM */ public function monthExists(string $month): bool { return DB::table('metrics_counter_submission_monthly as m') ->where(StatisticsHelper::STATISTICS_DIMENSION_MONTH, $month)->exists(); } /** * Delete daily usage stats for a month * * @param string $month Month in the form YYYYMM */ public function deleteDailyMetrics(string $month): void { // Construct the SQL part depending on the DB $monthFormatSql = "DATE_FORMAT(date, '%Y%m')"; if (substr(Config::getVar('database', 'driver'), 0, strlen('postgres')) === 'postgres') { $monthFormatSql = "to_char(date, 'YYYYMM')"; } DB::table('metrics_counter_submission_daily')->where(DB::raw($monthFormatSql), '=', $month)->delete(); DB::table('metrics_counter_submission_institution_daily')->where(DB::raw($monthFormatSql), '=', $month)->delete(); } /** * Delete monthly usage metrics for a month * * @param string $month Month in the form YYYYMM */ public function deleteMonthlyMetrics(string $month): void { DB::table('metrics_counter_submission_monthly')->where('month', $month)->delete(); DB::table('metrics_counter_submission_institution_monthly')->where('month', $month)->delete(); } /** * Aggregate daily usage metrics by a month * * @param string $month Month in the form YYYYMM */ public function addMonthlyMetrics(string $month): void { // Construct the SQL part depending on the DB $monthFormatSql = "CAST(DATE_FORMAT(csd.date, '%Y%m') AS UNSIGNED)"; if (substr(Config::getVar('database', 'driver'), 0, strlen('postgres')) === 'postgres') { $monthFormatSql = "to_char(csd.date, 'YYYYMM')::integer"; } // Get the application specific metrics columns $counterMetricsColumns = StatisticsHelper::getCounterMetricsColumns(); // SQL part for the select sub-statement creates the SUM for each metrics column, and then connects them with ',' $selectSql = implode(', ', array_map(fn ($value): string => 'SUM(csd.' . $value . ')', $counterMetricsColumns)); $selectSubmissionDaily = DB::table('metrics_counter_submission_daily as csd') ->select(DB::raw("csd.context_id, csd.submission_id, {$monthFormatSql} as csdmonth, {$selectSql}")) ->whereRaw("{$monthFormatSql} = ?", [$month]) ->groupBy(DB::raw('csd.context_id, csd.submission_id, csdmonth')); DB::table('metrics_counter_submission_monthly')->insertUsing(array_merge(['context_id', 'submission_id', 'month'], $counterMetricsColumns), $selectSubmissionDaily); $selectSubmissionInstitutionDaily = DB::table('metrics_counter_submission_institution_daily as csd') ->select(DB::raw("csd.context_id, csd.submission_id, csd.institution_id, {$monthFormatSql} as csdmonth, {$selectSql}")) ->whereRaw("{$monthFormatSql} = ?", [$month]) ->groupBy(DB::raw('csd.context_id, csd.submission_id, csd.institution_id, csdmonth')); DB::table('metrics_counter_submission_institution_monthly')->insertUsing(array_merge(['context_id', 'submission_id', 'institution_id', 'month'], $counterMetricsColumns), $selectSubmissionInstitutionDaily); } }