File: /home/imensosw/public_html/mpl.imenso.co/app/Models/Tour.php
<?php
namespace App\Models;
use App\TourManager\Warning\Collection\WarningCollection;
use App\TourManager\Warning\TourAnnounceWarning;
use App\TourManager\Warning\TourPublishWarning;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Facades\Image as ImageLibrary;
use Laravel\Scout\Searchable;
class Tour extends Model
{
use SoftDeletes, Searchable;
protected $fillable = [
'name',
'description',
'status_id',
];
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
public function events($announced_only = false)
{
$event_ids = DB::table('tour_events')
->leftJoin('events', 'events.id', 'tour_events.event_id')
->where('tour_id', $this->id)
->orderBy('events.event_at')
->get();
$events = new Collection;
$temp_event_count = 0;
if ($event_ids->count() > 0) {
foreach ($event_ids as $id) {
if ($id->event_id != 0) {
if (Event::where('id', $id->event_id)->count() > 0) {
$event = Event::findOrFail($id->event_id);
if (! $announced_only || $announced_only && $event->status_id == 3) {
$events->push($event);
}
}
} else {
$temp_event = new Event;
$temp_event->id = 't'.$temp_event_count;
$temp_event->tmp_id = 't'.$temp_event_count;
$temp_event->venue_name = $id->venue_name;
$temp_event->venue_postcode = $id->venue_postcode;
$temp_event->venue_country = $id->venue_country;
$temp_event->lat = $id->lat;
$temp_event->lng = $id->lng;
$temp_event->start_at = $id->start_at;
$temp_event->event_at = $id->start_at;
$events->push($temp_event);
$temp_event_count++;
}
}
}
return $events;
}
public function isFutureTour()
{
//If it's a plan, use the planned dates instead of real events to work out future/past
if ($this->status->id == 3) {
if ($this->plannedDates()->count() > 0) {
foreach ($this->plannedDates as $dates) {
if (Carbon::now()->lte(Carbon::parse($dates->date_at))) {
return true;
}
}
} else {
//Assume that a tour with no planned dates yet is for the future
return true;
}
} else {
if ($this->events()->count() > 0) {
foreach ($this->events() as $event) {
if (Carbon::now()->lte(Carbon::parse($event->event_at))) {
return true;
}
}
} else {
//Assume that a tour with no events yet is for the future
return true;
}
}
return false;
}
public function artists()
{
$artist_ids = DB::table('tour_artists')->where('tour_id', $this->id)->orderBy('orderby')->get();
$artists = new Collection;
$temp_artist_count = 0;
foreach ($artist_ids as $id) {
if ($id->artist_id != 0) {
$artist = User::findOrFail($id->artist_id);
$artist->role = $id->slot_type_id;
$artists->push($artist);
} else {
$temp_artist = new User;
$temp_artist->id = 't'.$temp_artist_count;
$temp_artist->tmp_id = 't'.$temp_artist_count;
$temp_artist->artist_name = $id->artist_name;
$temp_artist->role = $id->slot_type_id;
$temp_artist->created_at = \Carbon\Carbon::parse($id->created_at);
$artists->push($temp_artist);
$temp_artist_count++;
}
}
return $artists;
}
public function headliner()
{
if ($this->artists()->where('slot_type_id', 1)->count() > 0) {
return $this->artists()->where('slot_type_id', 1)->first();
} elseif ($this->artists()->count() > 0) {
return $this->artists()->first();
} else {
return;
}
}
public function venues($announced_only = true)
{
$venues = new Collection;
foreach ($this->events($announced_only) as $event) {
if ($event->id == 0) {
$venues->push($event);
} else {
$venues->push($event->venue);
}
}
// dd($venues);
return $venues;
}
public function creator()
{
return $this->belongsTo(\App\Models\User::class, 'creator_id');
}
public function comments()
{
return $this->morphMany(\App\Models\Comment::class, 'commentable');
}
public function status()
{
return $this->belongsTo(\App\Models\TourStatus::class, 'status_id');
}
public function images()
{
return $this->morphMany(\App\Models\Image::class, 'imageable');
}
public static function addNew($data)
{
$tour = self::create($data);
$event_ids = explode(',', $data['event_ids']);
$artist_ids = explode(',', $data['artist_ids']);
$events = Event::whereIn('id', $event_ids)->get();
foreach ($event_ids as $id) {
if (strpos($id, 't') !== false) {
$tmp_event = new Event;
$tmp_event->id = 0;
$tmp_event->tmp_id = $id;
$tmp_event->venue_name = $data['temp_event_venue_name_'.$id];
$tmp_event->venue_postcode = $data['temp_event_venue_postcode_'.$id];
$tmp_event->venue_country = $data['temp_event_venue_country_'.$id];
$tmp_event->start_at = \Carbon\Carbon::createFromFormat('d/m/Y H:i', $data['temp_event_start_date_'.$id].' '.$data['temp_event_start_time_'.$id]);
$tmp_event->end_at = \Carbon\Carbon::createFromFormat('d/m/Y H:i', $data['temp_event_end_date_'.$id].' '.$data['temp_event_end_time_'.$id]);
$events->push($tmp_event);
}
}
$order = 0;
foreach ($artist_ids as $artist_id) {
if (! strstr($artist_id, 't')) {
$artist = User::where('id', $artist_id)->firstOrFail();
$tour->addArtist($artist, TourSlotType::findOrFail($data['artist_type'][$artist_id.':'.$artist->created_at->timestamp]), $order);
} else {
$temp_artist = new User();
$temp_artist->id = 0;
$temp_artist->artist_name = $data['temp_artist_'.$artist_id];
$tour->addArtist($temp_artist, TourSlotType::findOrFail($data['artist_type'][$artist_id]), $order);
}
$order += 10;
}
foreach ($events as $event) {
$tour->addEvent($event);
}
if (isset($data['artwork'])) {
$tour->addArtwork($data['artwork']);
}
$tour->setCreator(Auth::user());
$tour->changeStatus(TourStatus::findOrFail($data['status_id']));
return $tour;
}
public function edit($data)
{
$this->updateName($data['name']);
$this->updateDescription($data['description']);
if (isset($data['artwork'])) {
$this->addArtwork($data['artwork']);
}
$event_ids = explode(',', $data['event_ids']);
$artist_ids = explode(',', $data['artist_ids']);
$this->removeArtists();
$this->removeEvents();
$events = Event::whereIn('id', $event_ids)->get();
$order = 0;
foreach ($artist_ids as $artist_id) {
if (! strstr($artist_id, 't')) {
$artist = User::find($artist_id);
$this->addArtist(User::find($artist_id), TourSlotType::findOrFail($data['artist_type'][$artist_id.':'.$artist->created_at->timestamp]), $order);
} else {
$temp_artist = new User();
$temp_artist->id = 0;
$temp_artist->artist_name = $data['temp_artist_'.$artist_id];
$this->addArtist($temp_artist, TourSlotType::findOrFail($data['artist_type'][$artist_id]), $order);
}
$order += 10;
}
foreach ($event_ids as $event_id) {
if (strstr($event_id, 't')) {
$tmp_event = new Event;
$tmp_event->id = 0;
$tmp_event->tmp_id = $event_id;
$tmp_event->venue_name = $data['temp_event_venue_name_'.$event_id];
$tmp_event->venue_postcode = $data['temp_event_venue_postcode_'.$event_id];
$tmp_event->venue_country = $data['temp_event_venue_country_'.$event_id];
$tmp_event->start_at = \Carbon\Carbon::createFromFormat('d/m/Y H:i', $data['temp_event_start_date_'.$event_id].' '.$data['temp_event_start_time_'.$event_id]);
$tmp_event->end_at = \Carbon\Carbon::createFromFormat('d/m/Y H:i', $data['temp_event_end_date_'.$event_id].' '.$data['temp_event_end_time_'.$event_id]);
$events->push($tmp_event);
}
}
foreach ($events as $event) {
$this->addEvent($event);
}
if (isset($data['status_id']) && !empty($data['status_id']) && $data['status_id'] != $this->status->id) {
$this->changeStatus(TourStatus::findOrFail($data['status_id']));
}
$this->save();
}
public function changeStatus(TourStatus $status)
{
$this->status_id = $status->id;
$this->save();
}
public function addArtist(User $artist, TourSlotType $slot_type, $order = 0)
{
$now = new \Carbon\Carbon;
$data = [
'tour_id' => $this->id,
'artist_id' => $artist->id,
'slot_type_id' => $slot_type->id,
'orderby' => $order,
'created_at' => $now,
'updated_at' => $now,
];
if ($artist->id == 0) {
$data['artist_name'] = $artist->artist_name;
}
DB::table('tour_artists')->insert($data);
}
public function addEvent(Event $event)
{
if ($this->events()->where('id', $event->id)->count() > 0) {
return;
}
$now = new \Carbon\Carbon;
$data = [
'tour_id' => $this->id,
'event_id' => $event->id,
'created_at' => $now,
'updated_at' => $now,
];
if ($event->id == 0) {
$data['venue_name'] = $event->venue_name;
$data['venue_postcode'] = $event->venue_postcode;
$data['venue_country'] = $event->venue_country;
$data['start_at'] = $event->start_at;
$data['end_at'] = $event->end_at;
$country = Country::findOrFail($event->venue_country);
$query = urlencode($event->venue_postcode.', '.$country->iso_code);
$endpoint = 'http://api.opencagedata.com/geocode/v1/json?q='.$query.'&key='.config('services.opencagedata.api_key');
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
$loc_data = json_decode($response);
if ($loc_data->status->code == 200) {
$data['lat'] = $loc_data->results[0]->geometry->lat;
$data['lng'] = $loc_data->results[0]->geometry->lng;
}
}
DB::table('tour_events')->insert($data);
}
public function removeArtists()
{
DB::table('tour_events')->where('tour_id', $this->id)->delete();
}
public function removeEvents()
{
DB::table('tour_artists')->where('tour_id', $this->id)->delete();
}
public function addArtwork(UploadedFile $image)
{
$filename = $this->id.'-'.time().'-tour.'.$image->getClientOriginalExtension();
$web_location = 'tour/'.$filename;
$processed_image = ImageLibrary::make($image->getRealPath());
$processed_image->resize(1920, 1920, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
$save = $processed_image->save();
Storage::disk('s3')->put($web_location, $save->__toString());
$this->deleteImage(17);
$this->setImage(17, $web_location);
}
public function getPoster()
{
return $this->image(17);
}
public function image($image_type_id = 0)
{
if ($this->images()->where('type_id', $image_type_id)->count() > 0) {
return $this->images()->where('type_id', $image_type_id)->first();
} else {
$image = new Image;
$image->src = ImageType::findOrFail($image_type_id)->default_image;
return $image;
}
}
public function deleteImage($type_id)
{
if ($this->images()->where('type_id', $type_id)->count() > 0) {
$this->images()->where('type_id', $type_id)->first()->remove();
}
}
public function setImage($type_id, $location)
{
$image = new Image;
$image->src = $location;
$image->imageable_id = $this->id;
$image->imageable_type = self::class;
$image->type_id = $type_id;
$image->save();
}
public function setCreator(User $creator)
{
$this->creator_id = $creator->id;
$this->save();
}
public function interestedCount()
{
return DB::table('tour_interests')->where('tour_id', $this->id)->count();
}
public function remove()
{
$this->delete();
}
public function toSearchableArray()
{
return [
'id' => $this->id,
'name' => $this->name,
'headliner' => ($this->hasHeadliner() ? $this->headliner()->getName() : ''),
'creator_id' => $this->creator_id,
];
}
public function getFirstDate($format = 'd/m/Y')
{
if ($this->status->id == 3) {
if ($this->plannedDates->count() > 0 && $this->plannedDates()->orderBy('date_at', 'ASC')->get()->first()->date_at) {
return $this->plannedDates()->orderBy('date_at', 'ASC')->get()->first()->date_at->format($format);
}
} else {
if ($this->events()->count() > 0) {
return $this->events()->first()->event_at->format($format);
}
}
return '-';
}
public function getLastDate($format = 'd/m/Y')
{
if ($this->status->id == 3) {
if ($this->plannedDates->count() > 0 && $this->plannedDates()->orderBy('date_at', 'ASC')->get()->last()->date_at) {
return $this->plannedDates()->orderBy('date_at', 'ASC')->get()->last()->date_at->format($format);
}
} else {
if ($this->events()->count() > 0) {
return $this->events()->last()->event_at->format($format);
}
}
return '-';
}
public function hasHeadliner()
{
if ($this->artists()->count() > 0) {
return true;
}
return false;
}
public function plannedDates()
{
return $this->hasMany(TourPlannerDate::class, 'tour_id');
}
public function updateName($name)
{
$this->name = $name;
$this->save();
}
public function updateDescription($description)
{
$this->description = $description;
$this->save();
}
public function isAnnounced()
{
if ($this->status->id == 2) {
return true;
}
return false;
}
public function hasPermissionToPreview(User $user)
{
if ($user->id == $this->creator_id) {
return true;
}
return false;
}
public function hasPermissionToEdit(User $user)
{
if ($user->id == $this->creator_id) {
return true;
}
return false;
}
public function hasPermissionToCancel(User $user)
{
if ($user->id == $this->creator_id) {
return true;
}
return false;
}
public function hasPermissionToPublish(User $user)
{
if ($user->id == $this->creator_id) {
return true;
}
return false;
}
public function hasPermissionToReinstate(User $user)
{
if ($user->id == $this->creator_id) {
return true;
}
return false;
}
public function hasPermissionToAnnounce(User $user)
{
if ($user->id == $this->creator_id) {
return true;
}
return false;
}
public function hasPermissionToUnannounce(User $user)
{
if ($user->id == $this->creator_id) {
return true;
}
return false;
}
public function hasFatalPublishWarnings()
{
if ($this->getPublishWarnings()->containsFatal()) {
return true;
}
return false;
}
public function hasFatalAnnounceWarnings()
{
if ($this->getAnnounceWarnings()->containsFatal()) {
return true;
}
return false;
}
public function getAnnounceWarnings()
{
$warnings = new WarningCollection;
if ($this->events()->count() == 0) {
$warning = new TourAnnounceWarning;
$warning->setMessage(config('messages.tour_manager.warnings.tour_has_no_events'))
->setAsFatal();
$warnings->push($warning);
return $warnings;
}
foreach ($this->events() as $event) {
if (! $event->isApprovedByVenue()) {
$warning = new TourAnnounceWarning;
$warning->setMessage(config('messages.tour_manager.warnings.event_not_approved_by_venue'))
->setDate($event->event_at);
$warnings->push($warning);
}
if (! $event->hasDoorsSet()) {
$warning = new TourAnnounceWarning;
$warning->setMessage(config('messages.tour_manager.warnings.event_has_no_doors_set'))
->setDate($event->event_at);
$warnings->push($warning);
}
if ($event->isAnnounced()) {
$warning = new TourAnnounceWarning;
$warning->setMessage(config('messages.tour_manager.warnings.is_already_announced'))
->setDate($event->event_at);
$warnings->push($warning);
}
}
return $warnings;
}
public function getAnnouncableEventCount()
{
$count = $this->events()->count();
foreach ($this->events() as $event) {
if (
! $event->isApprovedByVenue() ||
! $event->hasDoorsSet() ||
$event->isAnnounced()
) {
$count--;
}
}
return $count;
}
public function getPublishWarnings()
{
$warnings = new WarningCollection;
if ($this->plannedDates->count() == 0) {
$warning = new TourPublishWarning;
$warning->setMessage(config('messages.tour_manager.warnings.tour_has_no_dates'))
->setAsFatal();
$warnings->push($warning);
return $warnings;
}
$at_least_one_event = false;
foreach ($this->plannedDates as $date) {
if ($date->events()->count() != 0) {
$at_least_one_event = true;
}
}
if (! $at_least_one_event) {
$warning = new TourPublishWarning;
$warning->setMessage(config('messages.tour_manager.warnings.tour_has_no_events'))
->setAsFatal();
$warnings->push($warning);
return $warnings;
}
foreach ($this->plannedDates as $date) {
if ($date->events()->count() == 0) {
$warning = new TourPublishWarning;
$warning->setDate($date->date_at)
->setLocation($date->location)
->setMessage(config('messages.tour_manager.warnings.tour_date_has_no_events'));
$warnings->push($warning);
} else {
$at_least_one_event = true;
foreach ($date->events as $event) {
if ($event->isProposed()) {
$warning = new TourPublishWarning;
$warning->setDate($date->date_at)
->setLocation($date->location)
->setMessage(config('messages.tour_manager.warnings.event_has_not_been_approved_by_venue'));
$warnings->push($warning);
}
}
}
}
return $warnings;
}
public function announce()
{
$this->changeStatus(TourStatus::findOrFail(2));
return $this;
}
public function unannounce()
{
$this->changeStatus(TourStatus::findOrFail(1));
return $this;
}
public function publish()
{
$this->changeStatus(TourStatus::findOrFail(1));
return $this;
}
public function reinstate()
{
$this->restore();
return $this;
}
public function cancel()
{
$this->delete();
}
}