333 lines
11 KiB
PHP
333 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Bo;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Bo\StatsRequest;
|
|
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';
|
|
}
|
|
return app()->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;
|
|
}
|
|
}
|