Preview: SlotRepository.php
Size: 11.43 KB
/var/www/multi-event-cfp.bitkit.dk/httpdocs/app/Repositories/SlotRepository.php
<?php
namespace App\Repositories;
use App\Models\Event;
use App\Models\Slot;
use App\Models\SlotUser;
use App\Models\Session;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Jobs\SendPublishedSessionSlotAbstractOrPresentationChangeEmail;
use App\Jobs\SendSessionCreatedMail;
use App\Lib\EmailSetupHelper;
class SlotRepository extends Repository
{
protected $emailSetup;
const KEY_TO_SLOT_USERS = "session_create_slot_users";
public function __construct($event = null)
{
$this->for($event);
$this->emailSetup = new EmailSetupHelper();
}
public function model(): ?Slot
{
return new Slot();
}
public function query($as = null)
{
$model = $this->model();
return $model->newQuery();
}
public function listing(Request $request, $paginate)
{
//building arguments
$arguments = $this->arguments($request);
//building query
$query = $this->scope($arguments);
return ($paginate && $arguments->paging != 'All') ? $query->paginate($arguments->paging, ['*'], 'page', $arguments->page) : $query->get();
}
public function scope($arguments, $callback = null)
{
$query = $this->query()
->select($this->selectColumns());
//applying different scopes based on the arguments
$this->applyScope($query, $arguments);
//resolve if there is any callback functions available
return $this->resolve($query, $arguments, $callback);
}
public function applyScope(Builder $query, $arguments): Builder
{
$this->applyEventScope($query, $arguments);
$this->applySessionScope($query, $arguments);
$this->applySlotUserScope($query, $arguments);
$this->applyOrder($query, $arguments);
$this->applySearch($query, $arguments);
return $query;
}
public function applySearch(Builder $query, $arguments): Builder
{
$columns = [
'id' => 'slots.id',
'identifier' => 'identifier',
'session_id' => 'session_id',
'start_date' => 'slots.start_date',
'end_date' => 'slots.end_date',
'duration' => 'slots.duration',
'type' => 'slots.type',
'slot_users' => 'slot_users',
'room' => 'room',
];
$search = $arguments->search;
$search = strtolower($search);
foreach ($columns as $column) {
$query->orHaving(DB::raw("lower($column)"), 'like', "%{$search}%");
}
return $query;
}
public function applyOrder(Builder $query, $arguments): Builder
{
$columns = [
'id' => 'slots.id',
'title' => 'slots.title',
'identifier' => 'slots.identifier',
'session_id' => 'slots.session_id',
'start_date' => 'slots.start_date',
'end_date' => 'slots.end_date',
'duration' => 'slots.duration',
'type' => 'slots.type',
'slot_users' => 'slot_users',
'room' => 'room'
];
$sorts = json_decode($arguments->sort, true) ?? [];
foreach ($sorts as $sort => $method) {
if (array_key_exists($sort, $columns)) {
$query->orderBy($sort, $method);
}
}
return $query;
}
public function applySessionScope(Builder $query, $arguments): Builder
{
$query->join('sessions', 'slots.session_id', '=', 'sessions.id')
->addSelect(['sessions.room as room']);
return $query;
}
public function applySlotUserScope(Builder $query, $arguments): Builder
{
$query->leftJoin('slot_users as su', 'slots.id', '=', 'su.slot_id')
->leftJoin('users as u', 'su.user_id', '=', 'u.id')
->addSelect([
DB::raw("
concat('[',
GROUP_CONCAT(
DISTINCT(
IF(
u.id is not null,
JSON_OBJECT(
'name',
concat(u.first_name, ' ', u.last_name),
'role',
su.role
),
NULL )
)
), ']'
) as slot_users")
])->groupBy('slots.id');
return $query;
}
public function applyEventScope(Builder $query, $arguments): Builder
{
if ($arguments->event) {
$query->where('slots.event_id', '=', $arguments->event->id);
}
return $query;
}
public function selectColumns(): array
{
return [
'slots.id',
'slots.event_id',
'slots.session_id',
'slots.presentation_id',
'slots.abstract_id',
'slots.start_date',
'slots.end_date',
'slots.duration',
'slots.title',
'slots.type',
'slots.reserved',
'slots.exclude_from_website',
'slots.identifier',
'slots.break_slot',
'slots.featured_by',
'slots.sponsored_by'
];
}
public function getSlotCount(Event $event): int
{
return $event->slots()
->count();
}
public function updateRelatedSlots($abstract, $presentation)
{
if ($abstract && $abstract->exists) {
// update dependent slots
$this->updateSlots($abstract, 'Abstract');
}
if ($presentation && $presentation->exists) {
// update dependent slots
$this->updateSlots($presentation, 'Presentation');
}
}
public function updateSlots($entity, $type)
{
if ($entity && $entity->exists) {
$slots = Slot::where("{$type}_id", $entity->id)->get();
foreach ($slots as $slot) {
// update slot title
$this->updateSlotTitle($slot, $entity, $type);
// update slot users
$this->updateSlotUsers($slot, $entity, $type);
}
}
}
public function updateSlotTitle($slot, $entity, $type)
{
$currentSlotTitle = $slot->title;
// Get the updated title from the entity data
$updatedTitleField = collect($entity->data)->firstWhere('field_id', 'title');
$updatedTitle = $updatedTitleField ? $updatedTitleField['value'] : $entity->id;
$formSettings = $slot->event->form_settings->toArray();
$titleEnabled = false;
// Use array_column to extract 'field_id' values
$fieldIds = array_column($formSettings, 'field_id');
// Check if 'title' is present in the extracted 'field_id' values
$key = array_search('title', $fieldIds);
if ($key !== false) {
// Check if 'enabled' is set to true
$titleEnabled = isset($formSettings[$key]['enabled']) && $formSettings[$key]['enabled'];
}
// Check if the old title is different from the new title
if ($currentSlotTitle !== $updatedTitle && ($titleEnabled || $type == 'Presentation')) {
// Update the slot title with the new title
$slot->title = $updatedTitle;
// Update the track title
$slot->abstract_presentation_track['title'] = $updatedTitle;
$slot->save();
// handle slot changes
$this->handleSlotChanges($slot, $entity, $type);
}
}
public function updateSlotUsers($slot, $entity, $type)
{
$currentSpeakers = SlotUser::where('slot_id', '=', $slot->id)->pluck('user_id')->toArray();
$trackSpeakers = $slot->abstract_presentation_track['speakers'];
$updatedSpeakers = ($type === 'Abstract')
? $entity->users('abstract_presenter')->pluck('id')->toArray()
: $entity->presenters->pluck('id')->toArray();
// Identify new speakers to add
$newSpeakers = array_diff($updatedSpeakers, $trackSpeakers);
// Identify speakers to remove
$removedSpeakers = array_diff($trackSpeakers, $updatedSpeakers);
// Check if there are changes in slot users
if (!empty($newSpeakers) || !empty($removedSpeakers)) {
// slot user changed or not
$slotUserChanged = false;
// Combine existing speakers and new speakers
//$finalSpeakers = array_merge($trackSpeakers, $newSpeakers);
// Add new speakers to the slot users
foreach ($newSpeakers as $newSpeaker) {
// Check if the user ID is not already in the list of track speakers
if (!in_array($newSpeaker, $currentSpeakers)) {
$this->addSlotUser($slot, $newSpeaker);
$slotUserChanged = true;
}
}
// Remove speakers from the slot users
foreach ($removedSpeakers as $removedSpeaker) {
$this->removeSlotUser($slot, $removedSpeaker);
$slotUserChanged = true;
}
// Update the abstract/presentation track speakers
$slot->abstract_presentation_track['speakers'] = $updatedSpeakers;
$slot->save();
if ($slotUserChanged) {
// handle slot changes
$this->handleSlotChanges($slot, $entity, $type);
}
}
}
private function addSlotUser($slot, $userId)
{
// add new slot user
$slotUser = new SlotUser();
$slotUser->event_id = $slot->event_id;
$slotUser->slot_id = $slot->id;
$slotUser->user_id = $userId;
$slotUser->role = 'Speaker';
// add order based on count
$slotUser->order = SlotUser::where('slot_id', $slot->id)->count() + 1;
$slotUser->save();
// Session
$session = Session::find($slot->session_id);
// email slot content
$emailSlotContents = $this->emailSetup->getEmailData($session->event->id, self::KEY_TO_SLOT_USERS);
// send user added to session mail
dispatch(new SendSessionCreatedMail($session, $slotUser->user, 'added to slot', $slot, $emailSlotContents));
}
private function removeSlotUser($slot, $userId)
{
$slotUser = SlotUser::where('slot_id', $slot->id)
->where('user_id', $userId)
->first();
if ($slotUser) {
// delete slot user
$slotUser->delete();
// re order remaining slot user
$this->reorderRemainingSlotUsers($slot);
}
}
private function reorderRemainingSlotUsers($slot)
{
// Retrieve all slot users for the given slot
$slotUsers = SlotUser::where('slot_id', $slot->id)
->orderBy('order')
->get();
// Reassign order values
foreach ($slotUsers as $index => $slotUser) {
$slotUser->order = $index + 1;
$slotUser->save();
}
}
public function handleSlotChanges($slot, $entity, $type)
{
// Session
$session = Session::find($slot->session_id);
if ($session->published_status) {
// published session slots abstract or presentation change email
dispatch(new SendPublishedSessionSlotAbstractOrPresentationChangeEmail($session, $entity, $type));
// Set published_status to false if there are changes
$session->published_status = false;
$session->save();
}
}
}
Directory Contents
Dirs: 0 × Files: 17