본문으로 건너뛰기

반응형→적응형 스킨 전환 시 프론트 오류 수정

PHP 8 · GODO26
변경 파일 수: 8개
변경 파일 목록
총 8개
변경 파일 코드
추가삭제
Admin/design/design_skin_list.php+16
변경 전design_skin_list.php
const skinDevice = targetType === SKIN_TYPE.RESPONSIVE ? 'front' : targetType;
const deviceLabel = skinDevice === 'front' ? 'PC' : '모바일';
const otherDeviceLabel = skinDevice === 'front' ? '모바일' : 'PC';
 
 
 
 
 
 
 
 
return {
message: `${skinName} 스킨을 게시하시겠습니까?`,
subMessage: `<p class="layer-description--sub">현재 선택한 ${deviceLabel} 스킨만 게시할 경우, 일부 디바이스에서 페이지 접근 오류가 발생할 수 있습니다.<br><br>정상적인 서비스 제공을 위해 ${otherDeviceLabel} 스킨을 함께 게시해 주세요.<br><br>※ 모바일 스킨은 [모바일샵 설정 > 사용함] 상태에서만 정상적으로 노출됩니다.<br>※ [확인] 클릭 시 스킨이 게시되며, '모바일샵 설정' 페이지로 바로 이동합니다.</p>`,
skinName,
);
 
 
 
 
 
 
 
 
 
NCDSConfirm({
message: config.message,
subMessage: config.subMessage
 
변경 후design_skin_list.php
const skinDevice = targetType === SKIN_TYPE.RESPONSIVE ? 'front' : targetType;
const deviceLabel = skinDevice === 'front' ? 'PC' : '모바일';
const otherDeviceLabel = skinDevice === 'front' ? '모바일' : 'PC';
// 모바일만 먼저 게시하면 PC 사용스킨이 비어 PC 프론트 전체가 열리지 않는다
if (skinDevice === 'mobile') {
return {
message: 'PC 스킨을 먼저 게시해 주세요.',
subMessage: '<p class="layer-description--sub">현재 반응형 스킨을 사용 중입니다. 적응형 스킨으로 변경하려면 PC 스킨을 먼저 게시한 뒤 모바일 스킨을 게시해 주세요.</p>',
onConfirm: 'block'
};
}
return {
message: `${skinName} 스킨을 게시하시겠습니까?`,
subMessage: `<p class="layer-description--sub">현재 선택한 ${deviceLabel} 스킨만 게시할 경우, 일부 디바이스에서 페이지 접근 오류가 발생할 수 있습니다.<br><br>정상적인 서비스 제공을 위해 ${otherDeviceLabel} 스킨을 함께 게시해 주세요.<br><br>※ 모바일 스킨은 [모바일샵 설정 > 사용함] 상태에서만 정상적으로 노출됩니다.<br>※ [확인] 클릭 시 스킨이 게시되며, '모바일샵 설정' 페이지로 바로 이동합니다.</p>`,
skinName,
);
 
if (config.onConfirm === 'block') {
NCDSAlert({
message: config.message,
subMessage: config.subMessage
});
return;
}
 
NCDSConfirm({
message: config.message,
subMessage: config.subMessage
 
Admin/mobile/mobile_config.php+14
변경 전mobile_config.php
const initialMobileShopFl = '<?= $data['mobileShopFl'] ?? 'n' ?>';
const isMyappInstalled = <?= json_encode($isMyappInstalled ?? false) ?>;
const isMyappReleased = <?= json_encode($isMyappReleased ?? false) ?>;
 
 
// 마이앱 사용 중 + 적응형 스킨 사용 중 + 모바일샵 사용안함인 경우 안내 얼럿
if (isMyappInstalled && isMyappReleased && currentSkinType === 'adaptive' && initialMobileShopFl === 'n') {
return false;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
form.target = 'ifrmProcess';
form.submit();
return false;
 
변경 후mobile_config.php
const initialMobileShopFl = '<?= $data['mobileShopFl'] ?? 'n' ?>';
const isMyappInstalled = <?= json_encode($isMyappInstalled ?? false) ?>;
const isMyappReleased = <?= json_encode($isMyappReleased ?? false) ?>;
const hasMobileLiveSkin = <?= json_encode($hasMobileLiveSkin ?? true) ?>;
 
// 마이앱 사용 중 + 적응형 스킨 사용 중 + 모바일샵 사용안함인 경우 안내 얼럿
if (isMyappInstalled && isMyappReleased && currentSkinType === 'adaptive' && initialMobileShopFl === 'n') {
return false;
}
 
// 적응형인데 모바일 사용스킨이 비어 있으면 모바일 전 페이지가 열리지 않는다
if (currentSkinType === 'adaptive' && !hasMobileLiveSkin && selectedMobileShopFl === 'y') {
NCDSConfirm({
message: '게시된 모바일 스킨이 없습니다.',
subMessage: '<p class="layer-description--sub">모바일샵을 사용하려면 \'디자인 스킨 리스트\'에서 모바일 스킨을 먼저 게시해 주세요. 모바일 스킨 없이 모바일샵을 사용하면 모바일 쇼핑몰이 열리지 않습니다.</p>'
}).then(function(result) {
if (result) {
location.href = '/design/design_skin_list.php';
}
});
return false;
}
 
form.target = 'ifrmProcess';
form.submit();
return false;
 
Component/Policy/DesignSkinPolicy.php+26-7
변경 전DesignSkinPolicy.php
if ($this->hasGlobalMallDefaultSkin() === false) {
$currentPolicy = $this->getValue(self::KEY, $this->requestPolicy['sno']);
}
 
 
 
 
$this->initBoardSkinByChangeSkinLive();
 
$validatePolicy = $this->validateSkin();
&& $newSkinType === DesignEditorSkinType::RESPONSIVE->value;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/**
* 스킨 타입 전환 시 충돌 하는 정책 초기화
*
{
// 반응형 -> 적응형 전환
if ($this->isResponsiveToAdaptiveTransition($currentPolicy)) {
// mobileLive 게시 중이면 frontLive 초기화
if (!empty($validatePolicy['mobileLive'])) {
$validatePolicy['frontLive'] = '';
\Logger::channel('designEditor')->info(__METHOD__ . ' - Responsive to Adaptive: frontLive reset (mobile skin publish)');
}
// frontLive 게시 중이면 mobileLive 초기화
if (!empty($validatePolicy['frontLive'])) {
$validatePolicy['mobileLive'] = '';
\Logger::channel('designEditor')->info(__METHOD__ . ' - Responsive to Adaptive: mobileLive reset (PC skin publish)');
}
 
}
 
// 적응형 -> 반응형 전환
 
변경 후DesignSkinPolicy.php
if ($this->hasGlobalMallDefaultSkin() === false) {
$currentPolicy = $this->getValue(self::KEY, $this->requestPolicy['sno']);
}
// 게시판 테마가 먼저 바뀐 뒤 거부되면 사용스킨과 게시판 테마가 어긋난 채 남는다
if ($this->requestPolicy['skinUse'] === 'Live') {
$this->validateResponsiveSkinPublishOrder($currentPolicy);
}
$this->initBoardSkinByChangeSkinLive();
 
$validatePolicy = $this->validateSkin();
&& $newSkinType === DesignEditorSkinType::RESPONSIVE->value;
}
 
/**
* 반응형 사용 중 PC 스킨 없이 모바일 스킨만 게시하는 요청 거부
*
* @param array $currentPolicy
* @return void
* @throws Exception
*/
protected function validateResponsiveSkinPublishOrder(array $currentPolicy): void
{
if (!$this->isResponsiveToAdaptiveTransition($currentPolicy)) {
return;
}
 
// 모바일만 먼저 게시하면 PC 사용스킨이 비어 PC 프론트 전체가 열리지 않는다
if (empty($this->requestPolicy['frontLive']) && !empty($this->requestPolicy['mobileLive'])) {
throw new Exception(__('반응형 스킨 사용 중에는 PC 스킨을 먼저 게시해 주세요.'));
}
}
 
/**
* 스킨 타입 전환 시 충돌 하는 정책 초기화
*
{
// 반응형 -> 적응형 전환
if ($this->isResponsiveToAdaptiveTransition($currentPolicy)) {
// frontLive 만 게시 중이면 mobileLive 초기화
if (!empty($validatePolicy['frontLive']) && empty($validatePolicy['mobileLive'])) {
 
 
 
 
 
$validatePolicy['mobileLive'] = '';
\Logger::channel('designEditor')->info(__METHOD__ . ' - Responsive to Adaptive: mobileLive reset (PC skin publish)');
}
// PC·모바일을 한 요청에 함께 게시하면 둘 다 유지하되 게시판 테마는 saveSkin 이 한쪽만 갱신하므로, 동시 게시 호출부를 만들 때 initialSaveSkin 처럼 양쪽 테마 갱신을 함께 넣어야 한다
}
 
// 적응형 -> 반응형 전환
 
Component/Policy/Policy.php+30
변경 전Policy.php
use Framework\Utility\HttpUtils;
use Framework\Utility\StringUtils;
use Framework\Debug\Exception\AlertCloseException;
 
use Globals;
 
use Logger;
use Origin\Service\Policy\ShopInfoChangedTopicService;
use Request;
*/
public function saveMobileConfig($getValue)
{
 
 
// 이미지 폴더의 체크
$imagePath = UserFilePath::data('mobile');
if ($imagePath->isDir() === false) {
}
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/**
* 모바일샵 디자인 설정 저장하기
*
 
변경 후Policy.php
use Framework\Utility\HttpUtils;
use Framework\Utility\StringUtils;
use Framework\Debug\Exception\AlertCloseException;
use Framework\Debug\Exception\LayerNotReloadException;
use Globals;
use Origin\Enum\Design\DesignEditorSkinType;
use Logger;
use Origin\Service\Policy\ShopInfoChangedTopicService;
use Request;
*/
public function saveMobileConfig($getValue)
{
$this->validateMobileShopUsable($getValue);
 
// 이미지 폴더의 체크
$imagePath = UserFilePath::data('mobile');
if ($imagePath->isDir() === false) {
}
}
 
/**
* 모바일샵 사용함 저장 요청을 현재 사용스킨 기준으로 거부
*
* @param array $getValue 모바일샵 설정 저장 요청 (mobileShopFl: y|n)
* @return void
* @throws LayerNotReloadException
*/
protected function validateMobileShopUsable(array $getValue): void
{
if (($getValue['mobileShopFl'] ?? '') !== 'y') {
return;
}
 
$skinPolicy = $this->getValue('design.skin') ?: [];
$skinType = $skinPolicy['skinType'] ?? DesignEditorSkinType::ADAPTIVE->value;
 
if ($skinType === DesignEditorSkinType::RESPONSIVE->value) {
throw new LayerNotReloadException(__('반응형 스킨 사용 중에는 모바일샵을 사용할 수 없습니다. \'디자인 스킨 리스트\'에서 적응형 스킨으로 변경해 주세요.'));
}
 
// 모바일 사용스킨이 비면 모바일 프론트 전체가 503 으로 열리지 않는다
if (empty($skinPolicy['mobileLive'])) {
throw new LayerNotReloadException(__('게시된 모바일 스킨이 없어 모바일샵을 사용할 수 없습니다. 모바일 스킨을 먼저 게시해 주세요.'));
}
}
 
/**
* 모바일샵 디자인 설정 저장하기
*
 
Controller/Admin/Mobile/MobileConfigController.php+1
변경 전MobileConfigController.php
$this->setData('browserCheck', $browserCheck);
$this->setData('checked', $checked);
$this->setData('currentSkinType', $currentSkinType);
 
$this->setData('isMyappInstalled', $isMyappInstalled);
$this->setData('isMyappReleased', $isMyappReleased);
}
 
변경 후MobileConfigController.php
$this->setData('browserCheck', $browserCheck);
$this->setData('checked', $checked);
$this->setData('currentSkinType', $currentSkinType);
$this->setData('hasMobileLiveSkin', !empty($designSkinConfig['mobileLive']));
$this->setData('isMyappInstalled', $isMyappInstalled);
$this->setData('isMyappReleased', $isMyappReleased);
}
 
Core/Base/Interceptor/UserLayoutFront.php+24
변경 전UserLayoutFront.php
{
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/**
* {@inheritDoc}
*/
public function preHandle(AbstractController $controller)
{
 
 
 
 
// 현재 페이지가 index 인경우 main -> index 로 처리 (스킨 동기화 처리)
if ($controller->getPageName() === 'index') {
$currentPageName = gd_entryway('front');
 
변경 후UserLayoutFront.php
{
}
 
/**
* @throws HttpException
*/
protected function validateUsingSkinName(?string $skinName): void
{
// 스킨 전환 직후 사용스킨이 비면 이후 스킨 경로 해석에서 Fatal 이 나므로 진입부에서 오류 화면으로 끊는다
if (empty($skinName)) {
Logger::channel('designEditor')->error('사용스킨이 지정되지 않아 레이아웃을 구성할 수 없습니다.', [
'skinKey' => 'gSkin.frontSkinName',
]);
throw new HttpException('not exists using skin', 503);
}
}
 
protected function isLayoutlessRequest(string $phpSelf): bool
{
// PG 통보·처리 요청은 레이아웃을 그리지 않아 사용스킨이 비어도 처리됐으므로 막지 않는다
return str_starts_with($phpSelf, '/payment/') || str_contains(basename($phpSelf), '_ps');
}
 
/**
* {@inheritDoc}
*/
public function preHandle(AbstractController $controller)
{
if (!$this->isLayoutlessRequest(Request::getPhpSelf())) {
$this->validateUsingSkinName(Globals::get('gSkin.frontSkinName'));
}
 
// 현재 페이지가 index 인경우 main -> index 로 처리 (스킨 동기화 처리)
if ($controller->getPageName() === 'index') {
$currentPageName = gd_entryway('front');
 
Core/Base/Interceptor/UserLayoutMobile.php+38-1
변경 전UserLayoutMobile.php
{
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/**
* {@inheritDoc}
*/
public function preHandle(AbstractController $controller)
{
 
 
 
 
// 현재 페이지가 index 인경우 main -> index 로 처리 (스킨 동기화 처리)
if ($controller->getPageName() === 'index') {
$currentPageName = gd_entryway('mobile');
// 상단 배경이미지
if (empty($cfg['outline_header']) === false) {
if (empty($pagesInfo[$cfg['outline_header']]['inbg_img']) === false) {
$cfg['topbg_img'] = UserFilePath::frontSkin(Globals::get('gSkin.frontSkinName'), 'img', 'codi', $pagesInfo[$cfg['outline_header']]['inbg_img'])->www();
 
 
 
}
}
 
return gd_array_key_exists($outlineName, $dataFile) && $dataFile[$outlineName] != 'noprint' ? $dataFile[$outlineName] : '';
}
 
 
 
 
 
 
 
 
 
 
 
/**
* 정기결제(배송) 사용 여부 조회
*
 
변경 후UserLayoutMobile.php
{
}
 
/**
* @throws HttpException
*/
protected function validateUsingSkinName(?string $skinName): void
{
// 스킨 전환 직후 사용스킨이 비면 이후 스킨 경로 해석에서 Fatal 이 나므로 진입부에서 오류 화면으로 끊는다
if (empty($skinName)) {
Logger::channel('designEditor')->error('사용스킨이 지정되지 않아 레이아웃을 구성할 수 없습니다.', [
'skinKey' => 'gSkin.mobileSkinName',
]);
throw new HttpException('not exists using skin', 503);
}
}
 
protected function isLayoutlessRequest(string $phpSelf): bool
{
// PG 통보·처리 요청은 레이아웃을 그리지 않아 사용스킨이 비어도 처리됐으므로 막지 않는다
return str_starts_with($phpSelf, '/payment/') || str_contains(basename($phpSelf), '_ps');
}
 
/**
* {@inheritDoc}
*/
public function preHandle(AbstractController $controller)
{
if (!$this->isLayoutlessRequest(Request::getPhpSelf())) {
$this->validateUsingSkinName(Globals::get('gSkin.mobileSkinName'));
}
 
// 현재 페이지가 index 인경우 main -> index 로 처리 (스킨 동기화 처리)
if ($controller->getPageName() === 'index') {
$currentPageName = gd_entryway('mobile');
// 상단 배경이미지
if (empty($cfg['outline_header']) === false) {
if (empty($pagesInfo[$cfg['outline_header']]['inbg_img']) === false) {
$topBgImg = $this->getTopBgImageUrl(Globals::get('gSkin.frontSkinName'), $pagesInfo[$cfg['outline_header']]['inbg_img']);
if (!is_null($topBgImg)) {
$cfg['topbg_img'] = $topBgImg;
}
}
}
 
return gd_array_key_exists($outlineName, $dataFile) && $dataFile[$outlineName] != 'noprint' ? $dataFile[$outlineName] : '';
}
 
protected function getTopBgImageUrl(?string $frontSkinName, string $imageName): ?string
{
// 반응형에서 적응형으로 바꾸며 모바일 스킨만 게시하면 PC 사용스킨이 비어도 모바일은 진입 검사를 통과한다
if (empty($frontSkinName)) {
return null;
}
 
return UserFilePath::frontSkin($frontSkinName, 'img', 'codi', $imageName)->www();
}
 
/**
* 정기결제(배송) 사용 여부 조회
*
 
Framework/Debug/Handler/HttpHandler.php+11-1
변경 전HttpHandler.php
$seoPolicy = gd_policy('basic.seo', $mallBySession);
$seoData = is_array($seoPolicy) ? ($seoPolicy['errPage'] ?? []) : [];
 
if (($seoData['useFl'] ?? '') == 'y') {
$exErrorPage = [
'/payment/payment/payco/pg_start.php',
];
// @TODO 에러가 핸들링 되지 않는 부분에 대한 처리 (정적 HTML을 불러와 별도 처리하는 식의 처리가 필요)
}
}
 
 
 
 
 
 
 
 
 
 
}
 
변경 후HttpHandler.php
$seoPolicy = gd_policy('basic.seo', $mallBySession);
$seoData = is_array($seoPolicy) ? ($seoPolicy['errPage'] ?? []) : [];
 
if ($this->isErrorPageRedirectable($exception, $seoData)) {
$exErrorPage = [
'/payment/payment/payco/pg_start.php',
];
// @TODO 에러가 핸들링 되지 않는 부분에 대한 처리 (정적 HTML을 불러와 별도 처리하는 식의 처리가 필요)
}
}
 
protected function isErrorPageRedirectable(\Throwable $exception, array $seoData): bool
{
// 503 은 사용스킨이 비어 모든 프론트 페이지가 같은 예외를 던지는 상태라, 에러 페이지로 보내면 그 페이지에서 다시 503 이 나 리다이렉트가 반복된다
if ($exception->getCode() === 503) {
return false;
}
 
return ($seoData['useFl'] ?? '') == 'y';
}
}