feat: [boards] 게시판 API 시스템 구현
- BoardController, PostController 추가 - Board, BoardSetting 모델 수정 - BoardService 추가 - FormRequest 클래스 추가 - Swagger 문서 추가 (BoardApi, PostApi) - 게시판 시스템 필드 마이그레이션 추가
This commit is contained in:
320
app/Services/Boards/BoardService.php
Normal file
320
app/Services/Boards/BoardService.php
Normal file
@@ -0,0 +1,320 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Boards;
|
||||
|
||||
use App\Models\Boards\Board;
|
||||
use App\Models\Boards\BoardSetting;
|
||||
use App\Services\Service;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class BoardService extends Service
|
||||
{
|
||||
// =========================================================================
|
||||
// 조회 메서드
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 접근 가능한 게시판 목록 (시스템 + 테넌트)
|
||||
*/
|
||||
public function getAccessibleBoards(array $filters = []): Collection
|
||||
{
|
||||
return Board::accessible($this->tenantId())
|
||||
->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type']))
|
||||
->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%"))
|
||||
->orderBy('is_system', 'desc')
|
||||
->orderBy('name')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 시스템 게시판 목록 (mng용)
|
||||
*/
|
||||
public function getSystemBoards(array $filters = []): Collection
|
||||
{
|
||||
return Board::systemOnly()
|
||||
->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type']))
|
||||
->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%"))
|
||||
->orderBy('name')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 시스템 게시판 페이징 목록 (mng용)
|
||||
*/
|
||||
public function getSystemBoardsPaginated(array $filters = [], int $perPage = 15): LengthAwarePaginator
|
||||
{
|
||||
return Board::systemOnly()
|
||||
->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type']))
|
||||
->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%"))
|
||||
->when(isset($filters['is_active']), fn ($q) => $q->where('is_active', $filters['is_active']))
|
||||
->orderBy('name')
|
||||
->paginate($perPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 테넌트 게시판만 가져오기
|
||||
*/
|
||||
public function getTenantBoards(array $filters = []): Collection
|
||||
{
|
||||
return Board::tenantOnly($this->tenantId())
|
||||
->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type']))
|
||||
->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%"))
|
||||
->orderBy('name')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 코드로 조회 (접근 가능한 게시판 중에서)
|
||||
*/
|
||||
public function getBoardByCode(string $code): ?Board
|
||||
{
|
||||
return Board::accessible($this->tenantId())
|
||||
->where('board_code', $code)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 시스템 게시판 ID로 조회 (mng용)
|
||||
*/
|
||||
public function getSystemBoardById(int $id): ?Board
|
||||
{
|
||||
return Board::systemOnly()
|
||||
->with('customFields')
|
||||
->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 ID로 조회 (상세)
|
||||
*/
|
||||
public function getBoardDetail(int $id): ?Board
|
||||
{
|
||||
return Board::with('customFields')
|
||||
->find($id);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 생성 메서드
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 시스템 게시판 생성 (mng용)
|
||||
*/
|
||||
public function createSystemBoard(array $data): Board
|
||||
{
|
||||
$data['is_system'] = true;
|
||||
$data['tenant_id'] = null;
|
||||
$data['created_by'] = $this->apiUserId();
|
||||
|
||||
return Board::create($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 테넌트 게시판 생성 (sam용)
|
||||
*/
|
||||
public function createTenantBoard(array $data): Board
|
||||
{
|
||||
$data['is_system'] = false;
|
||||
$data['tenant_id'] = $this->tenantId();
|
||||
$data['created_by'] = $this->apiUserId();
|
||||
|
||||
return Board::create($data);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 수정 메서드
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 시스템 게시판 수정 (mng용)
|
||||
*/
|
||||
public function updateSystemBoard(int $id, array $data): ?Board
|
||||
{
|
||||
$board = Board::systemOnly()->find($id);
|
||||
|
||||
if (! $board) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data['updated_by'] = $this->apiUserId();
|
||||
$board->update($data);
|
||||
|
||||
return $board->fresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* 테넌트 게시판 수정 (sam용)
|
||||
*/
|
||||
public function updateTenantBoard(int $id, array $data): ?Board
|
||||
{
|
||||
$board = Board::tenantOnly($this->tenantId())->find($id);
|
||||
|
||||
if (! $board) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data['updated_by'] = $this->apiUserId();
|
||||
$board->update($data);
|
||||
|
||||
return $board->fresh();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 삭제 메서드
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 시스템 게시판 삭제 (mng용)
|
||||
*/
|
||||
public function deleteSystemBoard(int $id): bool
|
||||
{
|
||||
$board = Board::systemOnly()->find($id);
|
||||
|
||||
if (! $board) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$board->deleted_by = $this->apiUserId();
|
||||
$board->save();
|
||||
$board->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 테넌트 게시판 삭제 (sam용)
|
||||
*/
|
||||
public function deleteTenantBoard(int $id): bool
|
||||
{
|
||||
$board = Board::tenantOnly($this->tenantId())->find($id);
|
||||
|
||||
if (! $board) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$board->deleted_by = $this->apiUserId();
|
||||
$board->save();
|
||||
$board->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 필드 관리 메서드
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 게시판 필드 목록 조회
|
||||
*/
|
||||
public function getBoardFields(int $boardId): Collection
|
||||
{
|
||||
return BoardSetting::where('board_id', $boardId)
|
||||
->orderBy('sort_order')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 필드 추가
|
||||
*/
|
||||
public function addBoardField(int $boardId, array $data): BoardSetting
|
||||
{
|
||||
$data['board_id'] = $boardId;
|
||||
$data['created_by'] = $this->apiUserId();
|
||||
|
||||
// 기본 정렬 순서 설정
|
||||
if (! isset($data['sort_order'])) {
|
||||
$maxOrder = BoardSetting::where('board_id', $boardId)->max('sort_order') ?? 0;
|
||||
$data['sort_order'] = $maxOrder + 1;
|
||||
}
|
||||
|
||||
return BoardSetting::create($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 필드 수정
|
||||
*/
|
||||
public function updateBoardField(int $fieldId, array $data): ?BoardSetting
|
||||
{
|
||||
$field = BoardSetting::find($fieldId);
|
||||
|
||||
if (! $field) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data['updated_by'] = $this->apiUserId();
|
||||
$field->update($data);
|
||||
|
||||
return $field->fresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 필드 삭제
|
||||
*/
|
||||
public function deleteBoardField(int $fieldId): bool
|
||||
{
|
||||
$field = BoardSetting::find($fieldId);
|
||||
|
||||
if (! $field) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $field->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 필드 순서 변경
|
||||
*/
|
||||
public function reorderBoardFields(int $boardId, array $fieldIds): bool
|
||||
{
|
||||
foreach ($fieldIds as $order => $fieldId) {
|
||||
BoardSetting::where('id', $fieldId)
|
||||
->where('board_id', $boardId)
|
||||
->update(['sort_order' => $order + 1]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 유틸리티 메서드
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 게시판 코드 중복 확인
|
||||
*/
|
||||
public function isCodeExists(string $code, ?int $excludeId = null): bool
|
||||
{
|
||||
$query = Board::where('board_code', $code);
|
||||
|
||||
// 시스템 게시판이면 시스템 게시판 중에서 확인
|
||||
// 테넌트 게시판이면 해당 테넌트 중에서 확인
|
||||
$query->where(function ($q) {
|
||||
$q->where('is_system', true)
|
||||
->orWhere('tenant_id', $this->tenantIdOrNull());
|
||||
});
|
||||
|
||||
if ($excludeId) {
|
||||
$query->where('id', '!=', $excludeId);
|
||||
}
|
||||
|
||||
return $query->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 활성/비활성 토글
|
||||
*/
|
||||
public function toggleActive(int $id): ?Board
|
||||
{
|
||||
$board = Board::find($id);
|
||||
|
||||
if (! $board) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$board->is_active = ! $board->is_active;
|
||||
$board->updated_by = $this->apiUserId();
|
||||
$board->save();
|
||||
|
||||
return $board;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user