ldc-qrcollector-back/app/Http/Controllers/Bo/StatsController.php
Vincent BRIDIER 518c18331c
CSP Fix
2023-10-06 14:30:31 +02:00

336 lines
11 KiB
PHP

<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\StatsRequest;
use App\Lib\Helpers\ChartJsHelper;
use App\Models\Brand;
use App\Models\Url;
use App\Models\UrlStats;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Colors\RandomColor;
class StatsController extends Controller
{
/** @var array Colors used in charts */
private $colors = [];
/**
* Stats Page
*
* @param \App\Http\Requests\Bo\StatsRequest $request
* @return \Illuminate\Contracts\View\View
*/
public function index(StatsRequest $request)
{
$brandModels = Brand::all();
$chart = null;
$start = $request->start ? Carbon::parse($request->start) : null;
$end = $request->end ? Carbon::parse($request->end) : null;
$period = $request->period;
if ($request->post()) {
$periodInterval = CarbonPeriod::create($start, $end);
$chart = $this->getChart($request);
} //end if
return view('bo.pages.stats', compact('brandModels', 'chart', 'start', 'end'));
}
/**
* Get a chart from ChartJs.
*
* @param \Illuminate\Http\Request $request
* @return object
*/
private function getChart(Request $request)
{
$period = $request->period;
$periodInterval = $this->getDateInterval($request->start, $request->end, $request->period);
foreach ($periodInterval as $date) {
$labels[] = $this->getChartLabels($date, $request->period);
}
if (!$request->brand) {
$datasets = $this->getGlobalDatas($periodInterval, Brand::all(), $period);
} elseif (!$request->url) {
$datasets = $this->getBrandDatas($periodInterval, Brand::find($request->brand), $period);
} else {
$datasets = $this->getUrlDatas($periodInterval, Url::find($request->url), $period);
}
if (count(Arr::first($datasets)['data']) > 1) {
$type = 'line';
} else {
$type = 'bar';
}
$chartjs = new ChartJsHelper();
return $chartjs
->name('stats')
->type($type)
->labels($labels)
->datasets($datasets)
->optionsRaw($options ?? "{}");
}
/**
* Get datas for all brands.
*
* @param \Carbon\CarbonPeriod $periodInterval
* @param \Illuminate\Database\Eloquent\Collection $brandModels
* @param string $period
* @return array
*/
private function getGlobalDatas(
CarbonPeriod $periodInterval,
\Illuminate\Database\Eloquent\Collection $brandModels,
string $period = "day"
) {
foreach ($brandModels as $brand) {
foreach ($periodInterval as $date) {
switch ($period) {
case 'day':
$dailyStats = UrlStats::where('date', $date)
->whereIn('url_id', $brand->urls->pluck('id'))
->get();
break;
case 'week':
$dailyStats = UrlStats::whereIn(
'date',
CarbonPeriod::create(
$date->startOfWeek()->format('Y-m-d'),
$date->endOfWeek()->format('Y-m-d')
)->toArray()
)->whereIn('url_id', $brand->urls->pluck('id'))
->get();
break;
case 'month':
$dailyStats = UrlStats::whereIn(
'date',
CarbonPeriod::create(
$date->startOfMonth()->format('Y-m-d'),
$date->endOfMonth()->format('Y-m-d')
)->toArray()
)->whereIn('url_id', $brand->urls->pluck('id'))
->get();
break;
} //end switch
$data[$brand->id][] = $dailyStats->sum('calls');
} //end foreach
$color = $this->getUniqueColor();
$datasets[] = [
'label' => $brand->name,
'backgroundColor' => $color,
'borderColor' => $color,
"pointBorderColor" => $color,
"pointBackgroundColor" => $color,
'data' => $data[$brand->id],
'lineTension' => 0.4,
];
} //end foreach
return $datasets;
}
/**
* Get a chart for all urls of a given brand.
*
* @param \Carbon\CarbonPeriod $periodInterval
* @param \App\Models\Brand $brand
* @param string $period
* @return object
*/
private function getBrandDatas(
CarbonPeriod $periodInterval,
\App\Models\Brand $brand,
string $period = "day"
) {
foreach ($brand->urls as $url) {
foreach ($periodInterval as $date) {
switch ($period) {
case 'day':
$dailyStats = UrlStats::where('date', $date)
->where('url_id', $url->id)
->get();
break;
case 'week':
$dailyStats = UrlStats::whereIn(
'date',
CarbonPeriod::create(
$date->startOfWeek()->format('Y-m-d'),
$date->endOfWeek()->format('Y-m-d')
)->toArray()
)->where('url_id', $url->id)
->get();
break;
case 'month':
$dailyStats = UrlStats::whereIn(
'date',
CarbonPeriod::create(
$date->startOfMonth()->format('Y-m-d'),
$date->endOfMonth()->format('Y-m-d')
)->toArray()
)->where('url_id', $url->id)
->get();
break;
} //end switch
$data[$url->id][] = $dailyStats->sum('calls');
} //end foreach
$color = $this->getUniqueColor();
$datasets[] = [
'label' => $url->value,
'backgroundColor' => $color,
'borderColor' => $color,
"pointBorderColor" => $color,
"pointBackgroundColor" => $color,
'data' => $data[$url->id],
'lineTension' => 0.4,
];
} //end foreach
return $datasets;
}
/**
* Get a chart for a given url.
*
* @param \Carbon\CarbonPeriod $periodInterval
* @param \App\Models\Url $url
* @param string $period
* @return object
*/
private function getUrlDatas(
CarbonPeriod $periodInterval,
\App\Models\Url $url,
string $period = 'day'
) {
foreach ($periodInterval as $date) {
switch ($period) {
case 'day':
$dailyStats = UrlStats::where('date', $date)
->where('url_id', $url->id)
->get();
break;
case 'week':
$dailyStats = UrlStats::whereIn(
'date',
CarbonPeriod::create(
$date->startOfWeek()->format('Y-m-d'),
$date->endOfWeek()->format('Y-m-d')
)->toArray()
)->where('url_id', $url->id)
->get();
break;
case 'month':
$dailyStats = UrlStats::whereIn(
'date',
CarbonPeriod::create(
$date->startOfMonth()->format('Y-m-d'),
$date->endOfMonth()->format('Y-m-d')
)->toArray()
)->where('url_id', $url->id)
->get();
break;
} //end switch
$data[$url->id][] = $dailyStats->sum('calls');
} //end foreach
$color = $this->getUniqueColor();
$datasets[] = [
'label' => $url->value,
'backgroundColor' => $color,
'borderColor' => $color,
"pointBorderColor" => $color,
"pointBackgroundColor" => $color,
'data' => $data[$url->id],
'lineTension' => 0.4,
];
return $datasets;
}
/**
* Get the CarbonPeriod for the given period.
*
* @param string $start
* @param string $end
* @param string $period Can be day|week|month.
* @return \Carbon\CarbonPeriod
*/
private function getDateInterval(string $start, string $end, string $period)
{
switch ($period) {
case 'day':
$periodInterval = CarbonPeriod::create($start, $end);
break;
case 'week':
$periodInterval = CarbonPeriod::create(
Carbon::parse($start)->startOfWeek(),
Carbon::parse($end)->endOfWeek(),
'1 week'
);
break;
case 'month':
$periodInterval = CarbonPeriod::create(
Carbon::parse($start)->startOfMonth(),
Carbon::parse($end)->endOfMonth(),
'1 month'
);
break;
default:
$periodInterval = CarbonPeriod::create($start, $end);
} //end switch
return $periodInterval;
}
/**
* Get labels for charts.
*
* @param Carbon\Carbon $date
* @param string $period Can be day|week|month.
* @return string
*/
private function getChartLabels(Carbon $date, string $period)
{
$labels = [];
if ($period === "day") {
$labels = array_merge($labels, [$date->format('d-m-Y')]);
}
if ($period === "week") {
$labels = array_unique(array_merge($labels, [sprintf(
'Du %s au %s',
$date->startOfWeek()->format('Y-m-d'),
$date->endOfWeek()->format('Y-m-d')
)]));
}
if ($period === "month") {
$labels = array_unique(array_merge($labels, [Str::ucfirst($date->monthName)]));
}
return $labels;
}
/**
* getUniqueColor
*
* @return string
*/
private function getUniqueColor()
{
$color = RandomColor::one();
if (in_array($color, $this->colors)) {
return $this->getUniqueColor();
}
$this->colors[] = $color;
return $color;
}
}