Preview: PresentationRepository.php
Size: 59.48 KB
/var/www/multi-event-cfp.bitkit.dk/httpdocs/app/Repositories/PresentationRepository.php
<?php
namespace App\Repositories;
use App\Jobs\SendPresentationSubmittedMails;
use App\Jobs\SendSpeakerTerms;
use App\Models\Abstracts;
use Illuminate\Support\Facades\Log;
use App\Models\EventUser;
use App\Models\Presentation;
use App\Models\PresentationComment;
use App\Models\PresentationReview;
use App\Models\Presenter;
use App\Models\User;
use App\Models\Event;
use URL;
use ZipArchive;
use App\Rules\PresentationDataRule;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use App\Jobs\SendPresentationEditStatusChangeMail;
use App\Jobs\SendPresentationStatusChangeMail;
use App\Jobs\SendAssignReviewerMail;
use App\Jobs\SendReviewerApprovedMail;
use App\Jobs\SendPresentationDownloadLinkEmail;
use App\Models\Slot;
use Illuminate\Support\Str;
use PhpParser\Node\Expr\AssignOp\Concat;
class PresentationRepository extends Repository
{
public $fileName;
protected $presentaionFields = ["submission_status", "assigned_status", "written_paper_status", "reviewer_assigned_status"];
public function __construct($event = null)
{
$this->for($event);
}
public function model(): Presentation
{
return new Presentation;
}
public function query($as = null)
{
$model = $this->model();
return $model->newQuery();
}
public function createOrUpdate(Request $request, Abstracts $abstract = null): Presentation
{
$presentationId = $request->get('id');
$invitationResponse = $request->get('invitation_response');
$submissionStatusValue = $request->get('submission_status');
$input = $request->input();
if ($presentationId || $invitationResponse || $submissionStatusValue == "Draft") {
$role = $request->get('role');
$event = $request->get('event');
$submissionStatus = $request->get('submission_status', 'Draft');
$presentersOnly = $request->get('presenter_only', false) == 'true';
if ($role != 'event_submitter' && $role != 'event_admin')
validationErrorResponse(['Access denied']);
if (!$presentationId) {
if ($abstract) {
$presentation = Presentation::whereEventId($event->id)
->whereAbstractId($abstract->id)
->first();
if ($presentation)
validationErrorResponse(['Presentation already exists']);
}
$presentation = new Presentation([
'user_id' => $abstract->user_id ?? authUser()->id,
'submission_status' => $submissionStatus,
'event_id' => $event->id,
'abstract_id' => $abstract->id ?? null,
'type' => $abstract ? 'abstract' : 'presentation',
'presentation_type' => $abstract->presentation_type ?? null
]);
$presentation->save();
if ($abstract) {
$presenters = $abstract->users('abstract_presenter')->pluck('id')->toArray();
$presentation->presenters()->attach($presenters, ['event_id' => $presentation->event_id]);
$presentationPresenters = Presenter::wherePresentationId($presentation->id)->get();
$eventUsers = [];
foreach ($presentationPresenters as $presentationPresenter) {
$eventUser = getEventUser($event->id, $presentationPresenter->user_id);
$eventUsers[] = $eventUser;
$this->markAsConfirmedSpeaker($eventUser, 'Abstract', $event->id);
}
if (!empty($eventUsers) && !$abstract->presentation_tc_status)
dispatch(new SendSpeakerTerms($eventUsers));
}
else {
// managing presenters in presentation
if (isset($input['presenters'])) {
$presenters = json_decode($input['presenters'] ?? "[]", true);
}
else {
$user = authUser();
$userData = json_decode($user, true);
$presenters[] = $userData;
// $presentationRequestCount = $request->get('presentation_request_count') ? $request->get('presentation_request_count') : null;
// if ($presentationRequestCount || $presentationRequestCount == 0) {
// // event user
// $eventUser = EventUser::whereEventId($event->id)
// ->whereUserId($user->id)
// ->first();
// if ($eventUser) {
// // create presentation request without abstract count
// $eventUser->presentation_request_count = $presentationRequestCount;
// // save
// $eventUser->save();
// }
// }
}
$files = $request->allFiles();
$removedUsers = json_decode($input['removed_presenters'] ?? "[]", true);
$this->managePresenters($presentation, $presenters, $files, $removedUsers, $request);
}
}
else {
$validator = Validator::make($input, [
'data' => ['required', new PresentationDataRule()]
]);
if ($validator->fails() && $submissionStatus == 'Submitted')
validationErrorResponse($validator->errors());
$presentation = Presentation::find($presentationId);
if (!$presentersOnly) {
$data = json_decode($input['data'] ?? false, true);
//$writtenPaperData = ($input['written_paper_data'] ?? false) ? json_decode($input['written_paper_data'], true) : [];
$data = $this->handlePresentationFiles($request, $presentation, $data);
//$writtenPaperData = $this->handleWrittenPaperFiles($request, $presentation, $writtenPaperData);
$presentation->data = $data;
//$presentation->written_paper_data = $writtenPaperData;
$presentation->submission_status = $submissionStatus;
$presentation->save();
} else {
// managing presenters in presentation
$presenters = json_decode($input['presenters'], true);
$files = $request->allFiles();
$removedUsers = json_decode($input['removed_presenters'], true);
$this->managePresenters($presentation, $presenters, $files, $removedUsers, $request);
}
}
//send email if submitted to admins and submitter and presenters.
if ($presentation->submission_status == 'Submitted') {
if($role == 'event_submitter'){
$presentation->submission_date = date('Y-m-d H:i:s', time());
$presentation->save();
}
dispatch(new SendPresentationSubmittedMails($presentation));
}
if ($presentation->submission_status == 'Submitted') {
// update related slots
$slotRepository = new SlotRepository();
$slotRepository->updateRelatedSlots(null,$presentation);
}
return $presentation;
}
}
public function writtenPaper(Request $request)
{
$presentationId = $request->get('id');
$input = $request->input();
$role = $request->get('role');
$writtenPaperStatus = $request->get('written_paper_status', 'Draft');
// Allow both submitters and admins to edit written papers
if ($role != 'event_submitter' && $role != 'event_admin')
validationErrorResponse(['Access denied']);
if ($presentationId) {
$presentation = Presentation::find($presentationId);
$writtenPaperData = ($input['written_paper_data'] ?? false) ? json_decode($input['written_paper_data'], true) : [];
$writtenPaperData = $this->handleWrittenPaperFiles($request, $presentation, $writtenPaperData);
$presentation->written_paper_data = $writtenPaperData;
$presentation->written_paper_status = $writtenPaperStatus;
$presentation->save();
return $presentation;
}
}
public function markAsConfirmedSpeaker(EventUser $eventUser, $via = 'Abstract', $eventId): EventUser
{
if (!$eventUser->confirmed_speaker) {
$eventUser->confirmed_speaker = true;
$eventUser->speaker_added_via = $via;
if ($eventUser->confirmed_speaker) {
$lastConfirmedSpeakerOrder = EventUser::where('event_id', $eventId)
->where('confirmed_speaker', 1)
->whereNotNull('confirmed_speaker')
->max('order');
// Set the order for the new confirmed speaker
$eventUser->order = $lastConfirmedSpeakerOrder + 1;
}
$eventUser->save();
}
return $eventUser;
}
public function handleWrittenPaperFiles(Request $request, Presentation $presentation, $writtenPaperData)
{
$removedFiles = $request->get('removed_files');
$removedFiles = json_decode($removedFiles, true);
//handling uploaded files
if ($request->hasFile('written_paper_files')) {
$files = $request->file('written_paper_files');
$fileContents = [];
foreach ($files as $file) {
$fileObj = $presentation->saveFile(
$file,
null,
"{$presentation->id}/files/",
"presentation.written_paper.file",
null,
false
);
$fileContents[] = $fileObj->getFileObject();
}
$fileField = getField($writtenPaperData, 'written_paper_files');
$fileField = array_shift($fileField);
$fileFieldValue = $fileField['value'];
$fileFieldValue = array_values(array_filter(array_merge($fileFieldValue, $fileContents)));
$writtenPaperData = updateField($writtenPaperData, 'written_paper_files', 'value', $fileFieldValue);
}
//handling removed files
if (isset($removedFiles['written_paper_files'])) {
$fileIds = $removedFiles['written_paper_files'];
foreach ($fileIds as $fileId) {
$this->deleteFile($fileId);
}
}
return $writtenPaperData;
}
public function handlePresentationFiles(Request $request, Presentation $presentation, $data)
{
$removedFiles = $request->get('removed_files');
$removedFiles = json_decode($removedFiles, true);
//handling uploaded files
if ($request->hasFile('presentation_files')) {
$files = $request->file('presentation_files');
$fileContents = [];
foreach ($files as $file) {
$fileObj = $presentation->saveFile(
$file,
null,
"{$presentation->id}/files/",
"presentation.file",
null,
false
);
$fileContents[] = $fileObj->getFileObject();
}
$fileField = getField($data, 'presentation_files');
$fileField = array_shift($fileField);
$fileFieldValue = $fileField['value'];
$fileFieldValue = array_values(array_filter(array_merge($fileFieldValue, $fileContents)));
$data = updateField($data, 'presentation_files', 'value', $fileFieldValue);
}
//handling removed files
if (isset($removedFiles['presentation_files'])) {
$fileIds = $removedFiles['presentation_files'];
foreach ($fileIds as $fileId) {
$this->deleteFile($fileId);
}
}
return $data;
}
public function selectColumns(): array
{
return [
'presentations.id',
'presentations.user_id',
'presentations.event_id',
'presentations.abstract_id',
'presentations.data',
'presentations.type',
'presentations.presentation_type',
'presentations.submission_status',
'presentations.submission_date',
'presentations.written_paper_data',
'presentations.written_paper_status',
'presentations.created_at',
'presentations.updated_at',
];
}
public function applyEventScope(Builder $query, $arguments): Builder
{
if ($arguments->event) {
$query->where('presentations.event_id', '=', $arguments->event->id);
}
return $query;
}
public function applyUserScope(Builder $query, $arguments): Builder
{
if ($arguments->role == 'event_submitter') {
$query->where(function ($query) use ($arguments) {
$query->where('presentations.user_id', '=', $arguments->event_user->user_id)
->orWhereIn(
'presentations.id',
function ($query) use ($arguments) {
$query->select('presenters.presentation_id')
->from('presenters')
->where('presenters.user_id', '=', $arguments->event_user->user_id);
}
);
})->groupBy('presentations.id');
}
if ($arguments->role == 'event_admin') {
$query->leftJoin('presentation_reviews as pr', 'pr.presentation_id', '=', 'presentations.id')
->leftJoin('users as reviewers', 'reviewers.id', '=', 'pr.reviewer_id')
->addSelect([
DB::raw("
concat('[',
GROUP_CONCAT(
DISTINCT(
IF(
reviewers.id is not null,
JSON_OBJECT(
'name',
concat(reviewers.first_name, ' ', reviewers.last_name),
'email',
reviewers.email,
'status',
pr.status,
'do_not_send_emails',
reviewers.do_not_send_emails,
'cc_emails',
reviewers.cc_emails
),
NULL )
)
), ']'
) as reviewers")
])->groupBy('presentations.id');
}
if ($arguments->role == 'event_reviewer') {
$query->join('presentation_reviews as pr', function ($join) use ($arguments) {
$join->on('pr.presentation_id', '=', 'presentations.id')
->where('pr.reviewer_id', '=', authUser()->id)
->where('pr.event_id', '=', $arguments->event->id);
})->addSelect([
'pr.status as review_status'
])->groupBy('presentations.id');
}
return $query;
}
public function applyOrder(Builder $query, $arguments): Builder
{
if (!$arguments->sort)
return $query;
$columns = [
'id' => 'presentations.id',
'user_id' => 'presentations.user_id',
'event_id' => 'presentations.event_id',
'abstract_id' => 'presentations.abstract_id',
'type' => 'presentations.type',
'presentation_type' => 'presentations.presentation_type',
'submission_status' => 'presentations.submission_status',
'selection_status' => 'abstract.selection_status',
'written_paper_status' => 'presentations.written_paper_status',
'submission_date' => 'presentations.submission_date',
'created_at' => 'presentations.created_at',
'updated_at' => 'presentations.updated_at',
'presenters' => 'presenters',
'reviewers' => 'reviewers',
'submitter' => 'submitter'
];
$sorts = json_decode($arguments->sort, true);
// form settings
$formSettings = collect($arguments->event->form_settings->toArray());
// pluck all fields
$dataFields = $formSettings->pluck('field_id')->toArray();
foreach ($sorts as $sort => $method) {
if (array_key_exists($sort, $columns))
$query->orderBy($sort, $method);
// checking sort in field array
else if (in_array($sort, $dataFields)) {
$key = array_search($sort, $dataFields);
$query->orderByRaw("JSON_EXTRACT(abstract.data, '$[$key].value') $method");
}
}
//todo: add reviewer, presenter and submitter sort
return $query;
}
public function applyTab(Builder $query, $arguments): Builder
{
if (!($arguments->tab))
return $query;
// tab filter
$filter = json_decode($arguments->tab);
// filtering with reviewers assigned or not
if (isset($filter->assigned)) {
if ($filter->assigned)
$query->whereNotNull('reviewers.id');
else
$query->whereNull('reviewers.id');
}
return $query;
}
public function applyFilter(Builder $query, $arguments): Builder
{
if (!($arguments->filter))
return $query;
// for filtering
$filter = json_decode($arguments->filter);
// filter with category
$formSettings = collect($arguments->event->form_settings->toArray());
$dataFields = $formSettings->pluck('field_id')->toArray();
if ($filter->category ?? false) {
$key = array_search('category', $dataFields);
$values = $filter->category;
$query->where(function ($query) use ($values, $key) {
foreach ($values as $value) {
// $query->orWhereRaw(DB::raw("JSON_EXTRACT(abstract.data, '$[$key].value') = ?"), [$value]);
$query->orWhereJsonContains('abstract.data', [
['field_id' => 'category', 'value' => $value]
]);
}
});
}
// filter with subcategory
if ($filter->subcategory ?? false) {
$key = array_search('subcategory', $dataFields);
$values = $filter->subcategory;
$query->where(function ($query) use ($values, $key) {
foreach ($values as $value) {
//$query->whereRaw(DB::raw("JSON_EXTRACT(abstract.data, '$[$key].value') = ?"), [$value]);
$query->orWhereJsonContains('abstract.data', [
['field_id' => 'subcategory', 'value' => $value]
]);
}
});
}
// filter with company name
if ($filter->company ?? false) {
$values = $filter->company;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere('presenters.company', '=', $value);
}
});
}
// filter with submission status
if ($filter->submission_status ?? false) {
$values = $filter->submission_status;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere('presentations.submission_status', '=', $value);
}
});
}
// filter with written paper status
if ($filter->written_paper_status ?? false) {
$values = $filter->written_paper_status;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere('presentations.written_paper_status', '=', $value);
if ($value === 'draft') {
$query->orWhereNull('presentations.written_paper_status')
->orWhere('presentations.written_paper_status', '=', '');
}
}
});
}
// assign status
if (isset($filter->assigned_status)) {
if (count($filter->assigned_status) == 1 && $filter->assigned_status[0] == "Assigned") {
$query->where('pr.presentation_id', '>', 0);
}
else if (count($filter->assigned_status) == 1 && $filter->assigned_status[0] == "Un-Assigned") {
$query->whereNull('pr.presentation_id');
}
}
// filter with presentation type
if ($filter->presentation_type ?? false) {
$values = $filter->presentation_type;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere('presentations.presentation_type', '=', $value);
}
});
}
// filter with Abstract ID
if ($filter->abstractId ?? false) {
$values = $filter->abstractId;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
if ($value == 'Not Set') {
$query->orWhere('presentations.abstract_id', '=', null);
}
else {
$query->orWhere('presentations.abstract_id', '=', $value);
}
}
});
}
// filter with selection Status
if ($filter->selection_status ?? false) {
$values = $filter->selection_status;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
if ($value == 'Not Set') {
$query->orWhere('abstract.selection_status', '=', null);
}
else {
$query->orWhere('abstract.selection_status', '=', $value);
}
}
});
}
// filter with presenter name
if ($filter->presenter ?? false) {
$values = $filter->presenter;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere(DB::raw("CONCAT(presenters.first_name, ' ', presenters.last_name)"), '=', $value);
}
});
}
// filter with submitter name
if ($filter->submitter ?? false) {
$values = $filter->submitter;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere(DB::raw("CONCAT(user.first_name, ' ', user.last_name)"), '=', $value);
}
});
}
// filter with Assigned Reviewer Name
if ($filter->reviewer ?? false) {
$values = $filter->reviewer;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere(DB::raw("CONCAT(reviewers.first_name, ' ', reviewers.last_name)"), '=', $value);
}
});
}
// filter with Assigned Reviewer status
if ($filter->reviewer_assigned_status ?? false) {
$values = $filter->reviewer_assigned_status;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere('pr.status', '=', $value);
}
});
}
// filter submission date
if (isset($filter->start_date) || isset($filter->end_date)) {
$startDate = isset($filter->start_date) ? $filter->start_date : null;
$endDate = isset($filter->end_date) ? $filter->end_date : null;
if (!$endDate) {
$query->where(function ($query) use ($startDate) {
$query->orWhereDate(DB::raw('DATE(presentations.submission_date)'), '=', $startDate);
});
} else if (!$startDate) {
$query->where(function ($query) use ($endDate) {
$query->orWhereDate(DB::raw('DATE(presentations.submission_date)'), '=', $endDate);
});
} else {
$query->where(function ($query) use ($startDate, $endDate) {
$query->orWhereBetween('presentations.submission_date', [$startDate, $endDate]);
$query->orWhereDate(DB::raw('DATE(presentations.submission_date)'), '=', $startDate);
});
}
}
// filter sessions
if ($filter->sessions ?? false) {
$values = $filter->sessions;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere('session.title', '=', $value);
}
});
}
// filter slots
if ($filter->slots ?? false) {
$values = $filter->slots;
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orWhere('slot.title', '=', $value);
}
});
}
return $query;
}
public function applySearch(Builder $query, $arguments): Builder
{
if ($arguments->search) {
$columns = [
'id' => 'presentations.id',
'abstract_id' => 'presentations.abstract_id',
'submission_status' => 'presentations.submission_status'
];
$search = strtolower($arguments->search);
$query->where(function ($query) use ($arguments, $search, $columns) {
foreach ($columns as $column) {
$query->orWhere(DB::raw("lower($column)"), 'like', "%{$search}%");
}
//user name
$query->orWhereRaw(DB::raw("lower(CONCAT(user.first_name, ' ', user.last_name)) like ?"), ["%{$search}%"]);
// presenter name
$query->orWhereRaw(DB::raw("lower(CONCAT(presenters.first_name, ' ', presenters.last_name)) like ?"), ["%{$search}%"]);
// presenter company
$query->orWhereRaw(DB::raw("lower(presenters.company) like ?"), ["%{$search}%"]);
// presentation abstract category search
// form settings
$formSettings = collect($arguments->event->form_settings->toArray());
// pluck all fields
$dataFields = $formSettings->pluck('field_id')->toArray();
// key
$key = array_search('category', $dataFields);
//$query->orWhereRaw(DB::raw("lower(JSON_EXTRACT(abstract.data, '$[$key].value')) like ? "), ["%{$search}%"]);
$query->orWhereRaw(DB::raw("lower(JSON_EXTRACT(abstract.data, '$[*].value')) like ? "), ["%{$search}%"]);
// user selection status
$query->orWhereRaw(DB::raw("lower(abstract.selection_status) like ?"), ["%{$search}%"]);
// session title search
$query->orWhereRaw(DB::raw("lower(session.title) like ?"), ["%{$search}%"]);
// slot title search
$query->orWhereRaw(DB::raw("lower(slot.title) like ?"), ["%{$search}%"]);
$filter = json_decode($arguments->filter);
if (isset($filter->assigned)) {
if ($filter->assigned) {
$query->orWhereRaw(DB::raw("lower(CONCAT(reviewers.first_name, ' ', reviewers.last_name)) like ?"), ["%{$search}%"]);
$query->orWhereRaw(DB::raw("lower(pr.status) like ?"), ["%{$search}%"]);
}
}
});
}
return $query;
}
public function applyScope(Builder $query, $arguments): Builder
{
$this->applyEventScope($query, $arguments);
$this->applyUserScope($query, $arguments);
$this->applyOrder($query, $arguments);
$this->applyTab($query, $arguments);
$this->applyFilter($query, $arguments);
$this->applySearch($query, $arguments);
return $query;
}
/**
* @throws Exception
*/
public function scope($arguments, $callback = null): Builder
{
$query = $this->query()
->select($this->selectColumns());
//joining user to presentation
$query->leftJoin('users as user', 'user.id', '=', 'presentations.user_id');
$query->addSelect([DB::raw(
"JSON_OBJECT(
'id',user.id,
'first_name',user.first_name,
'last_name',user.last_name,
'do_not_send_emails',user.do_not_send_emails,
'cc_emails',user.cc_emails,
'email',user.email
) as user, concat(user.first_name, ' ', user.last_name) as submitter"
)]);
//joining abstract to presentation
$query->leftJoin('abstracts as abstract', 'abstract.id', '=', 'presentations.abstract_id');
$query->addSelect([DB::raw(
"JSON_OBJECT(
'id',abstract.id,
'data',abstract.data,
'submission_status',abstract.submission_status,
'selection_status',abstract.selection_status
) as abstract"
)
]);
//joining slots to presentation
$query->leftJoin('slots as slot', 'slot.presentation_id', '=', 'presentations.id')->
leftJoin('sessions as session', 'slot.session_id', '=', 'session.id')
->addSelect([
DB::raw("
JSON_ARRAYAGG(
JSON_OBJECT(
'title', slot.title,
'slot_id', slot.id,
'session_id', session.id,
'session_title', session.title
))
AS slotsArray")
])
->groupBy('presentations.id');
//joining presenters to presentation
$query->leftJoin('presenters as p', 'p.presentation_id', '=', 'presentations.id')
->leftJoin('users as presenters', 'presenters.id', '=', 'p.user_id')
->addSelect([
DB::raw("GROUP_CONCAT(DISTINCT(concat(presenters.first_name, ' ', presenters.last_name))) as presenters")
])->addSelect([
DB::raw("
concat('[',
GROUP_CONCAT(
DISTINCT(
IF(
presenters.id is not null,
JSON_OBJECT(
'name',
concat(presenters.first_name, ' ', presenters.last_name),
'company',
presenters.company,
'do_not_send_emails',
presenters.do_not_send_emails,
'cc_emails',
presenters.cc_emails,
'email',
presenters.email
),
NULL )
)
), ']'
) as presentersArray")
])->groupBy('presentations.id');
//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);
}
/**
* @throws Exception
*/
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 fetchPresentation($id, $eventId = null)
{
if (!$eventId)
return Presentation::with(['user', 'abstract', 'presenters', 'reviews.reviewer'])->find($id);
else
return Presentation::with(['user', 'abstract', 'presenters', 'reviews.reviewer'])->where('event_id', '=', $eventId)
->find($id);
}
public function getCommentRepository(): PresentationCommentRepository
{
return new PresentationCommentRepository();
}
public function managePresenters(Presentation $presentation, $presenters, $files, $removedUsers = [], $request): Presentation
{
$this->removerPresentersFromPresentation($presentation, $removedUsers);
$userRepository = new UserRepository();
//add/edit presenters in the presentation
foreach ($presenters as $key => $person) {
$user = User::find($person['id'] ?? null);
$isEdit = true;
if (!$user) {
$validator = Validator::make($person, [
'first_name' => ['required', 'string', 'max:255'],
'last_name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
]);
if ($validator->fails())
validationErrorResponse($validator->errors());
$user = new User();
$user->password = Hash::make(randomStringGenerator(8));
$user->valid = true;
$user->email = $person['email'];
$user->created_by = authUser()->id;
$user->new_user = true;
$user->save();
$user->assignRole('user');
$isEdit = false;
} else {
$user->new_user = false;
$user->save();
}
$eventUser = getEventUser($presentation->event->id, $user->id);
if (!$eventUser) {
$eventUser = $userRepository->attachUserToEvent($presentation->event, $user, 'event_submitter');
// type
$eventUser->type = "strategic";
// user added via
$eventUser->user_added_via = "Presentation";
// save
$eventUser->save();
}
if ($presentation->abstract_id) {
$abstract = Abstracts::find($presentation->abstract_id);
$abstractPresenters = $abstract->users('abstract_presenter')->pluck('id');
$speakerType = $abstractPresenters->contains($user->id) ? 'Abstract' : 'Presentation';
} else {
$speakerType = 'Presentation';
}
$this->markAsConfirmedSpeaker($eventUser, $speakerType, $presentation->event->id);
unset($person['pivot']);
unset($person['id']);
unset($person['checkboxes']);
unset($person['login_email_count']);
unset($person['valid']);
unset($person['forgot_password']);
unset($person['avatar']);
unset($person['company_logo']);
$user->fill($person);
//keep changes field lists
$changes = $user->getDirty();
// Track modification if users table data changed
if (!empty($changes)) {
$userRepository->trackUserModification($user, authUser()->id, $presentation->event_id);
$userRepository->trackVipMarkedBy($user, $changes);
}
$user->save();
$removeAvatar = false;
$removeCompanyLogo = false;
$removeUserSecondaryImage = false;
if (isset($request->get('avatar')[$key])) {
if ($request->get('avatar')[$key] === "null" && $user->avatar) {
$removeAvatar = true;
}
}
if (isset($request->get('company_logo')[$key])) {
if ($request->get('company_logo')[$key] === "null" && $user->company_logo) {
$removeCompanyLogo = true;
}
}
if (isset($request->get('user_secondary_image')[$key])) {
if ($request->get('user_secondary_image')[$key] === "null" && $user->user_secondary_image) {
$removeUserSecondaryImage = true;
}
}
if ($isEdit) {
// image files
$imageFiles = [
'avatar' => isset($files['avatar'][$key]) ? $files['avatar'][$key] : null,
'company_logo' => isset($files['company_logo'][$key]) ? $files['company_logo'][$key] : null,
];
// Get the changed fields using the common function
$changeFields = $userRepository->getChangedFields($changes, $imageFiles, $removeAvatar, $removeCompanyLogo);
// verification changes for change fields
if ($changeFields) {
// published session status changing
$userRepository->publishedSessionStatusUpdate($user);
$userRepository->userVerificationFieldsChanges($changeFields, $user);
}
}
$presentersId = $presentation->presenters()->pluck('user_id')->toArray();
if (!in_array($user->id, $presentersId)) {
$presentation->presenters()->attach($user, ['event_id' => $presentation->event_id]);
// event
$event = $request->get('event');
// general settings
$generalSettings = $event->general_settings;
// terms and condition
$termsAndConditionStatus = $generalSettings['speaker_terms_prefill']['terms_and_condition_status'];
if (!$termsAndConditionStatus) {
dispatch(new SendSpeakerTerms([$eventUser]));
}
}
$userRepository->removeUserImages($user, $removeAvatar, $removeCompanyLogo, $removeUserSecondaryImage);
//handling user images
$userFiles = [];
if (isset($files['avatar'][$key]))
$userFiles['avatar'] = $files['avatar'][$key];
if (isset($files['company_logo'][$key]))
$userFiles['company_logo'] = $files['company_logo'][$key];
if (isset($files['user_secondary_image'][$key]))
$userFiles['user_secondary_image'] = $files['user_secondary_image'][$key];
$userRepository->updateUserImages($userFiles, $user, authUser()->id, $presentation->event_id);
}
if ($presentation->submission_status == 'Submitted'){
// update related slots
$slotRepository = new SlotRepository();
$slotRepository->updateRelatedSlots(null,$presentation);
}
return $presentation;
}
// adding selected files in zip file
public function addingToZip(object $presentations, Request $request)
{
// Delete older files
$this->deleteOlderZipFiles();
// Create a new ZipArchive instance and open or create the ZIP file
$zip = new ZipArchive;
$zipName = 'presentationFiles' . time() . '.zip';
$zip->open($zipName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
// Get the selected presentation type from the request
$presentationType = $request['presentation_type'];
foreach ($presentations as $presentation) {
$this->addPresentationToZip($presentation, $zip, $presentationType);
// Reset the file name for the next iteration
$this->fileName = null;
}
// Close the ZIP archive
$zip->close();
// Set the file path
$filepath = public_path($zipName);
if (file_exists($filepath)) {
// maximum size
$maximumSizeInMB = 50;
// Check if the file size is too large
$fileSize = filesize($zipName);
if ($fileSize > $maximumSizeInMB * 1024 * 1024) {
// Handle large file size
return $this->handleLargeFileSize($zipName, $request);
}
}
// Return a response with the ZIP file for download or an error message
return file_exists($filepath)
? $this->returnZipFileResponse($filepath, $zipName)
: response(['status' => false, 'message' => "File not found"]);
}
public function deleteOlderZipFiles()
{
// public folder path
$publicPath = public_path();
// Get a list of all files in the public folder
$publicFiles = scandir($publicPath);
// delete zip files older than 1 hour
$expirationTime = now()->subHour()->timestamp;
foreach ($publicFiles as $file) {
$filePath = $publicPath . '/' . $file;
if (is_file($filePath) && pathinfo($filePath, PATHINFO_EXTENSION) === 'zip') {
$fileModificationTime = filemtime($filePath);
if ($fileModificationTime < $expirationTime) {
// Delete the zip file
unlink($filePath);
}
}
}
}
private function addPresentationToZip($presentation, $zip, $presentationType)
{
// Extract and format submitter name
$submitterName = '';
if ($presentation->user_id) {
$submitter = User::whereId($presentation->user_id)->first();
if ($submitter) {
$submitterName = removeSpecialCharacters(substr($submitter->name, 0, 30));
$submitterCompany = removeSpecialCharacters(substr($submitter->company, 0, 30));
$this->fileName = $submitterName . ($submitterCompany ? '_' . $submitterCompany : '');
}
}
// Zip presentation files if available
if ($presentation->data && $this->shouldZipPresentationFiles($presentationType)) {
$presentationData = json_decode(json_encode($presentation->data), true);
$this->filesToZip($presentationData, 'presentation_files', $zip, $presentation);
}
// Zip written paper files if available
if ($presentation->written_paper_data && $this->shouldZipWrittenPaperFiles($presentationType)) {
$writtenPaperData = json_decode(json_encode($presentation->written_paper_data), true);
$this->filesToZip($writtenPaperData, 'written_paper_files', $zip, $presentation);
}
}
private function shouldZipPresentationFiles($presentationType)
{
return array_search('Presentation Files', array_column($presentationType['option'], 'value')) !== false;
}
private function shouldZipWrittenPaperFiles($presentationType)
{
return array_search('Written Paper Files', array_column($presentationType['option'], 'value')) !== false;
}
private function handleLargeFileSize($zipName, $request)
{
// Generate a temporary URL for the file with an expiration time
$expiration = now()->addHours(1);
$temporaryUrl = URL::temporarySignedRoute(
'downloadPresentationZip',
$expiration,
['filename' => $zipName]
);
// Send an email to the user with the temporary download link
$userEmail = $request->user()->email;
// event
$event = $request->get('event');
// send email to user with download link
$this->sendPresentationDownloadLinkEmail($event, $userEmail, $temporaryUrl);
// Return the temporary URL to the user
return response()->json([
'status' => true,
'temporary_url' => urldecode($temporaryUrl),
'message' => "File is too large for direct download.
We've emailed you a download link, Please use that link to download the file.
",
]);
}
public function sendPresentationDownloadLinkEmail($event, $userEmail, $temporaryUrl)
{
SendPresentationDownloadLinkEmail::dispatch($event, $userEmail, $temporaryUrl);
}
private function returnZipFileResponse($filepath, $zipName)
{
return response()->download($filepath, $zipName, ['Content-Type: application/zip', 'Content-Length: ' . filesize($filepath)])->deleteFileAfterSend(true);
}
public function filesToZip($data, $field, $zip, $presentation)
{
// attachment field
$attachmentFields = array_values(
array_filter(
$data,
fn($presentationFile) => $presentationFile['field_id'] == $field
)
);
if (isset($attachmentFields[0]['value']) && is_array($attachmentFields[0]['value'])) {
foreach ($attachmentFields[0]['value'] as $attachmentField) {
if (isset($attachmentField['file_id'])) {
$file = \App\Models\File::whereId($attachmentField['file_id'])->first();
if ($file) {
// file path
$filePath = $file->filepath . $file->save_name;
$filePath = storage_path() . "/app/" . $filePath;
$savedFileName = $file->filename;
if (strlen($savedFileName) > 30) {
$savedFileName = substr($savedFileName, 0, 30);
$savedFileName = removeSpecialCharacters($savedFileName);
}
$name = $this->fileName . '_' . $savedFileName . '_' . $presentation->id . '.' . $file->extension;
if (file_exists($filePath)) {
// add file to zip
$zip->addFile($filePath, $name);
}
}
}
}
}
}
public function removerPresentersFromPresentation(Presentation $presentation, $users)
{
foreach ($users as $user) {
if ($user) {
$presentationUser = getPresentationPresenter($presentation->id, $user);
if ($presentationUser) {
$presentationUser->delete();
}
}
}
}
public function assignReviewer(Presentation $presentation, $reviewerId): PresentationReview
{
$reviewerEventUser = getEventUser($presentation->event_id, $reviewerId);
if (!$reviewerEventUser->hasRole('event_reviewer'))
validationErrorResponse(['User not a reviewer']);
$review = PresentationReview::wherePresentationId($presentation->id)
->whereReviewerId($reviewerId)
->first();
if ($review)
validationErrorResponse(['Reviewer already assigned']);
$review = new PresentationReview([
'presentation_id' => $presentation->id,
'event_id' => $presentation->event->id,
'reviewer_id' => $reviewerId,
'status' => 'Under Review',
]);
$review->save();
$review->refresh();
// disable mail for Egyps
// requirement from the client
$disableSlug = 'egyps-2023';
if ($review->presentation->event->slug_name !== $disableSlug) {
//mail to reviewer
dispatch(new SendAssignReviewerMail($review));
}
return $review;
}
public function removeReviewer(Presentation $presentation, $reviewerId)
{
$review = PresentationReview::wherePresentationId($presentation->id)
->whereReviewerId($reviewerId)
->first();
if (!$review)
validationErrorResponse(['Reviewer not found']);
$review->delete();
return true;
}
// remove presenter from presentation
public function removePresenter(Presentation $presentation, $presenterId)
{
$presenter = Presenter::wherePresentationId($presentation->id)
->whereUserId($presenterId)
->first();
if (!$presenter)
validationErrorResponse(['Presenter not found']);
$presenter->delete();
// update related slots
if ($presentation->submission_status == 'Submitted') {
$slotRepository = new SlotRepository();
$slotRepository->updateRelatedSlots(null,$presentation);
}
return true;
}
public function handleWrittenPaperEditRequest(Presentation $presentation, $status): Presentation
{
switch ($status) {
case 'change':
$status = $presentation->written_paper_status === 'Draft' ? 'Submitted' : 'Draft';
$presentation->written_paper_status = $status;
$presentation->save();
break;
default:
validationErrorResponse(['Invalid status']);
}
return $presentation;
}
public function handleEditRequest(Presentation $presentation, $status)
{
switch ($status) {
case 'accept':
$presentation->submission_status = 'Draft';
$presentation->edit_request = false;
$presentation->save();
$generalSettings = $presentation->event->general_settings;
$requestToEdit = $generalSettings['presentation_templates']['request_to_edit'];
if ($requestToEdit) {
//mail to submitter
dispatch(new SendPresentationEditStatusChangeMail($presentation, $status));
}
break;
case 'reject':
$presentation->edit_request = false;
$presentation->save();
//mail to submitter
dispatch(new SendPresentationEditStatusChangeMail($presentation, $status));
break;
case 'change':
$status = $presentation->submission_status === 'Draft' ? 'Submitted' : 'Draft';
if ($status == "Submitted") {
$data = $presentation->data;
if (!$data)
validationErrorResponse(['Required fields are missing']);
$data = $data->toArray();
$fileField = getField($data, 'presentation_files')[0];
$titleField = getField($data, 'title')[0];
if (empty($fileField['value']) && empty($titleField['value'])) {
validationErrorResponse(['Required fields are missing']);
}
}
$presentation->submission_status = $status;
$presentation->edit_request = false;
$presentation->save();
//mail to submitter
dispatch(new SendPresentationStatusChangeMail($presentation));
break;
default:
validationErrorResponse(['Invalid status']);
}
return $presentation;
}
public function handleReviewerApprovedRequest($comment, Presentation $presentation)
{
$user = authUser();
$presentationReview = PresentationReview::wherePresentationId($presentation->id)
->whereReviewerId($user->id)
->first();
if (!$presentationReview)
return response([
'status' => false,
'message' => 'reviewer not found'
]);
$presentationReview->status = "Approved";
$presentationReview->approved_date = date('Y-m-d H:i:s', time());
$presentationReview->comment = $comment;
$presentationReview->save();
//mail to admins
dispatch(new SendReviewerApprovedMail($presentationReview));
return $this->fetchPresentation($presentation->id, $presentation->event->id);
}
public function getPresentationCount(Request $request): array
{
$event = $request->get('event');
$eventPresentations = Presentation::whereEventId($event->id)
->get();
$eventPresentationsCount = $eventPresentations->count();
$assignedPresentations = Presentation::where('presentations.event_id', '=', $event->id)
->join('presentation_reviews as pr', 'pr.presentation_id', '=', 'presentations.id')
->groupBy('presentations.id')
->get();
$assignedPresentationsCount = $assignedPresentations->count();
$unAssignedCount = $eventPresentationsCount - $assignedPresentationsCount;
$eventPresentationsSubmitted = Presentation::whereEventId($event->id)
->where('submission_status', '=', 'Submitted')->get();
$eventPresentationsSubmittedCount = $eventPresentationsSubmitted->count();
$eventPresentationsDraftCount = $eventPresentationsCount - $eventPresentationsSubmittedCount;
return [
'assigned' => $assignedPresentationsCount,
'unassigned' => $unAssignedCount,
'submitted' => $eventPresentationsSubmittedCount,
'draft' => $eventPresentationsDraftCount,
'total' => $eventPresentationsCount
];
}
public function deletePresentation(Presentation $presentation): bool
{
$slotCount = Slot::wherePresentationId($presentation->id)
->count();
if ($slotCount > 0) {
return false;
}
//delete presentation comments
$presentationComments = PresentationComment::wherePresentationId($presentation->id)
->get();
foreach ($presentationComments as $presentationComment) {
$this->getCommentRepository()->deletePresentationComment($presentationComment);
}
//detach presenters from presentation
$presentation->presenters()->detach();
//delete presentation reviews
$presentation->reviews()->delete();
//delete files in presentation
$data = $presentation->data;
if ($data) {
$presentationFiles = getField($data, 'presentation_files')[0];
$files = $presentationFiles['value'];
if (is_array($files))
foreach ($files as $file) {
$fileId = $file['file_id'];
$this->deleteFile($fileId);
}
}
//delete directory
Storage::deleteDirectory('private/media/presentations/' . $presentation->id);
if ($presentation->abstract_id) {
Abstracts::whereId($presentation->abstract_id)
->update([
'presentation_invite' => null
]);
}
$presentation->delete();
return true;
}
/**
* getScheduleMailData()
*
* @return array
*/
public function getScheduleMailData(object $data): array
{
$filter = json_decode($data->filter, 1);
$to = [];
$email = [];
// storing recipients
if (isset($filter['recipients'])) {
foreach ($filter['recipients'] as $recipients) {
$to[] = $recipients['email'];
}
}
$formatedFilter = [];
// getting all users if there is no user selected
if (!isset($filter['users']) || count($filter['users']) <= 0) {
$filter['users'] = $this->getAllUsersByEmailType('Presentation');
}
foreach ($this->presentaionFields as $fields) {
$arrayColumn = (isset($filter[$fields])) ? $filter[$fields] : [];
$formatedFilter[$fields] = array_column($arrayColumn, 'value');
}
$event = Event::find($data->event_id);
$request = new Request();
$request->replace([
'paging' => 'all',
'sort' => '{}',
'filter' => json_encode($formatedFilter),
'role' => 'event_admin',
'event' => $event,
]);
$result = $this->listing($request, false);
$eventRepo = new EventRepository();
//getting users emails
foreach ($result as $key => $res) {
$body = $this->replaceMacros($res, $data, $event->event_name);
$bcc = [];
foreach ($filter['users'] as $user) {
switch ($user['value']) {
case "Submitters":
$mails = getUsersEmails([json_decode(json_encode($res->user))]);
$bcc = [...$bcc, ...$mails['emails']];
break;
case "Presenters":
if ($res->presentersArray)
$mails = getUsersEmails(json_decode(json_encode($res->presentersArray)));
$bcc = [...$bcc, ...$mails['emails']];
break;
case "Reviewers":
if ($res->reviewers)
$mails = getUsersEmails(json_decode(json_encode($res->reviewers)));
$bcc = [...$bcc, ...$mails['emails']];
break;
}
}
$bcc = array_unique($bcc);
$email[] = [
'to' => $to,
'bcc' => $bcc,
'subject' => $data->subject,
'body' => $body,
'attachments' => $data->attachments,
'event' => $event,
'event_id' => $data->event_id,
'id' => $data->id,
];
}
return $email;
}
/**
* Replace macros
*
* @return string
*/
public function replaceMacros($row, object $data, string $event_name): string
{
$variables = config('schedule_mail_settings')->Presentation->variables;
$submittedStatus = $row->submission_status;
$writtenPaperStatus = $row->written_paper_status;
$submittedDate = $row->submission_date;
$presentationId = $row->id;
$body = $data->body;
$body = Str::replace("{submission_status}", $submittedStatus, $body);
$body = Str::replace("{written_paper_status}", $writtenPaperStatus, $body);
$body = Str::replace("{presentation_id}", $presentationId, $body);
$body = Str::replace("{submission_date}", $submittedDate, $body);
$body = Str::replace("{event_name}", $event_name, $body);
return $body;
}
}
Directory Contents
Dirs: 0 × Files: 17