| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- <?php
- namespace App\Models;
- use Illuminate\Database\Eloquent\Model;
- use Illuminate\Support\Facades\DB;
- use Kalnoy\Nestedset\NodeTrait;
- use App\Http\Traits\PagingTrait;
- use App\Models\DTO\SearchData;
- class Comment extends Model
- {
- use NodeTrait;
- use PagingTrait;
- protected $table = 'tb_comment';
- protected $primaryKey = 'id';
- public $keyType = 'int';
- public $incrementing = true;
- public $timestamps = true;
- const CREATED_AT = 'created_at';
- const UPDATED_AT = 'updated_at';
- const DELETED_AT = 'deleted_at';
- protected $guarded = [];
- public function board()
- {
- return $this->belongsTo(Board::class)->withDefault();
- }
- public function post()
- {
- return $this->belongsTo(Post::class)->withDefault();
- }
- public function user()
- {
- return $this->belongsTo(User::class)->withDefault();
- }
- public function commentblame()
- {
- return $this->hasMany(CommentBlame::Class);
- }
- public function commentDeleted()
- {
- return $this->hasMany(CommentDeleted::Class);
- }
- public function commentHistory()
- {
- return $this->hasMany(CommentHistory::Class);
- }
- public function commentLike()
- {
- return $this->hasMany(CommentLike::Class);
- }
- public function commentMeta()
- {
- return $this->hasOne(CommentMeta::Class);
- }
- public function getParentIdName(): string
- {
- return 'parent_id';
- }
- public function getLftName(): string
- {
- return 'lft';
- }
- public function getRgtName(): string
- {
- return 'rgt';
- }
- /**
- * 댓글 조회
- */
- public function data(SearchData $params): object
- {
- $query = $this->query();
- $query->select(
- 'tb_comment.*',
- 'tb_board.name AS boardName',
- 'tb_board.code',
- 'tb_post.subject',
- 'users.id',
- 'users.sid',
- 'users.name',
- 'users.email'
- );
- if($params->keyword) {
- switch ($params->field) {
- case 'tb_comment.id' :
- case 'tb_comment.post_id' :
- case 'users.id' :
- case 'users.sid' :
- $query->where($params->field, '=', $params->keyword);
- break;
- case 'tb_comment.content' :
- case 'users.name' :
- case 'users.email' :
- $query->where($params->field, 'LIKE', "%{$params->keyword}%");
- break;
- }
- }
- $query->where('tb_comment.is_delete', '=', 0);
- if($params->startDate || $params->endDate) {
- if($params->startDate) {
- $query->where('tb_comment.created_at', '>=', $params->startDate . ' 00:00:00');
- }
- if($params->endDate) {
- $query->where('tb_comment.created_at', '<=', $params->endDate . ' 23:59:59');
- }
- }
- if($params->boardID) {
- $query->where('tb_comment.board_id', '=', $params->boardID);
- }
- $query->join('tb_board', 'tb_board.id', '=', 'tb_comment.board_id');
- $query->join('tb_post', 'tb_post.id', '=', 'tb_comment.post_id');
- $query->leftJoin('users', 'users.id', '=', 'tb_comment.user_id');
- $query->orderByDesc('tb_comment.id');
- $list = $query->paginate($params->perPage, ['*'], 'page', $params->page);
- $total = $this->count();
- $rows = $list->count();
- return (object)[
- 'total' => $total,
- 'rows' => $rows,
- 'list' => $list
- ];
- }
- /**
- * 댓글 전체 개수
- */
- public function total(int $postID): int
- {
- return $this->where('post_id', $postID)->count();
- }
- /**
- * 댓글 등록
- */
- public function register(array $params): Comment
- {
- return $this->create($params);
- }
- /**
- * 댓글 수정
- */
- public function updater(int $commentID, array $params): Comment
- {
- return $this->updateOrCreate([$this->primaryKey => $commentID], $params);
- }
- /**
- * 답글 등록
- */
- public function reply(int $commentID, array $params): Comment
- {
- $parent = $this->findParent($commentID);
- $node = $parent->children()->create($params);
- $node->depth = ($parent->depth + 1);
- $node->save();
- return $node;
- }
- /**
- * 댓글 조회
- */
- public function get(int $commentID): Comment
- {
- return $this->from('tb_comment AS CMT')->select('CMT.*')
- ->with(['board', 'post', 'user'])->where([
- ['CMT.id', $commentID],
- ['CMT.is_delete', 0]
- ])->firstOrNew();
- }
- /**
- * 댓글 조회
- */
- public function getList(string $code, int $postID, int $page, int $offset, int $perPage, int $sort): object
- {
- $orderBy = $this->sortQuery($sort);
- $sql = "
- SELECT
- COUNT(CMT.id) AS total
- FROM tb_comment CMT
- JOIN tb_post PST ON PST.id = CMT.post_id
- JOIN tb_board BRD ON BRD.id = PST.board_id
- WHERE TRUE
- AND BRD.code = ?
- AND PST.id = ?
- AND CASE WHEN (CMT.is_delete = 1 AND CMT.reply <= 0 AND CMT.depth <= 0) THEN FALSE ELSE TRUE END
- ";
- $total = DB::selectOne($sql, [$code, $postID])->total;
- $sql = "
- SELECT
- @replyRows := (SELECT (COUNT(id) - 1) FROM tb_comment WHERE lft BETWEEN CMT.lft AND CMT.rgt) AS replyRows,
- @depth := (SELECT (COUNT(*) - 1) FROM tb_comment WHERE CMT.rgt BETWEEN lft AND rgt),
- CMT.*,
- USR.name,
- USR.thumb,
- USR.icon,
- IFNULL(CLIK.`type`, 0) AS likeType
- FROM tb_comment CMT
- JOIN tb_comment PCMT ON CMT.lft BETWEEN PCMT.lft AND PCMT.rgt
- JOIN tb_post PST ON PST.id = CMT.post_id
- JOIN tb_board BRD ON BRD.id = PST.board_id
- LEFT JOIN tb_comment_like CLIK ON CLIK.post_id = CMT.post_id AND CMT.id = CLIK.comment_id
- LEFT JOIN users USR ON USR.id = CMT.user_id
- WHERE TRUE
- AND BRD.code = ?
- AND PST.id = ?
- AND CASE WHEN (CMT.is_delete = 1 AND @replyRows <= 0 AND @depth <= 0) THEN FALSE ELSE TRUE END
- GROUP BY
- CMT.id,
- CLIK.`type`
- ORDER BY
- {$orderBy}
- LIMIT ?, ?;
- ";
- $list = $this->getPaginator(
- DB::select($sql, [$code, $postID, $offset, $perPage]), $total, $perPage, $page
- );
- return (object)[
- 'total' => $total,
- 'list' => $list
- ];
- }
- /**
- * 회원 댓글 목록 조회
- */
- public function getUserList(int $userID, SearchData $params): object
- {
- $sql = "
- SELECT
- COUNT(CMT.id) AS total
- FROM tb_comment CMT
- JOIN tb_post PST ON PST.id = CMT.post_id
- JOIN tb_board BRD ON BRD.id = PST.board_id
- LEFT JOIN users USR ON USR.id = CMT.user_id
- WHERE TRUE
- AND USR.id = ?
- AND CMT.is_delete = 0;
- ";
- $total = DB::selectOne($sql, [$userID])->total;
- $sql = "
- SELECT
- @replyRows := (SELECT (COUNT(id) - 1) FROM tb_comment WHERE lft BETWEEN CMT.lft AND CMT.rgt) AS replyRows,
- @depth := (SELECT (COUNT(*) - 1) FROM tb_comment WHERE CMT.rgt BETWEEN lft AND rgt),
- CMT.*,
- BRD.code,
- PST.subject, PST.comment_rows, PST.file_rows, PST.image_rows, PST.link_rows,
- USR.name, USR.thumb, USR.icon
- FROM tb_comment CMT
- JOIN tb_comment PCMT ON CMT.lft BETWEEN PCMT.lft AND PCMT.rgt
- JOIN tb_post PST ON PST.id = CMT.post_id
- JOIN tb_board BRD ON BRD.id = CMT.board_id
- LEFT JOIN users USR ON USR.id = CMT.user_id
- WHERE TRUE
- AND USR.id = ?
- AND CMT.is_delete = 0
- GROUP BY
- CMT.id
- ORDER BY
- CMT.lft ASC, CMT.created_at ASC
- LIMIT ?, ?;
- ";
- $list = $this->getPaginator(
- DB::select($sql, [$userID, $params->offset, $params->perPage]), $total, $params->perPage, $params->page
- );
- return (object)[
- 'total' => $total,
- 'list' => $list
- ];
- }
- /**
- * 정렬 순서
- */
- private function sortQuery(int $sort): string
- {
- switch($sort) {
- default:case 1: // 등록순
- return 'CMT.lft ASC, CMT.created_at ASC';
- case 2: // 최신순
- return 'CMT.rgt DESC';
- case 3: // 공감 순
- return '
- CASE WHEN (CMT.parent_id IS NULL AND CMT.reply <= 0) THEN CMT.like
- WHEN TRUE THEN TRUE
- ELSE NULL
- END DESC
- , CMT.lft ASC
- ';
- case 4: // 댓글 순
- return '
- CASE WHEN (CMT.parent_id IS NULL AND CMT.reply <= 0) THEN CMT.like
- WHEN TRUE THEN TRUE
- ELSE NULL
- END DESC
- , CMT.lft ASC
- ';
- }
- }
- /**
- * 댓글 조회
- */
- public function findParent(int $commentID)
- {
- return $this->newQuery()->withDepth()->find($commentID);
- }
- /**
- * 댓글 신고 수 증가
- */
- public function increaseBlame(int $commentID): int
- {
- return $this->where('id', $commentID)->increment('blame');
- }
- /**
- * 댓글 신고 수 증감
- */
- public function decreaseBlame(int $commentID): int
- {
- return $this->where('id', $commentID)->where('blame', '>', '0')->decrement('blame', 1);
- }
- /**
- * 댓글 좋아요 수 증가
- */
- public function increaseLike(int $commentID): int
- {
- return $this->where('id', $commentID)->increment('like');
- }
- /**
- * 댓글 좋아요 수 증감
- */
- public function decreaseLike(int $commentID): int
- {
- return $this->where('id', $commentID)->where('like', '>', '0')->decrement('like', 1);
- }
- /**
- * 댓글 싫어요 수 증가
- */
- public function increaseDisLike(int $commentID): int
- {
- return $this->where('id', $commentID)->increment('dislike');
- }
- /**
- * 댓글 싫어요 수 증감
- */
- public function decreaseDisLike(int $commentID): int
- {
- return $this->where('id', $commentID)->where('dislike', '>', '0')->decrement('dislike');
- }
- /**
- * 댓글 수 증가
- */
- public function increaseReply(int $commentID): int
- {
- return $this->where('id', $commentID)->increment('reply');
- }
- /**
- * 댓글 수 증감
- */
- public function decreaseReply(int $commentID): int
- {
- return $this->where('id', $commentID)->where('reply', '>', '0')->decrement('reply');
- }
- /**
- * 댓글 개수 갱신
- */
- public function updateCommentRows(int $commentID): int
- {
- $sql = "
- UPDATE tb_comment A, (
- SELECT
- (COUNT(*) - 1) AS total
- FROM tb_comment CMT
- JOIN tb_comment PCMT ON CMT.lft BETWEEN PCMT.lft AND PCMT.rgt
- WHERE PCMT.id = :id
- ) B
- SET A.reply = B.total
- WHERE A.id = :id;
- ";
- return DB::update($sql, [
- 'id' => $commentID
- ]);
- }
- /**
- * 댓글의 현재 페이지 번호
- */
- public function findPageNumber(int $commentID, int $perPage = DEFAULT_LIST_PER_PAGE): int
- {
- $sql = "
- SELECT
- D.cnt,
- COALESCE(CEIL((D.cnt - 1) / :perPage), 1) AS page
- FROM (
- SELECT
- *, @num := (@num + 1) AS cnt
- FROM
- tb_comment,
- (SELECT @num := 0) AS N1,
- (SELECT
- @boardID := board_id, @postID := post_id, @commentID := id
- FROM tb_comment WHERE id = :commentID
- ) AS N2
- WHERE TRUE
- AND board_id = @boardID
- AND post_id = @postID
- ORDER BY lft
- ) D
- WHERE D.id = @commentID;
- ";
- return DB::selectOne($sql, [
- 'commentID' => $commentID,
- 'perPage' => $perPage
- ])->page;
- }
- /**
- * 댓글 존재 확인
- */
- public function isExists(int $commentID): int
- {
- $sql = "
- SELECT IF(COUNT(*) > 0, 1, 0) AS isExists
- FROM tb_comment CMT JOIN tb_post PST ON PST.id = CMT.post_id
- WHERE CMT.id = ? AND CMT.is_delete = 0;
- ";
- return DB::selectOne($sql, [$commentID])->isExists;
- }
- /**
- * 내가 작성한 댓글인지 확인
- */
- public function getChildRows(int $commentID): int
- {
- $sql = "
- SELECT (COUNT(CMT.comment_id) - 1) AS `rows` FROM tb_comment CMT
- JOIN tb_comment PCMT ON CMT.lft BETWEEN PCMT.lft AND PCMT.rgt
- WHERE PCMT.id = ?
- ";
- return DB::selectOne($sql, [$commentID])->rows;
- }
- /**
- * 추가 댓글 번호
- */
- public function lastedKey(): int
- {
- return intval(DB::selectOne(
- "SELECT AUTO_INCREMENT AS id FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'tb_comment';"
- )->id);
- }
- /**
- * 댓글 삭제
- */
- public function remove(Comment $comment, ?User $user): mixed
- {
- return DB::transaction(function() use ($comment, $user)
- {
- // 댓글 삭제 여부 승인
- $this->updater($comment->id, [
- 'is_delete' => 1,
- 'deleted_at' => now()
- ]);
- // 댓글 삭제 정보 추가
- (new CommentDeleted)->register([
- 'board_id' => $comment->board_id,
- 'post_id' => $comment->post_id,
- 'comment_id' => $comment->id,
- 'user_id' => $user?->id,
- 'ip_address' => IP_ADDRESS,
- 'user_agent' => USER_AGENT,
- 'created_at' => now()
- ]);
- // 게시판 댓글 수 갱신
- (new Board)->updateCommentRows($comment->board_id);
- // 게시판 댓글 수 갱신
- (new Post)->updateCommentRows($comment->post_id);
- // 부모 댓글 수 갱신
- $this->updateCommentRows($comment->id);
- return true;
- });
- }
- }
|