패치 내역
1. 전역 헬퍼 추가
클래스 메서드 (skinUrl):
php
public function skinUrl($skin, $path = '')
{
$base = dx_base_url('boards/skins/' . $this->safe($skin));
return $path ? $base . '/' . ltrim($path, '/') : $base;
}
전역 헬퍼 함수 (dx_skin_url):
php
dx_skin_url() // → .../boards/skins/business-simple
dx_skin_url('images/a.png') // → .../boards/skins/business-simple/images/a.png
dx_skin_url('', 'other') // → .../boards/skins/other (스킨 명시)
기존 dx_skin_asset()과 동일한 방식으로 $GLOBALS['dx_board_skin']을 자동으로 참조합니다.
2. Hook php5.6에러 코어 패치
1. core/hook/HookManager.php
run()과 filter() 메서드에서 콜백 실행 방식 변경:
php
// 변경 전
call_user_func($item['callback'], $args);
// 변경 후
if ($cb instanceof Closure) {
$cb($args); // 클로저 직접 호출 — PHP 5.6 참조 오류 회피
} else {
call_user_func($cb, $args);
}
2. core/functions.php
dx_add_hook() 등록 시 인자 없는 클로저 수정:
php
// 변경 전 (3곳)
dx_add_hook('dx_head', function() { ... });
dx_add_hook('dx_body_bottom',function() { ... });
dx_add_hook('dx_admin_top', function() { ... });
// 변경 후
dx_add_hook('dx_head', function($args) { ... });
dx_add_hook('dx_body_bottom',function($args) { ... });
dx_add_hook('dx_admin_top', function($args) { ... });
// PHP 5.6에서 call_user_func($callback, $args) 호출 시 클로저가 인자를 선언하지 않으면 참조 전달 오류가 발생하는 문제를 수정
3. 절대경로 dx_board_skin_url / dx_board_skin_path 패치
## 배경
DXCMS 게시판 스킨은 두 가지 위치에 설치할 수 있습니다.
| 위치 | 예시 경로 |
|------|-----------|
| `boards/skins/` | `boards/skins/d001/style.css` |
| `themes/board/` | `themes/default/board/basic/style.css` |
기존에는 위치에 따라 함수를 다르게 써야 했습니다.
```php
// boards/skins/ 에 있을 때
echo dx_skin_url('style.css');
// themes/board/ 에 있을 때
echo dx_theme_url('board/d001/style.css');
// include 할 때
include __DIR__ . '/_list_rows.php';
```
이 불편함을 해소하기 위해 **어느 위치에 있든 자동으로 탐색**하는 헬퍼 함수 2개를 추가했습니다.
---
## 탐색 순서
세 위치를 순서대로 탐색하여 **파일이 실제로 존재하는 첫 번째 경로**를 사용합니다.
```
1. boards/skins/{현재스킨}/{path}
2. themes/{현재테마}/board/{현재스킨}/{path}
3. themes/default/board/{현재스킨}/{path}
```
---
## 함수
### `dx_board_skin_url(string $path): string`
스킨 파일의 **웹 URL**을 반환합니다. CSS, JS, 이미지 로드에 사용합니다.
파일을 찾지 못하면 1순위 URL을 그대로 반환합니다 (404 허용).
```php
// CSS 로드
echo '<link rel="stylesheet" href="' . dx_board_skin_url('style.css') . '?v=' . DX_VERSION . '">';
// JS 로드
echo '<script src="' . dx_board_skin_url('board.js') . '"></script>';
// 이미지
echo '<img src="' . dx_board_skin_url('images/logo.png') . '">';
```
---
### `dx_board_skin_path(string $path): string`
스킨 파일의 **절대 파일 경로**를 반환합니다. `include` / `require` 에 사용합니다.
파일을 찾지 못하면 빈 문자열 `''` 을 반환합니다.
```php
// 바로 include
include dx_board_skin_path('_list_rows.php');
// 존재 확인 후 include
$f = dx_board_skin_path('_header.php');
if ($f) include $f;
// require
require dx_board_skin_path('_functions.php');
```
---
## 사용 예시
### 기존 방식 vs 통합 방식
```php
/* ── 기존 — 위치에 따라 다르게 작성 ── */
// boards/skins/d001/ 에 설치된 경우
echo '<link href="' . dx_skin_url('style.css') . '">';
include __DIR__ . '/_list_rows.php';
// themes/default/board/basic/ 에 설치된 경우
echo '<link href="' . dx_theme_url('board/basic/style.css') . '">';
include __DIR__ . '/_list_rows.php';
/* ── 통합 후 — 위치 상관없이 동일 ── */
echo '<link href="' . dx_board_skin_url('style.css') . '">';
include dx_board_skin_path('_list_rows.php');
```
---
### 실제 스킨 파일 적용 예 (`list.php`)
```php
<?php
if (!defined('DX_CMS')) exit('Direct access not allowed.');
// 스킨 CSS 로드 — boards/skins/ 와 themes/board/ 모두 대응
echo '<link rel="stylesheet" href="' . dx_board_skin_url('style.css') . '?v=' . DX_VERSION . '">';
// 변수 초기화 생략 ...
// _list_rows.php include — 경로 하드코딩 불필요
include dx_board_skin_path('_list_rows.php');
```
---
## 내부 구조
두 함수의 공통 탐색 로직은 `_dx_skin_candidates()` 로 분리되어 있습니다.
```
_dx_skin_candidates(path) ← 내부 공통 로직
├── dx_board_skin_url(path) ← URL 반환
└── dx_board_skin_path(path) ← 파일 경로 반환
```
---
## 설치
`boards/handler.php` 를 교체하면 즉시 적용됩니다.
기존 `dx_skin_url()`, `dx_theme_url()` 은 그대로 유지되므로 기존 스킨은 수정 없이 동작합니다.