middleware(function (Request $request, callable $next) { if (Auth::guard('club')->check()) { /** @var \App\Models\Customer */ $customerModel = Auth::guard('club')->user(); $notificationModels = $customerModel->getAllNotifications(); View::share( 'notifications_count', $notificationModels->count() - $customerModel->readNotifications()->count() ); View::share('notifications_list', $notificationModels); View::share('notifications_message_count', $notificationModels // @phpstan-ignore-next-line ->filter(function (Notification $notificationModel) { return $notificationModel->notifiable_type === Message::class and !is_null($notificationModel->customer_id); }) ->count()); $discountCache = Cache::remember( "discountsCustomerCount_{$customerModel->hashcode}", 86400, function () use ($customerModel) { return Discount::getCustomerDiscountsCount($customerModel->hashcode); } ); View::share('discountsCustomerCount', $discountCache); } //end if return $next($request); }); } /** * Gives the redirection path for FO Auth controllers. * * @return string */ protected function authLoggedRedirectPath(): string { return route('club.home.show'); } /** * Build Search query on specified fields * splitting search into words or using whole sentence. * * @param \Illuminate\Database\Eloquent\Builder $query The eloquent query builder. * @param string $search The query string. * @param callable|null $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. * @return \Illuminate\Database\Eloquent\Builder */ protected function searchQuery( Builder $query, string $search, callable|null $searchQuery = null, string ...$fields ): \Illuminate\Database\Eloquent\Builder { if (count($fields)) { // Search using words. $words = explode(' ', $search); $query->where(function ($query) use ($searchQuery, $words, $search, $fields) { foreach ($words as $word) { if (!strlen($word)) { continue; } $this->searchOnFields($query, $word, $fields); } //end foreach // Search whole using whole sentence. $this->searchOnFields($query, $search, $fields); if ($searchQuery) { $searchQuery($query); } }); } //end if return $query; } /** * Build query search on all fields. * * @param \Illuminate\Database\Eloquent\Builder $query * @param string $search * @param array $fields * @return \Illuminate\Database\Eloquent\Builder */ private function searchOnFields( Builder $query, string $search, array $fields ): \Illuminate\Database\Eloquent\Builder { $table = $query->getModel()->getTable(); foreach ($fields as $field) { $field = str_replace('?', '\?', $field); if (is_array($field)) { $query->orWhereRaw( sprintf("UPPER(CONCAT(%s)) LIKE UPPER(?)", collect($field)->map(function ($q) use ($table) { return "`$table`.`$q`"; })->implode(', \' \', ')), ['%' . htmlspecialchars($search) . '%'] ); return $query; } // 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) . '%'] ); } return $query; } // Get models with relation's name/label. if (Str::endsWith($field, '_id')) { $query->orWhereHas(Str::remove('_id', $field), function ($queryRelation) use ($field, $search) { 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 . '%'); } }); return $query; } $query->orWhereRaw( "UPPER(`$table`.`$field`) LIKE UPPER(?)", ['%' . htmlspecialchars($this->getSearchValue($query, $search, $field)) . '%'] ); } //end foreach return $query; } /** * Get the search value (on string or Enum). * * @param \Illuminate\Database\Eloquent\Builder $query * @param string $search * @param string $field * @return string|array */ protected function getSearchValue(Builder $query, string $search, string $field): string|array { $cast = $query->getModel()->getCasts()[$field] ?? null; if ( count($query->getModel()->getCasts()) and // Check if the model has casts. $cast and // Check if there is cast about specific field. enum_exists($cast) // Check if the cast is an enum. ) { /** @var \App\Traits\Enums $cast */ // @phpstan-ignore-next-line $cases = collect($cast::toArray()); $enum = $cases->filter(function ($item) use ($search) { return preg_match('/' . Str::lower($search) . '/', Str::lower($item->label)); }); return $enum->toArray(); } else { return $search; } } /** * Sort columns with a query. * * @param \Illuminate\Database\Eloquent\Builder $query * @param array $ignore * @return \Illuminate\Database\Eloquent\Builder */ protected function sortQuery(Builder $query, array $ignore = []): \Illuminate\Database\Eloquent\Builder { $rName = request()->route()->getName(); $table = $query->getModel()->getTable(); if (request()->input('sort_col')) { Session::put("$rName.sort_col", request()->input('sort_col')); Session::put("$rName.sorted", true); } if (request()->input('sort_way')) { Session::put("$rName.sort_way", request()->input('sort_way')); Session::put("$rName.sorted", true); } if (request()->rst) { Session::remove("$rName.sorted"); Session::remove("$rName.sort_col"); Session::remove("$rName.sort_way"); } if ( request()->input('sort_col') and request()->input('sort_way') and Schema::hasColumn($table, request()->input('sort_col')) ) { if (!in_array(request()->input('sort_col'), $ignore)) { $query = $query->orderBy( \sprintf("$table.%s", request()->input('sort_col')), request()->input('sort_way') ); } } elseif (Schema::hasColumn($table, 'order')) { $query = $query->orderBy('order', 'ASC'); Session::put("$rName.sort_col", 'order'); Session::put("$rName.sort_way", 'asc'); } elseif (Schema::hasColumn($table, 'updated_at')) { $query = $query->orderBy('updated_at', 'DESC'); Session::put("$rName.sort_col", 'updated_at'); Session::put("$rName.sort_way", 'desc'); } elseif (Schema::hasColumn($table, 'created_at')) { $query = $query->orderBy('created_at', 'DESC'); Session::put("$rName.sort_col", 'created_at'); Session::put("$rName.sort_way", 'desc'); } return $query; } /** * Customize pagination with cache or config (default). * * @param \Illuminate\Database\Eloquent\Builder $query * @param \App\Enums\Pagination\ItemsPerPaginationEnum|null $pagination * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator */ protected function paginate( Builder $query, ItemsPerPaginationEnum|null $pagination = null ): \Illuminate\Contracts\Pagination\LengthAwarePaginator { $currentRoutePath = Str::slug(request()->route()->getName()); $cacheKey = "pagination.{$currentRoutePath}"; $pagination = $pagination ?? ItemsPerPaginationEnum::twelve; $pagination = ToolboxHelper::getValidatedEnum( Cache::get($cacheKey, $pagination->value()), 'pagination', '\App\Enums\Pagination\ItemsPerPaginationEnum', ); if (Cache::get($cacheKey) !== $pagination) { Cache::put($cacheKey, $pagination); } $query = $query->paginate($pagination); return $query; } /** * Get a paginate resource. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ public function jsonPaginateModels(Request $request): \Illuminate\Http\JsonResponse { /** @var \Illuminate\Database\Eloquent\Model $models */ $models = $request->targetModel::query() ->where($request->input('fieldName') ?? 'name', 'like', "%{$request->input('search')}%") ->orderBy($request->input('fieldName') ?? 'name', 'ASC') ->paginate($request->input('paginate') ?? 10); return \response()->json($models); } /** * Set the bootstrap theme or light (default). * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\RedirectResponse */ protected function setTheme(Request $request): \Illuminate\Http\RedirectResponse { $theme = ToolboxHelper::getValidatedEnum( $request->theme ?: Cache::get('theme', BootstrapThemeEnum::light->value()), 'theme', '\App\Http\Controllers\BootstrapThemeEnum', ); if (Cache::get("theme") !== $theme) { Cache::put("theme", $theme); } return redirect()->back()->with('success', trans('crud.messages.theme_updated')); } /** * Get models titles for search input propositions. * * @param Builder $query * @param string $searchField * @param string|null $search * @return \Illuminate\Pagination\LengthAwarePaginator */ public function getModelsTitles( Builder $query, string $searchField, string|null $search = null ): \Illuminate\Pagination\LengthAwarePaginator { $modelsTitles = []; $searchLower = Str::lower($search); $query->when(!is_null($search), function (Builder $q) use ($searchLower, $searchField) { $q->where($searchField, 'like', "%{$searchLower}%"); }) ->where('published', true) ->inRandomOrder() ->pluck($searchField) ->each(function (string $title) use (&$modelsTitles, $searchLower) { if (count($modelsTitles) < 5) { foreach (explode(" ", $title) as $word) { $word = Str::lower($word); if ( strlen($word) > 3 && !in_array($word, $modelsTitles) && str_contains($word, $searchLower) ) { $modelsTitles[] = $word; } } return $modelsTitles; } }) ->toArray(); \sort($modelsTitles); $titles = array_slice($modelsTitles, 0, 5); return new LengthAwarePaginatorCustom($titles, count($titles), (count($titles) <= 0) ? 1 : count($titles)); } }