EscolaLMS/Courses

View on GitHub
src/Models/Topic.php

Summary

Maintainability
A
0 mins
Test Coverage
B
87%
<?php

namespace EscolaLms\Courses\Models;

use EscolaLms\Core\Models\Traits\QueryCacheable;
use EscolaLms\Courses\Database\Factories\TopicFactory;
use EscolaLms\Courses\Facades\Topic as TopicFacade;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Validation\Rule;

/**
 * @OA\Schema(
 *      schema="Topic",
 *      required={"lesson_id", "order"},
 *      @OA\Property(
 *          property="id",
 *          description="id",
 *          type="integer",
 *      ),
 *      @OA\Property(
 *          property="title",
 *          description="title",
 *          type="string"
 *      ),
 *      @OA\Property(
 *          property="active",
 *          description="active",
 *          type="boolean"
 *      ),
 *      @OA\Property(
 *          property="can_skip",
 *          description="can skip",
 *          type="boolean"
 *      ),
 *      @OA\Property(
 *          property="preview",
 *          description="preview",
 *          type="boolean"
 *      ),
 *      @OA\Property(
 *          property="lesson_id",
 *          description="lesson_id",
 *          type="integer",
 *      ),
 *      @OA\Property(
 *          property="topicable_id",
 *          description="topicable_id",
 *          type="integer",
 *      ),
 *      @OA\Property(
 *          property="topicable_type",
 *          description="topicable_type",
 *          type="string"
 *      ),
 *      @OA\Property(
 *          property="value",
 *          description="value",
 *          type="string"
 *      ),
 *      @OA\Property(
 *          property="summary",
 *          description="summary",
 *          type="string"
 *      ),
 *      @OA\Property(
 *          property="introduction",
 *          description="introduction",
 *          type="string"
 *      ),
 *      @OA\Property(
 *          property="description",
 *          description="description",
 *          type="string"
 *      ),
 *      @OA\Property(
 *          property="order",
 *          description="order",
 *          type="integer",
 *      ),
 *      @OA\Property(
 *          property="json",
 *          description="json",
 *          type="object",
 *      ),
 *      @OA\Property(
 *          property="duration",
 *          description="duration",
 *          type="string"
 *      ),
 * )
 *
 * @property bool                                  $active
 * @property \EscolaLms\Courses\Models\Lesson|null $lesson
 * @property int $lesson_id
 * @property int $topic_id
 * @property int $order
 * @property int $topicable_id
 * @property string $topicable_type
 */
class Topic extends Model
{
    use HasFactory, QueryCacheable;

    public $table = 'topics';

    public $fillable = [
        'title',
        'lesson_id',
        'topicable_id',
        'topicable_type',
        'order',
        'active',
        'preview',
        'summary',
        'introduction',
        'description',
        'json',
        'can_skip',
        'duration',
    ];

    /**
     * The attributes that should be casted to native types.
     *
     * @var array
     */
    protected $casts = [
        'id' => 'integer',
        'title' => 'string',
        'lesson_id' => 'integer',
        'topicable_id' => 'integer',
        'topicable_type' => 'string',
        'order' => 'integer',
        'active' => 'boolean',
        'preview' => 'boolean',
        'summary' => 'string',
        'introduction' => 'string',
        'description' => 'string',
        'json' => 'array',
        'can_skip' => 'boolean',
        'duration' => 'string',
    ];

    public static function rules(): array
    {
        return [
            'title' => ['string', 'max:255'],
            'summary' => ['string'],
            'introduction' => ['string'],
            'description' => ['string'],
            'lesson_id' => ['integer', 'exists:lessons,id'],
            'topicable_type' => ['string', Rule::in(TopicFacade::availableContentClasses())],
            'order' => ['integer'],
            'active' => ['boolean'],
            'preview' => ['boolean'],
            'can_skip' => ['boolean'],
            'json' => ['json'],
            'duration' => ['nullable', 'string', 'max:255'],
        ];
    }

    public function lesson(): BelongsTo
    {
        return $this->belongsTo(\EscolaLms\Courses\Models\Lesson::class, 'lesson_id');
    }

    protected static function newFactory(): TopicFactory
    {
        return \EscolaLms\Courses\Database\Factories\TopicFactory::new();
    }

    public function topicable(): MorphTo
    {
        return $this->morphTo();
    }

    public function progress(): HasMany
    {
        return $this->hasMany(CourseProgress::class, 'topic_id');
    }

    public function resources(): HasMany
    {
        return $this->hasMany(TopicResource::class, 'topic_id');
    }

    public function scopeActive(Builder $query): Builder
    {
        return $query->where('topics.active', '=', true);
    }

    public function getStorageDirectoryAttribute(): string
    {
        if ($this->lesson && $this->lesson->course_id) {
            return 'course/' . $this->lesson->course_id . '/topic/' . $this->getKey() . '/';
        }

        return 'topic/' . $this->getKey() . '/';
    }

    public function getCourseAttribute(): ?Course
    {
        return $this->lesson ? $this->lesson->course : null;
    }

    public function getIsActiveAttribute(): bool
    {
        return $this->active && ($this->course ? $this->course->is_active : true);
    }

    protected function getCacheBaseTags(): array
    {
        return [
            Topic::class,
        ];
    }
}