ldc-gen-game-web/app/Http/Controllers/Controller.php

257 lines
9.3 KiB
PHP
Raw Normal View History

2020-10-21 15:26:21 +02:00
<?php
2026-10-02 12:09:46 +02:00
declare(strict_types=1);
2020-10-21 15:26:21 +02:00
namespace App\Http\Controllers;
2023-11-23 17:31:28 +01:00
use App\Enums\Pagination\ItemsPerPaginationEnum;
use App\Enums\Theme\BootstrapThemeEnum;
2026-10-02 12:09:46 +02:00
use App\Lib\Discount;
2023-11-23 17:31:28 +01:00
use App\Lib\Helpers\ToolboxHelper;
2026-10-02 12:09:46 +02:00
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
2023-08-21 10:22:07 +02:00
use Illuminate\Database\Eloquent\Builder;
2020-10-21 15:26:21 +02:00
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
2026-10-02 12:09:46 +02:00
use Illuminate\Http\RedirectResponse;
2023-11-23 17:31:28 +01:00
use Illuminate\Http\Request;
2020-10-21 15:26:21 +02:00
use Illuminate\Routing\Controller as BaseController;
2023-08-21 10:15:14 +00:00
use Illuminate\Support\Facades\Cache;
2023-08-21 10:22:07 +02:00
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Session;
2023-11-23 17:31:28 +01:00
use Illuminate\Support\Str;
2020-10-21 15:26:21 +02:00
class Controller extends BaseController
{
2021-08-18 17:08:02 +02:00
use AuthorizesRequests;
use ValidatesRequests;
2023-08-21 10:22:07 +02:00
/**
* Utility function for getting random values with weighting.
* Pass in an associative array, such as array('A'=>5, 'B'=>45, 'C'=>50)
* An array like this means that "A" has a 5% chance of being selected, "B" 45%, and "C" 50%.
* The return value is the array key, A, B, or C in this case. Note that the values assigned
* do not have to be percentages. The values are simply relative to each other. If one value
* weight was 2, and the other weight of 1, the value with the weight of 2 has about a 66%
* chance of being selected. Also note that weights should be integers.
*
2026-10-02 12:09:46 +02:00
* @param array<Discount> $weightedValues
* @return int The winning key
*
* @url https://stackoverflow.com/a/11872928/4355295
*/
protected function getRandomWeightedElementIndex(array $weightedValues): int
{
mt_srand(time());
$rand = mt_rand(1, max((int) collect($weightedValues)->sum('percentage'), 1));
foreach ($weightedValues as $key => $value) {
$rand -= $value->percentage;
if ($rand <= 0) {
return $key;
}
}
2026-10-02 12:09:46 +02:00
2024-01-31 09:03:18 +00:00
return $rand;
}
/**
* Gives the redirection path for FO Auth controllers
*/
protected function authLoggedRedirectPath(): string
{
return response()->redirectToRoute('fo.homepage')->getTargetUrl();
}
2023-08-21 10:22:07 +02:00
/**
* Build Search query on specified fields
* splitting search into words or using whole sentence
*
2026-10-02 12:09:46 +02:00
* @param Builder $query The eloquent query builder.
* @param string $search The query string.
* @param callable $searchQuery The query string.
* @param string ...$fields Either a simple array or a string
* in case of a string the two fields
* would be concatenate to make the search.
2023-08-21 10:22:07 +02:00
*/
protected function searchQuery(
Builder $query,
string $search,
2026-10-02 12:09:46 +02:00
?callable $searchQuery = null,
2023-08-21 10:22:07 +02:00
string ...$fields
2026-10-02 12:09:46 +02:00
): Builder {
2023-08-21 10:22:07 +02:00
if (count($fields)) {
// Search using words.
$words = explode(' ', $search);
2026-10-02 12:09:46 +02:00
$query->where(function (\Illuminate\Contracts\Database\Query\Builder $query) use ($searchQuery, $words, $search, $fields): void {
2023-08-21 10:22:07 +02:00
foreach ($words as $word) {
2026-10-02 12:09:46 +02:00
if (! strlen($word)) {
2023-08-21 10:22:07 +02:00
continue;
}
$this->searchOnFields($query, $word, $fields);
2026-10-02 12:09:46 +02:00
} // end foreach
2023-08-21 10:22:07 +02:00
// Search whole using whole sentence.
$this->searchOnFields($query, $search, $fields);
if ($searchQuery) {
$searchQuery($query);
}
});
2026-10-02 12:09:46 +02:00
} // end if
2023-08-21 10:22:07 +02:00
return $query;
}
/**
* Build query search on all fields
*/
2023-11-23 17:31:28 +01:00
private function searchOnFields(
Builder $query,
string $search,
array $fields
2026-10-02 12:09:46 +02:00
): Builder {
2023-08-21 10:22:07 +02:00
$table = $query->getModel()->getTable();
2023-11-23 17:31:28 +01:00
foreach ($fields as $field) {
$field = str_replace('?', '\?', $field);
if (is_array($field)) {
2023-08-21 10:22:07 +02:00
$query->orWhereRaw(
2026-10-02 12:09:46 +02:00
sprintf('UPPER(CONCAT(%s)) LIKE UPPER(?)', collect($field)->map(fn ($q): string => "`$table`.`$q`")->implode(', \' \', ')),
2023-11-23 17:31:28 +01:00
['%' . htmlspecialchars($search) . '%']
2023-08-21 10:22:07 +02:00
);
2026-10-02 12:09:46 +02:00
2023-11-23 17:31:28 +01:00
return $query;
2023-08-21 10:22:07 +02:00
}
2023-11-23 17:31:28 +01:00
// Get models woth enum's label.
if (is_array($this->getSearchValue($query, $search, $field))) {
foreach ($this->getSearchValue($query, $search, $field) as $array) {
$query->orWhereRaw(
"UPPER(`$table`.`$field`) LIKE UPPER(?)",
['%' . htmlspecialchars($array->value) . '%']
);
}
2026-10-02 12:09:46 +02:00
2023-11-23 17:31:28 +01:00
return $query;
}
// Get models with relation's name/label.
2024-01-31 09:03:18 +00:00
if (Str::endsWith($field, '_id')) {
2026-10-02 12:09:46 +02:00
$query->orWhereHas(
Str::remove('_id', $field),
function (\Illuminate\Contracts\Database\Query\Builder $queryRelation) use ($field, $search): void {
if (Schema::hasColumn(Str::remove('_id', $field) . 's', 'name')) {
$queryRelation->where('name', 'like', '%' . $search . '%');
} elseif (Schema::hasColumn(Str::remove('_id', $field) . 's', 'label')) {
$queryRelation->where('label', 'like', '%' . $search . '%');
}
2023-11-23 17:31:28 +01:00
}
2026-10-02 12:09:46 +02:00
);
2023-11-23 17:31:28 +01:00
return $query;
}
$query->orWhereRaw(
"UPPER(`$table`.`$field`) LIKE UPPER(?)",
['%' . htmlspecialchars($this->getSearchValue($query, $search, $field)) . '%']
);
2026-10-02 12:09:46 +02:00
} // end foreach
2023-08-21 10:22:07 +02:00
return $query;
}
/**
2023-11-23 17:31:28 +01:00
* Get the search value (on string or Enum).
*/
2026-10-02 12:09:46 +02:00
protected function getSearchValue(Builder $query, string $search, string $field): string | array
2023-11-23 17:31:28 +01:00
{
2024-01-31 09:03:18 +00:00
$cast = $query->getModel()->getCasts()[$field] ?? null;
2023-11-23 17:31:28 +01:00
if (
2026-10-02 12:09:46 +02:00
count($query->getModel()->getCasts()) && $cast && enum_exists($cast) // Check if the cast is an enum.
2023-11-23 17:31:28 +01:00
) {
2024-01-31 09:03:18 +00:00
// @phpstan-ignore-next-line
$cases = collect($cast::toArray());
2026-10-02 12:09:46 +02:00
$enum = $cases->filter(fn ($item): int | false => preg_match('/' . Str::lower($search) . '/', Str::lower($item->label)));
2023-11-23 17:31:28 +01:00
return $enum->toArray();
}
2026-10-02 12:09:46 +02:00
return $search;
2023-11-23 17:31:28 +01:00
}
/**
* Sort columns with a query.
2023-08-21 10:22:07 +02:00
*/
2026-10-02 12:09:46 +02:00
protected function sortQuery(Builder $query, array $ignore = []): Builder
2023-08-21 10:22:07 +02:00
{
$rName = request()->route()->getName();
$table = $query->getModel()->getTable();
if (request()->sort_col) {
Session::put("$rName.sort_col", request()->sort_col);
Session::put("$rName.sorted", true);
}
if (request()->sort_way) {
Session::put("$rName.sort_way", request()->sort_way);
Session::put("$rName.sorted", true);
}
if (request()->rst) {
Session::remove("$rName.sorted");
Session::remove("$rName.sort_col");
Session::remove("$rName.sort_way");
}
2026-10-02 12:09:46 +02:00
if (request()->sort_col && request()->sort_way && Schema::hasColumn($table, request()->sort_col)) {
if (! in_array(request()->sort_col, $ignore)) {
2023-08-21 10:22:07 +02:00
$query = $query->orderBy(\sprintf("$table.%s", request()->sort_col), request()->sort_way);
}
} elseif (Schema::hasColumn($table, 'order')) {
$query = $query->orderBy('order', 'ASC');
Session::put("$rName.sort_col", 'order');
Session::put("$rName.sort_way", 'asc');
2023-11-23 17:31:28 +01:00
} elseif (Schema::hasColumn($table, 'updated_at')) {
2026-10-02 12:09:46 +02:00
$query = $query->latest('updated_at');
2023-11-23 17:31:28 +01:00
Session::put("$rName.sort_col", 'updated_at');
Session::put("$rName.sort_way", 'desc');
} elseif (Schema::hasColumn($table, 'created_at')) {
2026-10-02 12:09:46 +02:00
$query = $query->latest();
2023-11-23 17:31:28 +01:00
Session::put("$rName.sort_col", 'created_at');
Session::put("$rName.sort_way", 'desc');
2023-08-21 10:22:07 +02:00
}
2026-10-02 12:09:46 +02:00
2023-08-21 10:22:07 +02:00
return $query;
}
2023-08-21 10:15:14 +00:00
/**
* Customize pagination with cache or config (default).
*/
2023-11-23 17:31:28 +01:00
protected function paginate(
Builder $query,
2026-10-02 12:09:46 +02:00
?ItemsPerPaginationEnum $pagination = null
): LengthAwarePaginator {
2023-11-23 17:31:28 +01:00
$currentRoutePath = Str::slug(request()->route()->getName());
$cacheKey = "pagination.{$currentRoutePath}";
2026-10-02 12:09:46 +02:00
$pagination ??= ItemsPerPaginationEnum::twelve;
2023-11-23 17:31:28 +01:00
$pagination = ToolboxHelper::getValidatedEnum(
Cache::get($cacheKey, $pagination->value()),
'pagination',
2026-10-02 12:09:46 +02:00
ItemsPerPaginationEnum::class,
2023-08-21 10:15:14 +00:00
);
2023-11-23 17:31:28 +01:00
if (Cache::get($cacheKey) !== $pagination) {
Cache::put($cacheKey, $pagination);
}
$query = $query->paginate($pagination);
2026-10-02 12:09:46 +02:00
2023-08-21 10:15:14 +00:00
return $query;
}
2023-11-23 17:31:28 +01:00
/**
* Set the bootstrap theme or light (default).
*/
2026-10-02 12:09:46 +02:00
protected function setTheme(Request $request): RedirectResponse
2023-11-23 17:31:28 +01:00
{
$theme = ToolboxHelper::getValidatedEnum(
$request->theme ?: Cache::get('theme', BootstrapThemeEnum::light->value()),
'theme',
'\App\Http\Controllers\BootstrapThemeEnum',
);
2026-10-02 12:09:46 +02:00
if (Cache::get('theme') !== $theme) {
Cache::put('theme', $theme);
2023-11-23 17:31:28 +01:00
}
2026-10-02 12:09:46 +02:00
return back()->with('success', __('crud.messages.theme_updated'));
2023-11-23 17:31:28 +01:00
}
2020-10-21 15:26:21 +02:00
}