/** * Funzione richiamata da B nel caso in cui sta aspettando che arrivi la conferma che l'abbraccio è stato creato ma * non riceve nulla entro un tot di secondi. Utilizza quindi questa funzione per richiedere se l'abbraccio è stato * creato e se può entrare * * @param Request $request * * @return \Illuminate\Http\JsonResponse */ public function checkForHug(Request $request) { try { $this->validate($request, ['search_id' => 'required|numeric|exists:searches,id']); } catch (ValidationException $e) { $errors = $e->getErrors(); return parent::response([], $errors); } $user = $this->getAuthenticatedUser(); /** * @var Hug $hug * @var Search $search */ $hug = Hug::whereSearchId($request->get('search_id'))->whereNull('closed_at')->first(); $search = Search::whereId($request->get('search_id'))->first(); if (empty($hug)) { // Riprova o lascia perdere! return parent::response(["hug" => null, "retryIn" => 15]); } else { // L'abbraccio esiste. if ($hug->user_sought_id != $user->id) { // Non è lui quello che è stato trovato abort(403); } if (!empty($hug->user_sought_last_checkin)) { // Ha già fatto l'accesso abort(400); // Forse dovremmo evitare errore in questo caso e semplicemente dirgli "guarda che già sei dentro"? } // Ok può entrare $this->join($hug, $user); } return parent::response(["hug" => $hug]); }
/** * Algoritmo di riempimento di una lista. E' quello che decide quali utenti scegliere per la ricerca * * @throws Exception */ public function fillList() { if (!$this->exists) { throw new Exception('Non utilizzabile', 500); } /** * @var Search $search */ $search = Search::whereId($this->search_id)->first(); $lastTimeout = Carbon::now()->subMinutes(5)->toDateTimeString(); $lastUpdate = Carbon::now()->subMinutes(10)->toDateTimeString(); $usersWhoRefused = $search->usersWhoRefused(); $usersAlreadyFetched = $search->userAlreadyFetched(); // <Per test> $lastUpdate = Carbon::now()->subYear(1)->toDateTimeString(); // </Per test> $users = DB::table('users AS USER')->leftjoin('user_search_timeouts AS USER_TIMEOUT', 'USER_TIMEOUT.user_id', '=', 'USER.id')->selectRaw("USER.id, haversine(USER.geo_latitude, USER.geo_longitude, 10, 20) AS distance, MAX(USER_TIMEOUT.timed_out_at) AS last_timeout")->where('USER.geo_last_update', '>', $lastUpdate)->whereRaw('haversine(USER.geo_latitude, USER.geo_longitude, 10, 20) <= ' . (double) $search->max_distance)->whereNotIn('USER.id', $usersWhoRefused)->whereNotIn('USER.id', $usersAlreadyFetched)->where('USER.id', '<>', $search->user_id)->where('USER.status', '=', User::STATUS_AVAILABLE)->groupBy('USER.id')->havingRaw('last_timeout < ' . DB::getPdo()->quote($lastTimeout) . ' OR last_timeout IS NULL')->orderBy('distance')->limit(self::MAX_USERS_FOR_LIST)->get(); if (!empty($users)) { $tuples = []; foreach ($users as $i => $user) { /** * @var stdClass $user */ $tuples[] = ['search_list_id' => $this->id, 'user_id' => $user->id, 'order' => $i + 1]; } DB::table('search_list_users')->insert($tuples); } }
/** * Gestisce le risposte degli utenti in seguito ad una richista di abbraccio. * * @param Request $request * * @return \Illuminate\Http\JsonResponse */ public function userResponse(Request $request) { $responseType = last(explode('.', $request->route()->getName())); if (!in_array($responseType, ['accept', 'reject', 'noResponse'])) { // Risposta invalida abort(404, 'Invalid response'); } try { $this->validate($request, ['id' => 'required|numeric|exists:searches,id']); } catch (ValidationException $e) { $errors = $e->getErrors(); return parent::response([], $errors); } $user = $this->getAuthenticatedUser(); /** * @var Search $search */ $search = Search::whereId($request->input('id'))->whereNull('finished_at')->first(); if ($user->id != $search->getLastFetchedUserId()) { // Non può rispondere a questa ricerca // TODO: Forse bisognerebbe prevedere qualcosa, soprattuto nell'accept. (oppure gestirlo nell'app?) abort(403); } switch ($responseType) { case 'accept': $this->userResponseAccept($search, $user); // Termino la ricerca $this->finish($search, self::FINISH_STATUS_SUCCESSFUL); // salvo alcuni dati utili $search->setFoundUserId($user->id); $search->save(); // Notifico l'utente che ha avviato la ricerca $this->notifyTheSearcher($search); break; case 'reject': $this->userResponseReject($search, $user); // Continuo la ricerca $this->process($search); break; case 'noResponse': $this->userResponseNoResponse($search, $user); // Continuo la ricerca $this->process($search); break; default: } return parent::response([]); }