MOON
Server: Apache
System: Linux e2e-78-16.ssdcloudindia.net 3.10.0-1160.45.1.el7.x86_64 #1 SMP Wed Oct 13 17:20:51 UTC 2021 x86_64
User: imensosw (1005)
PHP: 8.0.30
Disabled: exec,passthru,shell_exec,system
Upload Files
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();
    }
}