훅 및 플러그인 개발
WordPress 스타일의 액션 및 필터 훅 시스템으로 TubePress를 확장하세요. 15개 이상의 훅 포인트, 플러그인 라이프사이클, 그리고 직접 플러그인을 만들고 패키징하는 방법을 다룹니다.
플러그인은 코어를 건드리지 않고 TubePress에 기능을 추가하는 방법입니다. 플러그인은 소규모 WordPress 스타일의 액션(발생 후 잊는 이벤트)과 필터(값을 수정하고 반환) 시스템을 통해 CMS에 연결됩니다. 함께 제공되는 세 가지 플러그인 — Age Gate, Backup Pro, CTR Ranking — 은 여기에 문서화된 동일한 API로 완전히 구축되었습니다.
훅 시스템
정적 HookSystem 클래스는 두 종류의 훅을 모두 관리합니다. 콜백은 오름차순 우선순위(기본값 10)로 실행되며, 콜백이 던지는 예외는 캐치되어 로그에 기록되므로 불량 플러그인 하나로 인해 페이지가 다운되는 일은 없습니다.
// Actions — do something when an event fires
HookSystem::addAction('head.meta', function () {
echo '<meta name="rating" content="adult">';
}, 10);
// Filters — receive a value, return a (possibly) changed value
HookSystem::addFilter('theme.template_data', function ($data, $template) {
if ($template === 'home') {
$data['promo'] = Promo::current();
}
return $data;
});| 메서드 | 용도 |
|---|---|
addAction($hook, $cb, $priority = 10) | 액션 리스너를 등록합니다. |
doAction($hook, ...$args) | 액션을 실행합니다(코어에서 호출). |
addFilter($hook, $cb, $priority = 10) | 필터를 등록합니다. |
applyFilter($hook, $value, ...$args) | 값을 필터에 통과시키고 반환합니다. |
hasAction() / hasFilter() | 리스너가 있는지 확인합니다. |
removeAction() / removeFilter() | 훅의 모든 리스너를 분리합니다. |
사용 가능한 훅 포인트
코어는 이러한 훅을 실행합니다. 플러그인에서 직접 정의하고 실행할 수도 있습니다.
액션
| 훅 | 실행 시점 |
|---|---|
head.meta | <head> 내부, CSS 이후 — 메타 태그, 인증 태그 등을 추가합니다. |
footer.scripts | </body> 이전, JS 이후 — 분석 도구나 위젯을 추가합니다. |
routes.registered | 모든 코어 라우트가 등록된 후, 페이지 catch-all 이전. |
router.before_dispatch | 매칭된 핸들러가 실행되기 직전. 인수: 확인된 경로. |
필터
| 훅 | 수정 대상 (인수) |
|---|---|
theme.template_data | 템플릿이 렌더링되기 전의 데이터 배열. 인수: ($data, $templateName). |
head.css | 결합된 CSS 출력 문자열. |
footer.scripts | 결합된 JS 출력 문자열. |
video.card.html | 전체 비디오 카드 HTML. 인수: ($html, $video). 비어 있지 않은 문자열을 반환하면 대체됩니다. |
플러그인 구조
플러그인은 plugins/ 아래의 폴더로, 매니페스트와 PluginInterface를 구현하는 클래스로 구성됩니다.
plugins/myplugin/
├── plugin.json Manifest (name, slug, version, …)
├── myplugin.php Main class implementing PluginInterface
├── icon.svg Optional icon shown in the admin
└── … Your assets, templates, migrations매니페스트는 번들 플러그인과 동일한 형식입니다:
{
"name": "My Plugin",
"slug": "myplugin",
"description": "What it does, in one sentence.",
"version": "1.0.0",
"author": "You",
"requires": "1.0.0",
"icon": "icon.svg"
}메인 클래스는 PluginInterface의 6가지 수명 주기 메서드를 구현합니다:
| 메서드 | 호출 시점 |
|---|---|
boot() | 플러그인이 활성화된 상태의 모든 요청 시 — 여기서 훅, 라우트, 에셋을 등록합니다. |
activate() | 관리자가 플러그인을 활성화합니다. |
deactivate() | 관리자가 비활성화합니다. |
install() | 최초 활성화 시 — 테이블 생성, 설정 시드. |
uninstall() | 플러그인 제거 시 — 정리 작업을 수행합니다. |
info() | 매니페스트 데이터를 배열로 반환합니다. |
라우트 및 에셋 등록
boot()에서 모든 연결 설정을 수행합니다:
public function boot(): void
{
// A front-end route
Router::get('/promo/{code}', [PromoController::class, 'show']);
// Inject a meta tag
HookSystem::addAction('head.meta', [$this, 'meta']);
// Tweak every video card
HookSystem::addFilter('video.card.html', [$this, 'badge'], 20);
}플러그인의 예약 작업
boot()에서 CronManager를 통해 반복 작업을 등록합니다. 내장 pseudo-cron으로 실행되므로 시스템 crontab이 필요하지 않습니다. CTR 플러그인의 점수 재계산 및 Backup Pro의 예약 백업이 이 방식으로 동작합니다.
번들 플러그인 참조
배포 및 라이선스
플러그인을 비공개로 유지하거나, 자유롭게 공유하거나, 마켓플레이스를 통해 판매할 수 있습니다. 마켓플레이스는 서명된 라이선스와 도메인별 활성화를 지원합니다. 프레젠테이션 측의 동등한 기능은 테마 개발을 참조하고, 템플릿 코드에서 사용 가능한 모든 것은 테마 API 참조를 확인하세요.