芝麻web文件管理V1.00
编辑当前文件:/home/forge/stage.sksb.smartcon-survey.com/app/Helpers/Analytics.php
validateFilters(); $this->setQuestions($questions); $this->interviewsQuery = Interview::whereRaw($this->getSqlFilter()); } /** * Get the results of the analytics query. */ final public function get(): mixed { return $this->results; } /** * Validates the filters array for required fields. * * @throws RuntimeException - If topic_id is not present in the filters array. */ private function validateFilters(): void { if (! array_key_exists('topic_id', $this->filters)) { throw new RuntimeException('Topic id is required in filters array'); } } /** * Set filters for the analytics data. * * @param array $filters - An array of filters to apply to the analytics data. * @return Analytics - The updated Analytics object with the filters applied. */ public function setFilters(array $filters): Analytics { $this->filters = array_merge($this->filters, $filters); $this->validateFilters(); $this->interviewsQuery = Interview::whereRaw($this->getSqlFilter()); return $this; } /** * Filter the analytics data by the last quarter. * * @return Analytics - The updated Analytics object with the last quarter filter applied. */ public function lastQuarter(): Analytics { $this->interviewsQuery->byQuarter(Carbon::now()->quarter, Carbon::now()->year); return $this; } /** * Filter the analytics data starting from the specified date. * * @param Carbon $fromDate - The starting date to filter the analytics data from. * @return Analytics - The updated Analytics object with the starting date filter applied. */ public function from(Carbon $fromDate): Analytics { $this->interviewsQuery->where('created_at', '>=', $fromDate); return $this; } /** * Filter the analytics data up to a specific date. * * @param Carbon $toDate - The date to filter the analytics data. * @return Analytics - The updated Analytics object with the date filter applied. */ public function to(Carbon $toDate): Analytics { $this->interviewsQuery->where('created_at', '<=', $toDate); return $this; } /** * Filter the analytics data by date range. * * @param Carbon $fromDate - The starting date of the range. * @param Carbon $toDate - The ending date of the range. * @return Analytics - The updated Analytics object with the date range filter applied. */ public function dateRange(Carbon $fromDate, Carbon $toDate): Analytics { $this->interviewsQuery->whereBetween('created_at', [$fromDate, $toDate]); return $this; } /** * Filter the analytics data by quarter. * * @return Analytics - The updated Analytics object with the quarter filter applied. */ public function byQuarter(): Analytics { $this->interviewsQuery->byQuarter(Carbon::now()->quarter, Carbon::now()->year); return $this; } /** * Calculate the Top 2 value for the given questions. * * @return float The Top 2 score as a percentage */ public function top2(): float { $total = $this->interviewsQuery->count(); $top2 = 0; foreach ($this->questions as $question) { $top2 += $this->interviewsQuery->whereQuestion($question['name'], range(1, 2))->count(); } if ($total === 0) { return 0; } return round($top2 / $total * 100, 2); } /** * Count the number of interviews based on the defined filters. * * @return int The count of interviews */ public function count(): int { return $this->interviewsQuery->count(); } /** * Get the pie chart data for the analytics. * * @return Analytics - The updated Analytics object with the pie chart data. */ public function calculatePieChartData(): Analytics { $results = $this->getQuestionResults(); $results = $this->fillMissingValues($results); ksort($results); $this->results = $results; return $this; } /** * Calculate the average of the analytics data. * * @return Analytics - The updated Analytics object with the average calculated. */ public function average(): Analytics { $set = collect([]); foreach ($this->results as $value => $amount) { foreach (range(1, $amount) as $test) { $set->add($value); } } $this->results = round($set->average(), 1); return $this; } /** * Get the results for each question. * * @return array - An array containing the results for each question. */ private function getQuestionResults(): array { $results = []; foreach ($this->questions as $question) { $interviews = $this->interviewsQuery->questionResults($question['name'])->get(); $results = $this->sumAnswers($interviews, $results); } return $results; } /** * Sum the answers from a collection of interviews and store the results in an array. * * @param Collection|EloquentCollection $interviews - The collection of interviews to sum the answers from. * @param array $results - The array to store the summed answers. * @return array - The array of summed answers. */ private function sumAnswers(Collection|EloquentCollection $interviews, array $results): array { foreach ($interviews as $res) { if (isset($results[$res->answer])) { $results[$res->answer] += $res->count; } else { $results[$res->answer] = $res->count; } } return $results; } /** * Fill missing values in the given array. * * @param array $results - The array to fill missing values in. * @return array - The updated array with missing values filled. */ private function fillMissingValues(array $results): array { foreach (range(1, 5) as $id) { if (! isset($results[$id])) { $results[$id] = 0; } } return $results; } /** * Get the SQL filter for the filters defined in the class. * * @return string The SQL filter */ private function getSqlFilter(): string { if (empty($this->filters)) { return ''; } $sql = ''; foreach ($this->filters as $key => $value) { $value = $this->prepareFilterValue($value); if (empty($value)) { continue; } $sql .= $key === 'quarters' ? $this->handleQuarterFilter($value) : $this->handleDefaultFilter($key, $value); } return rtrim($sql, ' AND'); } /** * Prepare filter value. * * @param array $value The array value to be filtered and prepared. * @return array The filtered and prepared array value. */ private function prepareFilterValue(array|int|string $value): array { if (! is_array($value)) { return [$value]; } return array_map(static fn ($item) => "'$item'", array_filter($value)); } /** * Handles the quarter filter for the SQL query. * * @param array $value An array containing the quarters and years to filter by. * The format of each element in the array should be "quarter-year" (e.g., "2-2022"). * @return string The SQL condition string for the quarter filter. */ private function handleQuarterFilter(array $value): string { $sql = ' ( '; foreach ($value as $quarters) { [$quarter, $year] = explode('-', str_replace("'", '', $quarters)); $sql .= "( QUARTER(created_at) = $quarter AND YEAR(created_at) = $year ) OR "; } return rtrim($sql, ' OR').' ) AND '; } /** * Handles the default filter by creating a SQL condition string for the given key and value. * * @param string $key The key for the filter. * @param array $value The value for the filter. * @return string The generated SQL condition string. */ private function handleDefaultFilter(string $key, array $value): string { return "`$key` IN (".implode(',', $value).')'.' AND '; } /** * Sets the questions for the survey. * * @param array|null $questions An array containing the names of the questions to be set. If null is provided, all questions will be set. */ public function setQuestions(?array $questions): void { $sh = new SurveyJSHelper(Topic::findOrFail($this->filters['topic_id'])); $this->questions = $sh->getQuestions(); if ($questions !== null) { $this->questions = array_filter( $this->questions, static fn ($q) => in_array($q['name'], $questions, true) ); } } public static function addLog(string $log_name, int $topicId, string $currentTab, string $url = ''): void { activity($log_name) ->causedBy(Auth::user()) ->tap(function (Activity $activity) use ($topicId, $currentTab, $url) { $activity->url = $url; $activity->topic_id = $topicId; $activity->tab = $currentTab; }) ->log($log_name); } }