View file app/Models/Topic.php

File size: 5.09Kb
<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\HtmlString;

/**
 * Class Topic
 *
 * @property int id
 * @property int forum_id
 * @property string title
 * @property int user_id
 * @property int closed
 * @property int locked
 * @property int count_posts
 * @property int visits
 * @property int updated_at
 * @property string|null moderators
 * @property string note
 * @property int last_post_id
 * @property int close_user_id
 * @property int created_at
 * @property Forum forum
 * @property Collection posts
 * @property Vote vote
 */
class Topic extends BaseModel
{
    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = false;

    /**
     * The attributes that aren't mass assignable.
     *
     * @var array
     */
    protected $guarded = [];

    /**
     * Counting field
     *
     * @var string
     */
    public $countingField = 'visits';

    /**
     * Morph name
     *
     * @var string
     */
    public static $morphName = 'topics';

    /**
     * Возвращает сообщения
     *
     * @return HasMany
     */
    public function posts(): HasMany
    {
        return $this->hasMany(Post::class, 'topic_id');
    }

    /**
     * Возвращает закладки
     *
     * @return HasMany
     */
    public function bookmarks(): HasMany
    {
        return $this->hasMany(Bookmark::class, 'topic_id');
    }

    /**
     * Возвращает голосование
     *
     * @return hasOne
     */
    public function vote(): hasOne
    {
        return $this->hasOne(Vote::class, 'topic_id')->withDefault();
    }

    /**
     * Возвращает последнее сообщение
     *
     * @return BelongsTo
     */
    public function lastPost(): BelongsTo
    {
        return $this->belongsTo(Post::class, 'last_post_id')->withDefault();
    }

    /**
     * Возвращает раздел форума
     *
     * @return BelongsTo
     */
    public function forum(): BelongsTo
    {
        return $this->belongsTo(Forum::class, 'forum_id')->withDefault();
    }

    /**
     * Возвращает связь пользователей
     *
     * @return BelongsTo
     */
    public function closeUser(): BelongsTo
    {
        return $this->belongsTo(User::class, 'close_user_id')->withDefault();
    }

    /**
     * Возвращает иконку в зависимости от статуса
     *
     * @return string иконка топика
     */
    public function getIcon(): string
    {
        if ($this->closed) {
            $icon = 'fa-lock';
        } elseif ($this->locked) {
            $icon = 'fa-thumbtack';
        } else {
            $icon = 'fa-folder-open';
        }

        return $icon;
    }

    /**
     * Генерирует постраничную навигация для форума
     *
     * @param  string $url
     * @return HtmlString|null сформированный блок
     */
    public function pagination(string $url = '/topics'): ?HtmlString
    {
        if (! $this->count_posts) {
            return null;
        }

        $pages = [];
        $link = $url . '/' . $this->id;

        $pg_cnt = ceil($this->count_posts / setting('forumpost'));

        for ($i = 1; $i <= 5; $i++) {
            if ($i <= $pg_cnt) {
                $pages[] = [
                    'page' => $i,
                    'title' => $i.' страница',
                    'name' => $i,
                ];
            }
        }

        if (5 < $pg_cnt) {
            if (6 < $pg_cnt) {
                $pages[] = [
                    'separator' => true,
                    'name' => ' ... ',
                ];
            }

            $pages[] = [
                'page' => $pg_cnt,
                'title' => $pg_cnt.' страница',
                'name' => $pg_cnt,
            ];
        }

        return new HtmlString(view('forums/_pagination', compact('pages', 'link')));
    }

    /**
     * Пересчет темы
     *
     * @return void
     */
    public function restatement(): void
    {
        $lastPost = Post::query()
            ->where('topic_id', $this->id)
            ->orderByDesc('updated_at')
            ->first();

        $countPosts = Post::query()->where('topic_id', $this->id)->count();

        $this->update([
            'count_posts'  => $countPosts,
            'last_post_id' => $lastPost->id ?? 0,
        ]);

        $this->forum->restatement();
    }

    /**
     * Get count posts
     *
     * @return HtmlString
     */
    public function getCountPosts(): HtmlString
    {
        $newPosts = null;
        if (isset($this->bookmark_posts) && $this->count_posts > $this->bookmark_posts) {
            $newPosts = ' <span style="color:#00aa00">+' . ($this->count_posts - $this->bookmark_posts) . '</span>';
        }


        return new HtmlString($this->count_posts . $newPosts);
    }
}