- MenuService에 게시판 메뉴 연동 메서드 추가 - createMenuForBoard(): 게시판 생성 시 /board 하위에 메뉴 자동 추가 - updateMenuForBoard(): 코드/이름 변경 시 메뉴 URL/이름 동기화 - deleteMenuForBoard(): 게시판 삭제 시 메뉴 Soft Delete - restoreMenuForBoard(): 게시판 복원 시 메뉴 복원 - findParentMenuForBoard(): 부모 메뉴 (/board) 찾기 - BoardService에서 테넌트 게시판 CRUD 시 MenuService 호출 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
379 lines
10 KiB
PHP
379 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Boards;
|
|
|
|
use App\Models\Boards\Board;
|
|
use App\Models\Boards\BoardSetting;
|
|
use App\Services\MenuService;
|
|
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();
|
|
}
|
|
|
|
/**
|
|
* 시스템 게시판 코드로 조회
|
|
*/
|
|
public function getSystemBoardByCode(string $code): ?Board
|
|
{
|
|
return Board::systemOnly()
|
|
->where('board_code', $code)
|
|
->where('is_active', true)
|
|
->first();
|
|
}
|
|
|
|
/**
|
|
* 테넌트 게시판 코드로 조회
|
|
*/
|
|
public function getTenantBoardByCode(string $code): ?Board
|
|
{
|
|
return Board::tenantOnly($this->tenantId())
|
|
->where('board_code', $code)
|
|
->where('is_active', true)
|
|
->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();
|
|
|
|
$board = Board::create($data);
|
|
|
|
// 메뉴 자동 생성
|
|
MenuService::createMenuForBoard(
|
|
$board->board_code,
|
|
$board->name,
|
|
$board->tenant_id
|
|
);
|
|
|
|
return $board;
|
|
}
|
|
|
|
// =========================================================================
|
|
// 수정 메서드
|
|
// =========================================================================
|
|
|
|
/**
|
|
* 시스템 게시판 수정 (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;
|
|
}
|
|
|
|
// 기존 코드/이름 저장 (메뉴 업데이트용)
|
|
$oldCode = $board->board_code;
|
|
$oldName = $board->name;
|
|
|
|
$data['updated_by'] = $this->apiUserId();
|
|
$board->update($data);
|
|
|
|
// 코드 또는 이름 변경 시 메뉴도 업데이트
|
|
$newCode = $data['board_code'] ?? $oldCode;
|
|
$newName = $data['name'] ?? $oldName;
|
|
|
|
if ($oldCode !== $newCode || $oldName !== $newName) {
|
|
MenuService::updateMenuForBoard(
|
|
$oldCode,
|
|
$newCode,
|
|
$newName,
|
|
$board->tenant_id
|
|
);
|
|
}
|
|
|
|
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용)
|
|
* - 게시판 삭제 시 메뉴도 자동 삭제 (Soft Delete)
|
|
*/
|
|
public function deleteTenantBoard(int $id): bool
|
|
{
|
|
$board = Board::tenantOnly($this->tenantId())->find($id);
|
|
|
|
if (! $board) {
|
|
return false;
|
|
}
|
|
|
|
$boardCode = $board->board_code;
|
|
$tenantId = $board->tenant_id;
|
|
|
|
$board->deleted_by = $this->apiUserId();
|
|
$board->save();
|
|
$board->delete();
|
|
|
|
// 메뉴도 함께 삭제 (Soft Delete)
|
|
MenuService::deleteMenuForBoard($boardCode, $tenantId);
|
|
|
|
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;
|
|
}
|
|
}
|