rinvex/laravel-bookings

View on GitHub
src/Traits/Ticketable.php

Summary

Maintainability
A
35 mins
Test Coverage
<?php

declare(strict_types=1);

namespace Rinvex\Bookings\Traits;

use Illuminate\Database\Eloquent\Model;
use Rinvex\Bookings\Models\TicketableBooking;
use Illuminate\Database\Eloquent\Relations\MorphMany;

trait Ticketable
{
    /**
     * Register a saved model event with the dispatcher.
     *
     * @param \Closure|string $callback
     *
     * @return void
     */
    abstract public static function saved($callback);

    /**
     * Register a deleted model event with the dispatcher.
     *
     * @param \Closure|string $callback
     *
     * @return void
     */
    abstract public static function deleted($callback);

    /**
     * Define a polymorphic one-to-many relationship.
     *
     * @param string $related
     * @param string $name
     * @param string $type
     * @param string $id
     * @param string $localKey
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     */
    abstract public function morphMany($related, $name, $type = null, $id = null, $localKey = null);

    /**
     * Get the booking model name.
     *
     * @return string
     */
    abstract public function getBookingModel(): string;

    /**
     * Get the ticket model name.
     *
     * @return string
     */
    abstract public function getTicketModel(): string;

    /**
     * Boot the Ticketable trait for the model.
     *
     * @return void
     */
    public static function bootTicketable()
    {
        static::deleted(function (self $model) {
            $model->bookings()->delete();
        });
    }

    /**
     * Attach the given bookings to the model.
     *
     * @param \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|array $ids
     * @param mixed                                                                         $bookings
     *
     * @return void
     */
    public function setBookingsAttribute($bookings): void
    {
        static::saved(function (self $model) use ($bookings) {
            $this->bookings()->sync($bookings);
        });
    }

    /**
     * The resource may have many tickets.
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     */
    public function tickets(): MorphMany
    {
        return $this->morphMany(static::getTicketModel(), 'ticketable', 'ticketable_type', 'ticketable_id');
    }

    /**
     * The resource may have many bookings.
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     */
    public function bookings(): MorphMany
    {
        return $this->morphMany(static::getBookingModel(), 'ticketable', 'ticketable_type', 'ticketable_id');
    }

    /**
     * Get bookings by the given customer.
     *
     * @param \Illuminate\Database\Eloquent\Model $customer
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     */
    public function bookingsBy(Model $customer): MorphMany
    {
        return $this->bookings()->where('customer_type', $customer->getMorphClass())->where('customer_id', $customer->getKey());
    }

    /**
     * Book the model for the given customer at the given dates with the given price.
     *
     * @param \Illuminate\Database\Eloquent\Model $customer
     * @param float                               $paid
     * @param string                              $currency
     *
     * @return \Rinvex\Bookings\Models\TicketableBooking
     */
    public function newBooking(Model $customer, float $paid, string $currency): TicketableBooking
    {
        return $this->bookings()->create([
            'ticketable_id' => static::getKey(),
            'ticketable_type' => static::getMorphClass(),
            'customer_id' => $customer->getKey(),
            'customer_type' => $customer->getMorphClass(),
            'paid' => $paid,
            'currency' => $currency,
        ]);
    }
}