feat(ckeditor5,board,ecommerce,page,core,admin_basic): 미참조 에디터 업로드 이미지 정리 신설 + 업로드 고아 동종 결함 7건 전수 해소
공개 (@Tuwasduliebst 제보) 대응. - ckeditor5: 미참조 이미지 정리 엔진 신설 — 참조 판정(hash + 파일명 2토큰, filter_reference_sources 훅으로 확장 콘텐츠 등록) + 정리 커맨드(기본 꺼짐 옵트인, 3중 게이트) + 업로드 관리 화면(권한 분리·참조 배지·개별/선택 삭제) + 기설치본 설정 백필 upgrade step - board: 임시 첨부 GC(상시) + 소프트삭제 첨부 영구 정리(옵트인) + 설정 UI, 저장 payload 누락(F4)·빈 temp 디렉토리 잔존(F5) 수정 - ecommerce: 임시 상품 이미지 GC + 카테고리 삭제 시 이미지 파일 미삭제(S4) 수정 - page: 임시 첨부 GC - 코어: 고아 첨부 정리 커맨드(옵트인, site_logo 보호) + 사이트 로고 교체 시 구 로고 재편입 차단(S6) + DB 백업 미구현 501 정직화(B3) + 플러그인 관리자 메뉴 설치·업데이트 자동 동기화(F1·F7) - 동반: 플러그인 설정 검증 오류 필드명 라벨화(F3), Toggle 노드 type 정정 수평 전개(marketing 1.0.2 bump·gdpr·ecommerce), ja 언어팩 4종, API 문서, hooks.md, 시나리오 매니페스트 8종, Playwright E2E 4종
This commit is contained in:
@@ -202,6 +202,8 @@ HTTP/1.1 200
|
||||
| upload.image_max_width | body | integer | 아니오 | min 100, max 10000 | 이미지 리사이즈 최대 너비 (px) |
|
||||
| upload.image_max_height | body | integer | 아니오 | min 100, max 10000 | 이미지 리사이즈 최대 높이 (px) |
|
||||
| upload.image_quality | body | integer | 아니오 | min 1, max 100 | 이미지 리사이즈 시 압축 품질 (1~100) |
|
||||
| upload.orphan_cleanup_enabled | body | boolean | 아니오 | — | 고아 첨부(소유자 없이 남은 첨부) 자동 정리 활성화 여부. **기본 false** — 사용자 파일을 실제로 파기하므로 운영자가 직접 켜야 동작하며, 예약 작업(`attachments:prune-orphans --scheduled`)이 이 값을 false 폴백으로 재확인한다 |
|
||||
| upload.orphan_retention_days | body | integer | 아니오 | min 1, max 3650 | 고아 첨부 보존기간(일, 기본 30). 폼 작성 중 이탈을 감안한 유예 기간이다. 하한·상한은 `config('core.settings_limits.upload_orphan_retention_days_*')` 가 정하며 화면 입력도 같은 값을 읽는다 |
|
||||
| seo.meta_title_suffix | body | string | 아니오 | max 100 | 모든 페이지 SEO 제목 뒤에 붙는 접미 문구 |
|
||||
| seo.meta_description | body | string | 아니오 | max 160 | SEO 메타 설명 (검색엔진/소셜 공유 표시 요약) |
|
||||
| seo.meta_keywords | body | string | 아니오 | max 255 | SEO 메타 키워드 (검색엔진 노출 키워드, 쉼표 구분) |
|
||||
@@ -654,14 +656,14 @@ Authorization: Bearer {YOUR_TOKEN}
|
||||
|
||||
**응답 필드** (`data` 내부)
|
||||
|
||||
_이 엔드포인트는 `data` 를 반환하지 않습니다 (성공 메시지만). 컨트롤러가 `ResponseHelper::success('settings.backup_success')` 를 데이터 없이 호출하므로 `data` 는 `null` 입니다._
|
||||
_이 엔드포인트는 성공 응답을 반환하지 않습니다. 데이터베이스 백업 기능이 아직 제공되지 않아 항상 501 로 응답합니다._
|
||||
|
||||
**응답 예시**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "데이터베이스 백업이 성공적으로 시작되었습니다.",
|
||||
"success": false,
|
||||
"message": "데이터베이스 백업 기능은 아직 제공하지 않습니다. 설정 백업은 설정 백업 기능을 이용해 주세요.",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
@@ -670,16 +672,17 @@ _이 엔드포인트는 `data` 를 반환하지 않습니다 (성공 메시지
|
||||
|
||||
| 상태코드 | 의미 | 발생 조건 |
|
||||
| --- | --- | --- |
|
||||
| 400 | Bad Request | 백업이 수행되지 않은 경우 (`settings.backup_failed`) |
|
||||
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
|
||||
| 403 | Forbidden | 요구 권한(`core.settings.update`)이 없는 경우 |
|
||||
| 500 | Internal Server Error | 백업 처리 중 예외가 발생한 경우 (`settings.backup_error`) |
|
||||
| 501 | Not Implemented | 항상 (데이터베이스 백업 미제공, `settings.database_backup_unavailable`) |
|
||||
|
||||
<!-- @generated:end -->
|
||||
|
||||
**설명**
|
||||
|
||||
데이터베이스를 백업합니다. SettingsService 에 위임하며, 성공/실패를 메시지로 반환합니다. 설정 백업(`POST /backup`)이 설정 파일만 다루는 것과 달리, 이 엔드포인트는 DB 데이터를 백업 대상으로 합니다.
|
||||
**데이터베이스 백업은 아직 제공하지 않습니다.** 이 엔드포인트는 라우트만 존재하며 호출하면 항상 501(Not Implemented)로 응답합니다. 코어에는 데이터베이스 덤프 수단이 없어 구현된 적이 없으며, 관리자 화면에도 이 기능을 호출하는 지점이 없습니다.
|
||||
|
||||
설정 파일 백업이 필요하면 `POST /api/admin/settings/backup` 을 사용하십시오 — 그쪽은 정상 동작하며 생성된 백업 경로를 `data.backup_path` 로 돌려줍니다.
|
||||
|
||||
|
||||
### POST /api/admin/settings/clear-cache
|
||||
|
||||
@@ -148,7 +148,14 @@ sirsoft-page.attachment.filter_upload_file # 페이지 첨부
|
||||
sirsoft-ecommerce.product-image.filter_upload_file # 상품 이미지
|
||||
sirsoft-ecommerce.category-image.filter_upload_file # 카테고리 이미지
|
||||
sirsoft-ecommerce.review-image.filter_upload_file # 리뷰 이미지 (공개 #96)
|
||||
sirsoft-ckeditor5.image.before_upload # 에디터 이미지
|
||||
sirsoft-ckeditor5.image.filter_upload_file # 에디터 이미지
|
||||
sirsoft-ckeditor5.image.after_upload # 에디터 이미지
|
||||
|
||||
# 업로드 잔존물 회수 — 어떤 콘텐츠에서도 쓰이지 않는 에디터 이미지의 참조 판정 대상 선언 (필터)
|
||||
# 자기 콘텐츠를 가진 확장이 이 훅으로 테이블/컬럼을 등록하지 않으면, 그 확장에서만 쓰이는
|
||||
# 이미지가 "미참조" 로 판정돼 자동 정리 대상이 된다.
|
||||
sirsoft-ckeditor5.image.filter_reference_sources # 에디터 이미지 참조 소스
|
||||
|
||||
# FormRequest Validation Rules 훅 (Filter)
|
||||
core.user.create_validation_rules
|
||||
@@ -238,6 +245,41 @@ core.seo.sitemap.after_regenerate_failed # 재생성 실패 시 (['status'=>'fai
|
||||
|
||||
`core.settings.available_public_asset_drivers` 로 등록하는 디스크는 플러그인 ServiceProvider 에서 `filesystems.disks.{id}` 정의가 함께 있어야 하며, 그 정의에 `url` 키가 있어야 직접 URL 이 생성됩니다(없으면 스트리밍 폴백). 플러그인이 비활성화되어 디스크 정의가 사라지면 저장값은 보존된 채 스트리밍으로 자동 폴백합니다.
|
||||
|
||||
#### `sirsoft-ckeditor5.image.filter_reference_sources`
|
||||
|
||||
에디터 업로드 이미지가 "어디선가 쓰이고 있는지" 판정할 때 훑을 테이블/컬럼 목록을 확장합니다. 첫 인자인 소스 배열에 다음 구조의 항목을 append 합니다.
|
||||
|
||||
| 키 | 타입 | 값 |
|
||||
| --- | --- | --- |
|
||||
| `table` | string | 테이블명 — **프리픽스 제외 원시 이름** (`board_posts`) |
|
||||
| `columns` | list\<string\> | 본문이 담긴 컬럼명 목록 (`['content']`) |
|
||||
|
||||
자기 콘텐츠에 에디터를 노출하는 확장은 이 훅을 반드시 구독해야 합니다. 등록하지 않으면 그 확장에서만 쓰이는 이미지가 "미참조" 로 판정돼 자동 정리 대상이 됩니다.
|
||||
|
||||
리스너는 테이블명 문자열만 덧붙이고 DB 에 접근하지 않습니다 — 실재 검증(테이블·컬럼 존재)과 조회는 플러그인이 수행하며, 존재하지 않는 선언은 경고만 남기고 건너뜁니다(한 확장의 잘못된 선언이 판정 전체를 멈추지 않습니다).
|
||||
|
||||
로그 사본 테이블(발송 이력·신고 스냅샷 등)은 등록하지 않습니다. 이들은 자체 보존기간으로 삭제되므로 참조 소스로 삼으면 "로그가 지워지는 순간 이미지가 고아가 되는" 역전이 생깁니다.
|
||||
|
||||
```php
|
||||
public static function getSubscribedHooks(): array
|
||||
{
|
||||
return [
|
||||
'sirsoft-ckeditor5.image.filter_reference_sources' => [
|
||||
'method' => 'addSources',
|
||||
'priority' => 10,
|
||||
'type' => 'filter',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function addSources(array $sources): array
|
||||
{
|
||||
$sources[] = ['table' => 'my_documents', 'columns' => ['body']];
|
||||
|
||||
return $sources;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 리스너 구현
|
||||
|
||||
Reference in New Issue
Block a user