Eager load relations and optimize queries
This commit is contained in:
parent
5fccc7e421
commit
05725cd58c
|
@ -175,7 +175,9 @@ function angeltype_controller()
|
||||||
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
|
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
|
||||||
/** @var UserAngelType $user_angeltype */
|
/** @var UserAngelType $user_angeltype */
|
||||||
$user_angeltype = UserAngelType::whereUserId($user->id)->where('angel_type_id', $angeltype->id)->first();
|
$user_angeltype = UserAngelType::whereUserId($user->id)->where('angel_type_id', $angeltype->id)->first();
|
||||||
$members = $angeltype->userAngelTypes->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE);
|
$members = $angeltype->userAngelTypes
|
||||||
|
->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE)
|
||||||
|
->load(['state', 'personalData', 'contact']);
|
||||||
$days = angeltype_controller_shiftsFilterDays($angeltype);
|
$days = angeltype_controller_shiftsFilterDays($angeltype);
|
||||||
$shiftsFilter = angeltype_controller_shiftsFilter($angeltype, $days);
|
$shiftsFilter = angeltype_controller_shiftsFilter($angeltype, $days);
|
||||||
if (request()->input('showFilledShifts')) {
|
if (request()->input('showFilledShifts')) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\ShiftCalendarRenderer;
|
use Engelsystem\ShiftCalendarRenderer;
|
||||||
use Engelsystem\ShiftsFilter;
|
use Engelsystem\ShiftsFilter;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -297,13 +298,15 @@ function users_list_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var User[]|Collection $users */
|
/** @var User[]|Collection $users */
|
||||||
$users = User::with(['contact', 'personalData', 'state'])
|
$users = User::with(['contact', 'personalData', 'state', 'shiftEntries' => function (HasMany $query) {
|
||||||
|
$query->where('freeloaded', true);
|
||||||
|
}])
|
||||||
->orderBy('name')
|
->orderBy('name')
|
||||||
->get();
|
->get();
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
$user->setAttribute(
|
$user->setAttribute(
|
||||||
'freeloads',
|
'freeloads',
|
||||||
$user->shiftEntries()
|
$user->shiftEntries
|
||||||
->where('freeloaded', true)
|
->where('freeloaded', true)
|
||||||
->count()
|
->count()
|
||||||
);
|
);
|
||||||
|
|
|
@ -116,7 +116,7 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
|
||||||
|
|
||||||
$shifts = collect($shifts);
|
$shifts = collect($shifts);
|
||||||
|
|
||||||
return Shift::query()
|
return Shift::with(['location', 'shiftType'])
|
||||||
->whereIn('id', $shifts->pluck('id')->toArray())
|
->whereIn('id', $shifts->pluck('id')->toArray())
|
||||||
->orderBy('shifts.start')
|
->orderBy('shifts.start')
|
||||||
->get();
|
->get();
|
||||||
|
@ -189,12 +189,14 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
$shifts = [];
|
$shifts = new Collection();
|
||||||
foreach ($shiftsData as $shift) {
|
foreach ($shiftsData as $shift) {
|
||||||
$shifts[] = (new Shift())->forceFill($shift);
|
$shifts[] = (new Shift())->forceFill($shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
return collect($shifts);
|
$shifts->load(['location', 'shiftType']);
|
||||||
|
|
||||||
|
return $shifts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -354,7 +356,7 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
|
||||||
*/
|
*/
|
||||||
function ShiftEntries_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
function ShiftEntries_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
{
|
{
|
||||||
return ShiftEntry::with('user')
|
return ShiftEntry::with('user', 'user.state')
|
||||||
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
|
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
|
||||||
->whereIn('shifts.location_id', $shiftsFilter->getLocations())
|
->whereIn('shifts.location_id', $shiftsFilter->getLocations())
|
||||||
->whereBetween('start', [$shiftsFilter->getStart(), $shiftsFilter->getEnd()])
|
->whereBetween('start', [$shiftsFilter->getStart(), $shiftsFilter->getEnd()])
|
||||||
|
@ -638,12 +640,13 @@ function Shifts_by_user($userId, $include_freeloaded_comments = false)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
$shifts = [];
|
$shifts = new Collection();
|
||||||
foreach ($shiftsData as $data) {
|
foreach ($shiftsData as $data) {
|
||||||
$shifts[] = (new Shift())->forceFill($data);
|
$shifts[] = (new Shift())->forceFill($data);
|
||||||
}
|
}
|
||||||
|
$shifts->load(['shiftType', 'location']);
|
||||||
|
|
||||||
return collect($shifts);
|
return $shifts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@ function UserWorkLogsForUser($userId, Carbon $sinceTime = null)
|
||||||
if ($sinceTime) {
|
if ($sinceTime) {
|
||||||
$worklogs = $worklogs->whereDate('worked_at', '>=', $sinceTime);
|
$worklogs = $worklogs->whereDate('worked_at', '>=', $sinceTime);
|
||||||
}
|
}
|
||||||
|
$worklogs->with(['user', 'creator']);
|
||||||
|
|
||||||
return $worklogs->get();
|
return $worklogs->get();
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ function admin_active()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = User::with('personalData')
|
$query = User::with(['personalData', 'state'])
|
||||||
->selectRaw(
|
->selectRaw(
|
||||||
sprintf(
|
sprintf(
|
||||||
'
|
'
|
||||||
|
|
|
@ -65,7 +65,7 @@ function admin_arrive()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var User[] $users */
|
/** @var User[] $users */
|
||||||
$users = User::with('personalData')->orderBy('name')->get();
|
$users = User::with(['personalData', 'state'])->orderBy('name')->get();
|
||||||
$arrival_count_at_day = [];
|
$arrival_count_at_day = [];
|
||||||
$planned_arrival_count_at_day = [];
|
$planned_arrival_count_at_day = [];
|
||||||
$planned_departure_count_at_day = [];
|
$planned_departure_count_at_day = [];
|
||||||
|
|
|
@ -40,7 +40,7 @@ function admin_free()
|
||||||
/** @var User[] $users */
|
/** @var User[] $users */
|
||||||
$users = [];
|
$users = [];
|
||||||
if ($request->has('submit')) {
|
if ($request->has('submit')) {
|
||||||
$query = User::with('personalData')
|
$query = User::with(['personalData', 'contact', 'state'])
|
||||||
->select('users.*')
|
->select('users.*')
|
||||||
->leftJoin('shift_entries', 'users.id', 'shift_entries.user_id')
|
->leftJoin('shift_entries', 'users.id', 'shift_entries.user_id')
|
||||||
->leftJoin('users_state', 'users.id', 'users_state.user_id')
|
->leftJoin('users_state', 'users.id', 'users_state.user_id')
|
||||||
|
|
|
@ -21,13 +21,13 @@ function admin_groups()
|
||||||
$html = '';
|
$html = '';
|
||||||
$request = request();
|
$request = request();
|
||||||
/** @var Group[]|Collection $groups */
|
/** @var Group[]|Collection $groups */
|
||||||
$groups = Group::query()->orderBy('name')->get();
|
$groups = Group::with('privileges')->orderBy('name')->get();
|
||||||
|
|
||||||
if (!$request->has('action')) {
|
if (!$request->has('action')) {
|
||||||
$groups_table = [];
|
$groups_table = [];
|
||||||
foreach ($groups as $group) {
|
foreach ($groups as $group) {
|
||||||
/** @var Privilege[]|Collection $privileges */
|
/** @var Privilege[]|Collection $privileges */
|
||||||
$privileges = $group->privileges()->orderBy('name')->get();
|
$privileges = $group->privileges->sortBy('name');
|
||||||
$privileges_html = [];
|
$privileges_html = [];
|
||||||
|
|
||||||
foreach ($privileges as $privilege) {
|
foreach ($privileges as $privilege) {
|
||||||
|
|
|
@ -326,6 +326,9 @@ function admin_shifts()
|
||||||
|
|
||||||
$shifts_table = [];
|
$shifts_table = [];
|
||||||
foreach ($shifts as $shift) {
|
foreach ($shifts as $shift) {
|
||||||
|
$shiftType = $shifttypes_source->find($shift['shift_type_id']);
|
||||||
|
$location = $locations->find($shift['location_id']);
|
||||||
|
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = $shift['start'];
|
$start = $shift['start'];
|
||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
|
@ -340,9 +343,9 @@ function admin_shifts()
|
||||||
. '</span>'
|
. '</span>'
|
||||||
. ', ' . round($end->copy()->diffInMinutes($start) / 60, 2) . 'h'
|
. ', ' . round($end->copy()->diffInMinutes($start) / 60, 2) . 'h'
|
||||||
. '<br>'
|
. '<br>'
|
||||||
. location_name_render(Location::find($shift['location_id'])),
|
. location_name_render($location),
|
||||||
'title' =>
|
'title' =>
|
||||||
htmlspecialchars(ShiftType::find($shifttype_id)->name)
|
htmlspecialchars($shiftType->name)
|
||||||
. ($shift['title'] ? '<br />' . htmlspecialchars($shift['title']) : ''),
|
. ($shift['title'] ? '<br />' . htmlspecialchars($shift['title']) : ''),
|
||||||
'needed_angels' => '',
|
'needed_angels' => '',
|
||||||
];
|
];
|
||||||
|
|
|
@ -552,8 +552,7 @@ class ImportSchedule extends BaseController
|
||||||
$existingShifts = $this->getScheduleShiftsByGuid($scheduleUrl, $scheduleEventsGuidList);
|
$existingShifts = $this->getScheduleShiftsByGuid($scheduleUrl, $scheduleEventsGuidList);
|
||||||
foreach ($existingShifts as $scheduleShift) {
|
foreach ($existingShifts as $scheduleShift) {
|
||||||
$guid = $scheduleShift->guid;
|
$guid = $scheduleShift->guid;
|
||||||
/** @var Shift $shift */
|
$shift = $scheduleShift->shift;
|
||||||
$shift = Shift::with('location')->find($scheduleShift->shift_id);
|
|
||||||
$event = $scheduleEvents[$guid];
|
$event = $scheduleEvents[$guid];
|
||||||
$location = $locations->where('name', $event->getRoom()->getName())->first();
|
$location = $locations->where('name', $event->getRoom()->getName())->first();
|
||||||
|
|
||||||
|
@ -620,7 +619,7 @@ class ImportSchedule extends BaseController
|
||||||
*/
|
*/
|
||||||
protected function getScheduleShiftsByGuid(ScheduleUrl $scheduleUrl, array $events)
|
protected function getScheduleShiftsByGuid(ScheduleUrl $scheduleUrl, array $events)
|
||||||
{
|
{
|
||||||
return ScheduleShift::query()
|
return ScheduleShift::with('shift.location')
|
||||||
->whereIn('guid', $events)
|
->whereIn('guid', $events)
|
||||||
->where('schedule_id', $scheduleUrl->id)
|
->where('schedule_id', $scheduleUrl->id)
|
||||||
->get();
|
->get();
|
||||||
|
@ -633,7 +632,7 @@ class ImportSchedule extends BaseController
|
||||||
*/
|
*/
|
||||||
protected function getScheduleShiftsWhereNotGuid(ScheduleUrl $scheduleUrl, array $events)
|
protected function getScheduleShiftsWhereNotGuid(ScheduleUrl $scheduleUrl, array $events)
|
||||||
{
|
{
|
||||||
return ScheduleShift::query()
|
return ScheduleShift::with('shift.location')
|
||||||
->whereNotIn('guid', $events)
|
->whereNotIn('guid', $events)
|
||||||
->where('schedule_id', $scheduleUrl->id)
|
->where('schedule_id', $scheduleUrl->id)
|
||||||
->get();
|
->get();
|
||||||
|
|
|
@ -297,7 +297,6 @@ function view_user_shifts()
|
||||||
|
|
||||||
return page([
|
return page([
|
||||||
div('col-md-12', [
|
div('col-md-12', [
|
||||||
msg(),
|
|
||||||
view(__DIR__ . '/../../resources/views/pages/user-shifts.html', [
|
view(__DIR__ . '/../../resources/views/pages/user-shifts.html', [
|
||||||
'title' => shifts_title(),
|
'title' => shifts_title(),
|
||||||
'add_link' => auth()->can('admin_shifts') ? $link : '',
|
'add_link' => auth()->can('admin_shifts') ? $link : '',
|
||||||
|
|
|
@ -38,7 +38,8 @@ class QuestionsController extends BaseController
|
||||||
$questions = $this->question
|
$questions = $this->question
|
||||||
->orderBy('answered_at')
|
->orderBy('answered_at')
|
||||||
->orderByDesc('created_at')
|
->orderByDesc('created_at')
|
||||||
->get();
|
->get()
|
||||||
|
->load(['user.state', 'answerer.state']);
|
||||||
|
|
||||||
return $this->response->withView(
|
return $this->response->withView(
|
||||||
'pages/questions/overview.twig',
|
'pages/questions/overview.twig',
|
||||||
|
|
|
@ -218,7 +218,8 @@ class MessagesController extends BaseController
|
||||||
$join->on('messages.id', '=', 'conversations.last_id');
|
$join->on('messages.id', '=', 'conversations.last_id');
|
||||||
})
|
})
|
||||||
->orderBy('created_at', 'DESC')
|
->orderBy('created_at', 'DESC')
|
||||||
->get();
|
->get()
|
||||||
|
->load(['receiver.personalData', 'receiver.state']);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function raw(mixed $value): QueryExpression
|
protected function raw(mixed $value): QueryExpression
|
||||||
|
|
|
@ -53,8 +53,7 @@ class NewsController extends BaseController
|
||||||
$newsId = (int) $request->getAttribute('news_id');
|
$newsId = (int) $request->getAttribute('news_id');
|
||||||
|
|
||||||
$news = $this->news
|
$news = $this->news
|
||||||
->with('user')
|
->with(['user', 'comments.user.state', 'comments.user.personalData'])
|
||||||
->with('comments')
|
|
||||||
->findOrFail($newsId);
|
->findOrFail($newsId);
|
||||||
|
|
||||||
return $this->renderView('pages/news/news.twig', ['news' => $news]);
|
return $this->renderView('pages/news/news.twig', ['news' => $news]);
|
||||||
|
|
|
@ -36,7 +36,8 @@ class QuestionsController extends BaseController
|
||||||
->whereUserId($this->auth->user()->id)
|
->whereUserId($this->auth->user()->id)
|
||||||
->orderByDesc('answered_at')
|
->orderByDesc('answered_at')
|
||||||
->orderBy('created_at')
|
->orderBy('created_at')
|
||||||
->get();
|
->get()
|
||||||
|
->load(['user.state', 'answerer.state']);
|
||||||
|
|
||||||
return $this->response->withView(
|
return $this->response->withView(
|
||||||
'pages/questions/overview.twig',
|
'pages/questions/overview.twig',
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Authenticator
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->user = $this->userFromSession();
|
$this->user = $this->userFromSession();
|
||||||
if (!$this->user && request()->getAttribute('route-api-accessible', false)) {
|
if (!$this->user && $this->isApiRequest()) {
|
||||||
$this->user = $this->userFromApi();
|
$this->user = $this->userFromApi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +102,10 @@ class Authenticator
|
||||||
if ($user) {
|
if ($user) {
|
||||||
$this->permissions = $user->privileges->pluck('name')->toArray();
|
$this->permissions = $user->privileges->pluck('name')->toArray();
|
||||||
|
|
||||||
$user->last_login_at = new Carbon();
|
if ($user->last_login_at < Carbon::now()->subMinutes(5) && !$this->isApiRequest()) {
|
||||||
$user->save();
|
$user->last_login_at = Carbon::now();
|
||||||
|
$user->save(['touch' => false]);
|
||||||
|
}
|
||||||
} elseif ($this->session->get('user_id')) {
|
} elseif ($this->session->get('user_id')) {
|
||||||
$this->session->remove('user_id');
|
$this->session->remove('user_id');
|
||||||
}
|
}
|
||||||
|
@ -206,6 +208,11 @@ class Authenticator
|
||||||
return $this->user;
|
return $this->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function isApiRequest(): bool
|
||||||
|
{
|
||||||
|
return (bool) request()->getAttribute('route-api-accessible', false);
|
||||||
|
}
|
||||||
|
|
||||||
public function setPassword(User $user, string $password): void
|
public function setPassword(User $user, string $password): void
|
||||||
{
|
{
|
||||||
$user->password = password_hash($password, $this->passwordAlgorithm);
|
$user->password = password_hash($password, $this->passwordAlgorithm);
|
||||||
|
|
|
@ -14,6 +14,8 @@ use function array_key_exists;
|
||||||
|
|
||||||
class Globals extends TwigExtension implements GlobalsInterface
|
class Globals extends TwigExtension implements GlobalsInterface
|
||||||
{
|
{
|
||||||
|
protected array $globals = [];
|
||||||
|
|
||||||
public function __construct(protected Authenticator $auth, protected Request $request)
|
public function __construct(protected Authenticator $auth, protected Request $request)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -22,6 +24,18 @@ class Globals extends TwigExtension implements GlobalsInterface
|
||||||
* Returns a list of global variables to add to the existing list.
|
* Returns a list of global variables to add to the existing list.
|
||||||
*/
|
*/
|
||||||
public function getGlobals(): array
|
public function getGlobals(): array
|
||||||
|
{
|
||||||
|
if (empty($this->globals)) {
|
||||||
|
$this->globals = $this->getGlobalValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->globals;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the list of global variables
|
||||||
|
*/
|
||||||
|
protected function getGlobalValues(): array
|
||||||
{
|
{
|
||||||
$user = $this->auth->user();
|
$user = $this->auth->user();
|
||||||
$themes = config('themes');
|
$themes = config('themes');
|
||||||
|
|
|
@ -207,6 +207,7 @@ class AuthenticatorTest extends ServiceProviderTest
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Helpers\Authenticator::can
|
* @covers \Engelsystem\Helpers\Authenticator::can
|
||||||
|
* @covers \Engelsystem\Helpers\Authenticator::isApiRequest
|
||||||
*/
|
*/
|
||||||
public function testCan(): void
|
public function testCan(): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,7 @@ class GlobalsTest extends ExtensionTest
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Globals::__construct
|
* @covers \Engelsystem\Renderer\Twig\Extensions\Globals::__construct
|
||||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Globals::getGlobals
|
* @covers \Engelsystem\Renderer\Twig\Extensions\Globals::getGlobals
|
||||||
|
* @covers \Engelsystem\Renderer\Twig\Extensions\Globals::getGlobalValues
|
||||||
*/
|
*/
|
||||||
public function testGetGlobals(): void
|
public function testGetGlobals(): void
|
||||||
{
|
{
|
||||||
|
@ -82,6 +83,7 @@ class GlobalsTest extends ExtensionTest
|
||||||
$this->assertGlobalsExists('theme', $theme2, $globals);
|
$this->assertGlobalsExists('theme', $theme2, $globals);
|
||||||
|
|
||||||
// User
|
// User
|
||||||
|
$extension = new Globals($auth, $request);
|
||||||
$globals = $extension->getGlobals();
|
$globals = $extension->getGlobals();
|
||||||
$this->assertGlobalsExists('user', $user, $globals);
|
$this->assertGlobalsExists('user', $user, $globals);
|
||||||
$this->assertGlobalsExists('user_messages', 0, $globals);
|
$this->assertGlobalsExists('user_messages', 0, $globals);
|
||||||
|
@ -89,15 +91,21 @@ class GlobalsTest extends ExtensionTest
|
||||||
$this->assertGlobalsExists('theme', $theme, $globals);
|
$this->assertGlobalsExists('theme', $theme, $globals);
|
||||||
|
|
||||||
// User with not available theme configured
|
// User with not available theme configured
|
||||||
|
$extension = new Globals($auth, $request);
|
||||||
$user->settings->theme = 9999;
|
$user->settings->theme = 9999;
|
||||||
$globals = $extension->getGlobals();
|
$globals = $extension->getGlobals();
|
||||||
$this->assertGlobalsExists('themeId', 42, $globals);
|
$this->assertGlobalsExists('themeId', 42, $globals);
|
||||||
|
|
||||||
// Request query parameter
|
// Request query parameter
|
||||||
|
$extension = new Globals($auth, $request);
|
||||||
$request->query->set('theme', 1337);
|
$request->query->set('theme', 1337);
|
||||||
$globals = $extension->getGlobals();
|
$globals = $extension->getGlobals();
|
||||||
$this->assertGlobalsExists('user', [], $globals);
|
$this->assertGlobalsExists('user', [], $globals);
|
||||||
$this->assertGlobalsExists('themeId', 1337, $globals);
|
$this->assertGlobalsExists('themeId', 1337, $globals);
|
||||||
$this->assertGlobalsExists('theme', $theme3, $globals);
|
$this->assertGlobalsExists('theme', $theme3, $globals);
|
||||||
|
|
||||||
|
// Second retrieval is loaded directly
|
||||||
|
$globals = $extension->getGlobals();
|
||||||
|
$this->assertGlobalsExists('themeId', 1337, $globals);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue