feat: added logs to hunts controller
This commit is contained in:
parent
011f426f96
commit
3b4c887d3d
|
|
@ -14,13 +14,35 @@ class HuntsController extends Controller
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
Log::info('HUNTS_INDEX_START', [
|
||||||
|
'full_request' => $request->all(),
|
||||||
|
'url' => $request->fullUrl(),
|
||||||
|
'method' => $request->method(),
|
||||||
|
]);
|
||||||
|
|
||||||
$searchTerm = $this->resolveSearchTerm($request);
|
$searchTerm = $this->resolveSearchTerm($request);
|
||||||
|
Log::info('HUNTS_SEARCH_TERM_RESOLVED', [
|
||||||
|
'search_term' => $searchTerm,
|
||||||
|
]);
|
||||||
|
|
||||||
$filters = $this->buildMeilisearchFilters($request);
|
$filters = $this->buildMeilisearchFilters($request);
|
||||||
|
Log::info('HUNTS_FILTERS_BUILT', [
|
||||||
|
'filters' => $filters,
|
||||||
|
'filters_length' => strlen($filters),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Log::info('HUNTS_CREATING_SEARCH_QUERY', [
|
||||||
|
'search_term' => $searchTerm ?? '',
|
||||||
|
'filters' => $filters,
|
||||||
|
]);
|
||||||
|
|
||||||
$search = Hunts::search($searchTerm ?? '')
|
$search = Hunts::search($searchTerm ?? '')
|
||||||
->query(fn ($query) => $query->with('participants:id,avatar_uri'))
|
->query(fn ($query) => $query->with('participants:id,avatar_uri'))
|
||||||
->options(['filter' => $filters]);
|
->options(['filter' => $filters]);
|
||||||
|
|
||||||
|
Log::info('HUNTS_SEARCH_QUERY_CREATED', [
|
||||||
|
'search_class' => get_class($search),
|
||||||
|
]);
|
||||||
|
|
||||||
Log::info('HUNTS_SEARCH', [
|
Log::info('HUNTS_SEARCH', [
|
||||||
'q' => $searchTerm ?? '',
|
'q' => $searchTerm ?? '',
|
||||||
|
|
@ -30,16 +52,93 @@ class HuntsController extends Controller
|
||||||
'request_params' => $request->all(),
|
'request_params' => $request->all(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Log::info('HUNTS_EXECUTING_PAGINATE');
|
||||||
$result = $search->paginate(10);
|
$result = $search->paginate(10);
|
||||||
|
|
||||||
Log::info('HUNTS_SEARCH_SUCCESS', [
|
Log::info('HUNTS_SEARCH_SUCCESS', [
|
||||||
'total' => $result->total(),
|
'total' => $result->total(),
|
||||||
'count' => count($result->items()),
|
'count' => count($result->items()),
|
||||||
|
'result_class' => get_class($result),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->json($result);
|
// Log the structure of each item
|
||||||
|
$items = $result->items();
|
||||||
|
Log::info('HUNTS_RESULT_ITEMS_COUNT', [
|
||||||
|
'items_count' => count($items),
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach ($items as $index => $item) {
|
||||||
|
try {
|
||||||
|
Log::info('HUNTS_ITEM_STRUCTURE', [
|
||||||
|
'index' => $index,
|
||||||
|
'item_class' => get_class($item),
|
||||||
|
'item_id' => $item->id ?? null,
|
||||||
|
'item_title' => $item->title ?? null,
|
||||||
|
'has_participants' => isset($item->participants),
|
||||||
|
'participants_type' => isset($item->participants) ? gettype($item->participants) : null,
|
||||||
|
'participants_class' => isset($item->participants) && is_object($item->participants) ? get_class($item->participants) : null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Try to access participants
|
||||||
|
if (isset($item->participants)) {
|
||||||
|
try {
|
||||||
|
$participantsData = $item->participants;
|
||||||
|
Log::info('HUNTS_ITEM_PARTICIPANTS_DATA', [
|
||||||
|
'index' => $index,
|
||||||
|
'item_id' => $item->id,
|
||||||
|
'participants_count' => is_countable($participantsData) ? count($participantsData) : 'not_countable',
|
||||||
|
'participants_value' => $participantsData,
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $participantsError) {
|
||||||
|
Log::error('HUNTS_ERROR_ACCESSING_PARTICIPANTS', [
|
||||||
|
'index' => $index,
|
||||||
|
'item_id' => $item->id,
|
||||||
|
'error' => $participantsError->getMessage(),
|
||||||
|
'trace' => $participantsError->getTraceAsString(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to serialize this specific item
|
||||||
|
try {
|
||||||
|
$itemJson = json_encode($item);
|
||||||
|
Log::info('HUNTS_ITEM_JSON_SUCCESS', [
|
||||||
|
'index' => $index,
|
||||||
|
'item_id' => $item->id,
|
||||||
|
'json_length' => strlen($itemJson),
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $jsonError) {
|
||||||
|
Log::error('HUNTS_ERROR_JSON_ENCODING_ITEM', [
|
||||||
|
'index' => $index,
|
||||||
|
'item_id' => $item->id ?? null,
|
||||||
|
'error' => $jsonError->getMessage(),
|
||||||
|
'trace' => $jsonError->getTraceAsString(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
} catch (\Throwable $itemError) {
|
||||||
|
Log::error('HUNTS_ERROR_PROCESSING_ITEM', [
|
||||||
|
'index' => $index,
|
||||||
|
'error' => $itemError->getMessage(),
|
||||||
|
'trace' => $itemError->getTraceAsString(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('HUNTS_CREATING_JSON_RESPONSE');
|
||||||
|
$jsonResponse = response()->json($result);
|
||||||
|
|
||||||
|
Log::info('HUNTS_JSON_RESPONSE_CREATED', [
|
||||||
|
'status' => $jsonResponse->status(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $jsonResponse;
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
Log::error('Error fetching hunts: '.$e->getMessage());
|
Log::error('HUNTS_ERROR_CAUGHT', [
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'trace' => $e->getTraceAsString(),
|
||||||
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'error' => 'Server Error',
|
'error' => 'Server Error',
|
||||||
|
|
@ -50,79 +149,166 @@ class HuntsController extends Controller
|
||||||
|
|
||||||
private function buildMeilisearchFilters(Request $request): string
|
private function buildMeilisearchFilters(Request $request): string
|
||||||
{
|
{
|
||||||
|
Log::info('BUILD_FILTERS_START', [
|
||||||
|
'has_participating' => $request->has('participating'),
|
||||||
|
'has_active' => $request->has('active'),
|
||||||
|
'has_city' => $request->filled('city'),
|
||||||
|
'has_difficulty' => $request->filled('difficulty'),
|
||||||
|
]);
|
||||||
|
|
||||||
$filters = [];
|
$filters = [];
|
||||||
|
|
||||||
// participating
|
// participating
|
||||||
if ($request->has('participating')) {
|
if ($request->has('participating')) {
|
||||||
|
Log::info('PROCESSING_PARTICIPATING_FILTER', [
|
||||||
|
'participating_raw' => $request->query('participating'),
|
||||||
|
]);
|
||||||
|
|
||||||
$participating = filter_var(
|
$participating = filter_var(
|
||||||
$request->query('participating'),
|
$request->query('participating'),
|
||||||
FILTER_VALIDATE_BOOLEAN,
|
FILTER_VALIDATE_BOOLEAN,
|
||||||
FILTER_NULL_ON_FAILURE
|
FILTER_NULL_ON_FAILURE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Log::info('PARTICIPATING_PARSED', [
|
||||||
|
'participating_value' => $participating,
|
||||||
|
'is_bool' => is_bool($participating),
|
||||||
|
]);
|
||||||
|
|
||||||
$userId = auth('sanctum')->id(); // chez toi => UUID string
|
$userId = auth('sanctum')->id(); // chez toi => UUID string
|
||||||
|
|
||||||
|
Log::info('USER_ID_RETRIEVED', [
|
||||||
|
'user_id' => $userId,
|
||||||
|
'user_id_type' => gettype($userId),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($userId) {
|
if ($userId) {
|
||||||
$escapedUserId = $this->escapeMeiliString((string) $userId);
|
$escapedUserId = $this->escapeMeiliString((string) $userId);
|
||||||
|
|
||||||
|
Log::info('USER_ID_ESCAPED', [
|
||||||
|
'escaped_user_id' => $escapedUserId,
|
||||||
|
]);
|
||||||
|
|
||||||
if ($participating === true) {
|
if ($participating === true) {
|
||||||
// ✅ UUID => string
|
// ✅ UUID => string
|
||||||
$filters[] = "participant_ids = \"{$escapedUserId}\"";
|
$filter = "participant_ids = \"{$escapedUserId}\"";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_PARTICIPATING_TRUE_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
]);
|
||||||
} elseif ($participating === false) {
|
} elseif ($participating === false) {
|
||||||
$filters[] = "participant_ids != \"{$escapedUserId}\"";
|
$filter = "participant_ids != \"{$escapedUserId}\"";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_PARTICIPATING_FALSE_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
} elseif ($participating === true) {
|
} elseif ($participating === true) {
|
||||||
$filters[] = "id < 0";
|
$filter = "id < 0";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_NO_USER_PARTICIPATING_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// active
|
// active
|
||||||
if ($request->has('active')) {
|
if ($request->has('active')) {
|
||||||
|
Log::info('PROCESSING_ACTIVE_FILTER', [
|
||||||
|
'active_raw' => $request->query('active'),
|
||||||
|
]);
|
||||||
|
|
||||||
$now = Carbon::now('UTC')->timestamp;
|
$now = Carbon::now('UTC')->timestamp;
|
||||||
$active = filter_var($request->query('active'), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
$active = filter_var($request->query('active'), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
||||||
|
|
||||||
|
Log::info('ACTIVE_PARSED', [
|
||||||
|
'active_value' => $active,
|
||||||
|
'is_bool' => is_bool($active),
|
||||||
|
'now_timestamp' => $now,
|
||||||
|
]);
|
||||||
|
|
||||||
if ($active === true) {
|
if ($active === true) {
|
||||||
// Hunt actif = démarré ET (pas terminé OU pas de date de fin)
|
// Hunt actif = démarré ET (pas terminé OU pas de date de fin)
|
||||||
$filters[] = "start_at_timestamp <= {$now}";
|
$filter1 = "start_at_timestamp <= {$now}";
|
||||||
|
$filters[] = $filter1;
|
||||||
|
Log::info('ADDED_ACTIVE_START_FILTER', [
|
||||||
|
'filter' => $filter1,
|
||||||
|
]);
|
||||||
|
|
||||||
// Meilisearch : la syntaxe est 'field EXISTS' et non 'EXISTS field'
|
// Meilisearch : la syntaxe est 'field EXISTS' et non 'EXISTS field'
|
||||||
// Un hunt est actif si end_at_timestamp n'existe pas OU >= now
|
// Un hunt est actif si end_at_timestamp n'existe pas OU >= now
|
||||||
$filters[] = "(end_at_timestamp >= {$now} OR NOT end_at_timestamp EXISTS)";
|
$filter2 = "(end_at_timestamp >= {$now} OR NOT end_at_timestamp EXISTS)";
|
||||||
|
$filters[] = $filter2;
|
||||||
|
Log::info('ADDED_ACTIVE_END_FILTER', [
|
||||||
|
'filter' => $filter2,
|
||||||
|
]);
|
||||||
} elseif ($active === false) {
|
} elseif ($active === false) {
|
||||||
// Hunt non actif = pas encore commencé OU (déjà terminé ET a une date de fin)
|
// Hunt non actif = pas encore commencé OU (déjà terminé ET a une date de fin)
|
||||||
// Si pas de end_at_timestamp, le hunt ne peut pas être terminé
|
// Si pas de end_at_timestamp, le hunt ne peut pas être terminé
|
||||||
$filters[] = "(start_at_timestamp > {$now} OR (end_at_timestamp < {$now} AND end_at_timestamp EXISTS))";
|
$filter = "(start_at_timestamp > {$now} OR (end_at_timestamp < {$now} AND end_at_timestamp EXISTS))";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_NOT_ACTIVE_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// city
|
// city
|
||||||
if ($request->filled('city')) {
|
if ($request->filled('city')) {
|
||||||
|
Log::info('PROCESSING_CITY_FILTER', [
|
||||||
|
'city_raw' => $request->query('city'),
|
||||||
|
]);
|
||||||
|
|
||||||
$city = $request->query('city');
|
$city = $request->query('city');
|
||||||
if (is_string($city)) {
|
if (is_string($city)) {
|
||||||
$city = $this->escapeMeiliString($city);
|
$city = $this->escapeMeiliString($city);
|
||||||
$filters[] = "city = \"{$city}\"";
|
$filter = "city = \"{$city}\"";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_CITY_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// difficulty
|
// difficulty
|
||||||
if ($request->filled('difficulty')) {
|
if ($request->filled('difficulty')) {
|
||||||
|
Log::info('PROCESSING_DIFFICULTY_FILTER', [
|
||||||
|
'difficulty_raw' => $request->query('difficulty'),
|
||||||
|
]);
|
||||||
|
|
||||||
$difficulties = $request->query('difficulty');
|
$difficulties = $request->query('difficulty');
|
||||||
|
|
||||||
if (is_string($difficulties)) {
|
if (is_string($difficulties)) {
|
||||||
$difficulties = explode(',', $difficulties);
|
$difficulties = explode(',', $difficulties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log::info('DIFFICULTY_PARSED', [
|
||||||
|
'difficulties' => $difficulties,
|
||||||
|
'is_array' => is_array($difficulties),
|
||||||
|
]);
|
||||||
|
|
||||||
if (is_array($difficulties)) {
|
if (is_array($difficulties)) {
|
||||||
$validDifficulties = array_values(array_intersect(
|
$validDifficulties = array_values(array_intersect(
|
||||||
HuntDifficulty::values(),
|
HuntDifficulty::values(),
|
||||||
array_map('strtolower', $difficulties)
|
array_map('strtolower', $difficulties)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
Log::info('VALID_DIFFICULTIES', [
|
||||||
|
'valid_difficulties' => $validDifficulties,
|
||||||
|
'count' => count($validDifficulties),
|
||||||
|
]);
|
||||||
|
|
||||||
if (!empty($validDifficulties)) {
|
if (!empty($validDifficulties)) {
|
||||||
$difficultyFilters = array_map(
|
$difficultyFilters = array_map(
|
||||||
fn ($d) => 'difficulty = "'.$this->escapeMeiliString($d).'"',
|
fn ($d) => 'difficulty = "' . $this->escapeMeiliString($d) . '"',
|
||||||
$validDifficulties
|
$validDifficulties
|
||||||
);
|
);
|
||||||
$filters[] = '(' . implode(' OR ', $difficultyFilters) . ')';
|
$filter = '(' . implode(' OR ', $difficultyFilters) . ')';
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_DIFFICULTY_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
'difficulty_filters' => $difficultyFilters,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -133,26 +319,72 @@ class HuntsController extends Controller
|
||||||
$endFrom = $this->parseDateFilterUtc($request->query('end_from'));
|
$endFrom = $this->parseDateFilterUtc($request->query('end_from'));
|
||||||
$endTo = $this->parseDateFilterUtc($request->query('end_to'));
|
$endTo = $this->parseDateFilterUtc($request->query('end_to'));
|
||||||
|
|
||||||
|
Log::info('DATE_FILTERS_PARSED', [
|
||||||
|
'start_from' => $startFrom?->toIso8601String(),
|
||||||
|
'start_to' => $startTo?->toIso8601String(),
|
||||||
|
'end_from' => $endFrom?->toIso8601String(),
|
||||||
|
'end_to' => $endTo?->toIso8601String(),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($startFrom) {
|
if ($startFrom) {
|
||||||
$filters[] = "start_at_timestamp >= {$startFrom->timestamp}";
|
// start_at_timestamp est toujours présent (created_at par défaut), donc pas besoin de EXISTS
|
||||||
|
$filter = "start_at_timestamp >= {$startFrom->timestamp}";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_START_FROM_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
'timestamp' => $startFrom->timestamp,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
if ($startTo) {
|
if ($startTo) {
|
||||||
$filters[] = "start_at_timestamp <= {$startTo->timestamp}";
|
// start_at_timestamp est toujours présent
|
||||||
|
$filter = "start_at_timestamp <= {$startTo->timestamp}";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_START_TO_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
'timestamp' => $startTo->timestamp,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
if ($endFrom) {
|
if ($endFrom) {
|
||||||
$filters[] = "end_at_timestamp >= {$endFrom->timestamp}";
|
// end_at_timestamp peut être null, donc on vérifie qu'il existe avant de comparer
|
||||||
|
$filter = "(end_at_timestamp EXISTS AND end_at_timestamp >= {$endFrom->timestamp})";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_END_FROM_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
'timestamp' => $endFrom->timestamp,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
if ($endTo) {
|
if ($endTo) {
|
||||||
$filters[] = "end_at_timestamp <= {$endTo->timestamp}";
|
// end_at_timestamp peut être null, donc on vérifie qu'il existe avant de comparer
|
||||||
|
$filter = "(end_at_timestamp EXISTS AND end_at_timestamp <= {$endTo->timestamp})";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_END_TO_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
'timestamp' => $endTo->timestamp,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filtre par défaut : si aucun filtre n'est spécifié, afficher uniquement les hunts publics
|
// Filtre par défaut : si aucun filtre n'est spécifié, afficher uniquement les hunts publics
|
||||||
// Cela évite l'erreur Meilisearch avec une chaîne de filtres vide
|
// Cela évite l'erreur Meilisearch avec une chaîne de filtres vide
|
||||||
if (empty($filters)) {
|
if (empty($filters)) {
|
||||||
$filters[] = "is_public = true";
|
// En Meilisearch, les booléens peuvent être comparés avec true/false (sans guillemets)
|
||||||
|
$filter = "is_public = true";
|
||||||
|
$filters[] = $filter;
|
||||||
|
Log::info('ADDED_DEFAULT_PUBLIC_FILTER', [
|
||||||
|
'filter' => $filter,
|
||||||
|
'reason' => 'no_filters_provided',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return implode(' AND ', $filters);
|
$finalFilters = implode(' AND ', $filters);
|
||||||
|
|
||||||
|
Log::info('BUILD_FILTERS_COMPLETE', [
|
||||||
|
'filters_array' => $filters,
|
||||||
|
'filters_count' => count($filters),
|
||||||
|
'final_filters' => $finalFilters,
|
||||||
|
'final_filters_length' => strlen($finalFilters),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $finalFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveSearchTerm(Request $request): ?string
|
private function resolveSearchTerm(Request $request): ?string
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue