diff --git a/hwe/func.php b/hwe/func.php index b680d36c..5c89d774 100644 --- a/hwe/func.php +++ b/hwe/func.php @@ -2345,7 +2345,7 @@ function getRandTurn($term, ?\DateTimeInterface $baseDateTime = null) $randSecond = Util::randRangeInt(0, 60 * $term - 1); $randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수 - return $baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s.u'); + return TimeUtil::format($baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction)), true); } function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null) diff --git a/hwe/func_converter.php b/hwe/func_converter.php index f8d80927..4d0f3716 100644 --- a/hwe/func_converter.php +++ b/hwe/func_converter.php @@ -369,7 +369,7 @@ function getAPIExecutorClass($path){ throw new \InvalidArgumentException("{$path}는 올바른 API 지시자가 아님"); } - $classPath = ($basePath.$path); + $classPath = str_replace('/', '\\', $basePath.$path); if(class_exists($classPath)){ return $classPath; @@ -377,7 +377,7 @@ function getAPIExecutorClass($path){ throw new \InvalidArgumentException("{$path}는 올바른 API 경로가 아님"); } -function buildAPIExecutorClass(string $type, string $rootPath, array $args):\sammo\BaseAPI{ +function buildAPIExecutorClass($type, string $rootPath, array $args):\sammo\BaseAPI{ $class = getAPIExecutorClass($type); return new $class($rootPath, $args); } diff --git a/hwe/func_gamerule.php b/hwe/func_gamerule.php index 80ff03d0..a4d9b355 100644 --- a/hwe/func_gamerule.php +++ b/hwe/func_gamerule.php @@ -1158,13 +1158,13 @@ function resetInheritanceUser(int $userID, bool $isRebirth=false):float{ $inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}"); $totalPoint = 0; $allPoints = $inheritStor->getAll(); - if(count($allPoints) == 0){ + if(!$allPoints || count($allPoints) == 0){ //비었으므로 리셋 안함 return 0; } if(count($allPoints) == 1 && key_exists('previous', $allPoints)){ //이미 리셋되었으므로 리셋 안함 - return $allPoints['previous']; + return $allPoints['previous'][0]; } foreach($allPoints as $key=>[$value,]){ if($isRebirth && key_exists($key, $rebirthDegraded)){ diff --git a/hwe/join_post.php b/hwe/join_post.php index e9fb0d22..2bf8b8b9 100644 --- a/hwe/join_post.php +++ b/hwe/join_post.php @@ -111,7 +111,7 @@ if ($inheritBonusStat) { dieMsg("보너스 능력치가 잘못 지정되었습니다. 다시 가입해주세요!"); } $sum = array_sum($inheritBonusStat); - if ($sum < 3 || $sum > 5) { + if ($sum < GameConst::$bornMinStatBonus || GameConst::$bornMaxStatBonus > 5) { dieMsg("보너스 능력치 합이 잘못 지정되었습니다. 다시 가입해주세요!"); } foreach ($inheritBonusStat as $stat) { @@ -180,7 +180,7 @@ if ($inheritBonusStat) { $pleadership = 0; $pstrength = 0; $pintel = 0; - foreach (Util::range(Util::randRangeInt(3, 5)) as $statIdx) { + foreach (Util::range(Util::randRangeInt(GameConst::$bornMinStatBonus, GameConst::$bornMaxStatBonus)) as $statIdx) { switch (Util::choiceRandomUsingWeight([$leadership, $strength, $intel])) { case 0: $pleadership++; diff --git a/hwe/sammo/API/General/Join.php b/hwe/sammo/API/General/Join.php index 63d1ab8f..99a70b7c 100644 --- a/hwe/sammo/API/General/Join.php +++ b/hwe/sammo/API/General/Join.php @@ -80,7 +80,7 @@ class Join extends \sammo\BaseAPI public function launch(?Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag) { - if($session === null){ + if ($session === null) { throw "invalid session"; } @@ -98,10 +98,10 @@ class Join extends \sammo\BaseAPI $strength = $this->args['strength']; $intel = $this->args['intel']; - $inheritSpecial = $this->args['inheritSpecial']??null; - $inheritTurntime =$this->args['inheritTurntime']??null; - $inheritCity = $this->args['inheritCity']??null; - $inheritBonusStat = $this->args['inheritBonusStat']??null; + $inheritSpecial = $this->args['inheritSpecial'] ?? null; + $inheritTurntime = $this->args['inheritTurntime'] ?? null; + $inheritCity = $this->args['inheritCity'] ?? null; + $inheritBonusStat = $this->args['inheritBonusStat'] ?? null; $rootDB = RootDB::db(); //회원 테이블에서 정보확인 @@ -277,11 +277,11 @@ class Join extends \sammo\BaseAPI $experience *= 0.8; } - if ($inheritTurntime === null) { + if ($inheritTurntime !== null) { $inheritTurntime = $inheritTurntime % ($gameStor->turnterm * 60); $inheritTurntime += Util::randRangeInt(0, 999999) / 1000000; - $turntime = cutTurn($admin['turntime'], $admin['turnterm']); - $turntime = TimeUtil::nowAddSeconds($inheritTurntime, true); + $turntime = new \DateTimeImmutable(cutTurn($admin['turntime'], $admin['turnterm'])); + $turntime = TimeUtil::format($turntime->add(TimeUtil::secondsToDateInterval($inheritTurntime)), true); } else { $turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime'])); } diff --git a/hwe/sammo/GameConstBase.php b/hwe/sammo/GameConstBase.php index b90b2715..37b61b89 100644 --- a/hwe/sammo/GameConstBase.php +++ b/hwe/sammo/GameConstBase.php @@ -144,6 +144,11 @@ class GameConstBase /** @var int 거병,임관 제한 기간 */ public static $joinActionLimit = 12; + /** @var int 장수 생성시 능력치 최소 보너스 */ + public static $bornMinStatBonus = 3; + /** @var int 장수 생성시 능력치 최대 보너스 */ + public static $bornMaxStatBonus = 5; + /** @var array 선택 가능한 국가 성향 */ public static $availableNationType = [ 'che_도적', 'che_명가', 'che_음양가', 'che_종횡가', 'che_불가', 'che_오두미도', 'che_태평도', 'che_도가', diff --git a/hwe/scss/game_bg.scss b/hwe/scss/game_bg.scss index bac638f0..716bcecd 100644 --- a/hwe/scss/game_bg.scss +++ b/hwe/scss/game_bg.scss @@ -10,6 +10,7 @@ html { color: white; } +//TODO: 삭제!! table.tb_layout { border-collapse: collapse; padding: 0px; @@ -17,7 +18,8 @@ table.tb_layout { word-break: break-all; } -html, body{ +html, +body { font-size: 13px; } @@ -30,10 +32,23 @@ html, body{ } -.float-left{ - float:left; +.float-left { + float: left; } -.float-right{ - float:right; +.float-right { + float: right; +} + + +.a-right { + text-align: right; +} + +.a-left { + text-align: left; +} + +.a-center { + text-align: center; } \ No newline at end of file diff --git a/hwe/ts/Join.vue b/hwe/ts/Join.vue new file mode 100644 index 00000000..b813774c --- /dev/null +++ b/hwe/ts/Join.vue @@ -0,0 +1,348 @@ + + + \ No newline at end of file diff --git a/hwe/ts/battle_simulator.ts b/hwe/ts/battle_simulator.ts index 29c06159..08b2ae1c 100644 --- a/hwe/ts/battle_simulator.ts +++ b/hwe/ts/battle_simulator.ts @@ -6,7 +6,8 @@ import 'bootstrap'; import download from 'downloadjs'; import { unwrap } from "./util/unwrap"; import { isInteger } from 'lodash'; -import { combineArray, errUnknown, getNpcColor, isBrightColor } from './common_legacy'; +import { combineArray, errUnknown, getNpcColor } from './common_legacy'; +import { isBrightColor } from "./util/isBrightColor"; import { numberWithCommas } from "./util/numberWithCommas"; import { unwrap_any } from './util/unwrap_any'; import { BasicGeneralListResponse, InvalidResponse } from './defs'; diff --git a/hwe/ts/common_deprecated.ts b/hwe/ts/common_deprecated.ts index a9d5a502..bd161546 100644 --- a/hwe/ts/common_deprecated.ts +++ b/hwe/ts/common_deprecated.ts @@ -1,5 +1,7 @@ import { exportWindow } from "./util/exportWindow"; -import { activateFlip, isBrightColor, getIconPath, errUnknown, errUnknownToast, quickReject, initTooltip } from "./common_legacy"; +import { activateFlip, errUnknown, errUnknownToast, quickReject, initTooltip } from "./common_legacy"; +import { isBrightColor } from "./util/isBrightColor"; +import { getIconPath } from "./util/getIconPath"; import { mb_strwidth } from "./util/mb_strwidth"; import { TemplateEngine } from "./util/TemplateEngine"; import { escapeHtml } from "./legacy/escapeHtml"; diff --git a/hwe/ts/common_legacy.ts b/hwe/ts/common_legacy.ts index a3f247b6..5a686eda 100644 --- a/hwe/ts/common_legacy.ts +++ b/hwe/ts/common_legacy.ts @@ -1,4 +1,3 @@ -import { unwrap } from "./util/unwrap"; import $ from "jquery"; import axios from "axios"; @@ -31,24 +30,6 @@ export function stringFormat(text: string, ...args: (string | number)[]): string }); } -export function hexToRgb(hex: string): { r: number, g: number, b: number } | null { - const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result ? { - r: parseInt(result[1], 16), - g: parseInt(result[2], 16), - b: parseInt(result[3], 16) - } : null; -} - -export function isBrightColor(color: string): boolean { - const cv = unwrap(hexToRgb(color)); - if ((cv.r * 0.299 + cv.g * 0.587 + cv.b * 0.114) > 140) { - return true; - } else { - return false; - } -} - /** * 게임내에서 지원하는 color type만 선택할 수 있도록 해주는 함수 * @param {string} color #AAAAAA 또는 AAAAAA 형태로 작성된 RGB hex color string @@ -82,15 +63,6 @@ declare global { linkifyStr: (v: string, k?: Record) => string; } } -export function getIconPath(imgsvr: boolean | 1 | 0, picture: string): string { - // ../d_shared/common_path.js 필요 - if (!imgsvr) { - return window.pathConfig.sharedIcon + '/' + picture; - } else { - return window.pathConfig.root + '/d_pic/' + picture; - } -} - export function activateFlip($obj?: JQuery): void { let $result: JQuery; if ($obj === undefined) { diff --git a/hwe/ts/diplomacy.ts b/hwe/ts/diplomacy.ts index 546aff5d..160be3d3 100644 --- a/hwe/ts/diplomacy.ts +++ b/hwe/ts/diplomacy.ts @@ -1,7 +1,7 @@ import $ from 'jquery'; import { unwrap_any } from './util/unwrap_any'; import axios from 'axios'; -import { isBrightColor } from './common_legacy'; +import { isBrightColor } from "./util/isBrightColor"; import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest'; import { isString } from 'lodash'; import { convertFormData } from './util/convertFormData'; diff --git a/hwe/ts/gateway/entrance.ts b/hwe/ts/gateway/entrance.ts index c8e6c32b..753e9f45 100644 --- a/hwe/ts/gateway/entrance.ts +++ b/hwe/ts/gateway/entrance.ts @@ -61,7 +61,7 @@ const serverLoginBtn = ""; // eslint-disable-next-line @typescript-eslint/no-unused-vars -const serverCreateBtn = " stats.max || + strength > stats.max || + intel > stats.max || + leadership < stats.min || + strength < stats.min || + intel < stats.min + ) { + return abilityRand(); + } + + return [leadership, strength, intel]; +} + +export function abilityLeadpow(): [number, number, number] { + let leadership = Math.random() * 6; + let strength = Math.random() * 6; + let intel = Math.random() * 1; + const rate = leadership + strength + intel; + + leadership = Math.floor((leadership / rate) * stats.total); + strength = Math.floor((strength / rate) * stats.total); + intel = Math.floor((intel / rate) * stats.total); + + while (leadership + strength + intel < stats.total) { + strength += 1; + } + + if (intel < stats.min) { + leadership -= stats.min - intel; + intel = stats.min; + } + + if (leadership > stats.max) { + strength += leadership - stats.max; + leadership = stats.max; + } + + if (strength > stats.max) { + leadership += strength - stats.max; + strength = stats.max; + } + + if (leadership > stats.max) { + intel += leadership - stats.max; + leadership = stats.max; + } + + return [leadership, strength, intel]; +} + +export function abilityLeadint(): [number, number, number] { + let leadership = Math.random() * 6; + let strength = Math.random() * 1; + let intel = Math.random() * 6; + const rate = leadership + strength + intel; + + leadership = Math.floor((leadership / rate) * stats.total); + strength = Math.floor((strength / rate) * stats.total); + intel = Math.floor((intel / rate) * stats.total); + + while (leadership + strength + intel < stats.total) { + intel += 1; + } + + if (strength < stats.min) { + leadership -= stats.min - strength; + strength = stats.min; + } + + if (leadership > stats.max) { + intel += leadership - stats.max; + leadership = stats.max; + } + + if (intel > stats.max) { + leadership += intel - stats.max; + intel = stats.max; + } + + if (leadership > stats.max) { + strength += leadership - stats.max; + leadership = stats.max; + } + + return [leadership, strength, intel]; +} + +export function abilityPowint(): [number, number, number] { + let leadership = Math.random() * 1; + let strength = Math.random() * 6; + let intel = Math.random() * 6; + const rate = leadership + strength + intel; + + leadership = Math.floor((leadership / rate) * stats.total); + strength = Math.floor((strength / rate) * stats.total); + intel = Math.floor((intel / rate) * stats.total); + + while (leadership + strength + intel < stats.total) { + intel += 1; + } + + if (leadership < stats.min) { + strength -= stats.min - leadership; + leadership = stats.min; + } + + if (strength > stats.max) { + intel += strength - stats.max; + strength = stats.max; + } + + if (intel > stats.max) { + strength += intel - stats.max; + intel = stats.max; + } + + if (strength > stats.max) { + leadership += strength - stats.max; + strength = stats.max; + } + + return [leadership, strength, intel]; +} \ No newline at end of file diff --git a/hwe/ts/util/getIconPath.ts b/hwe/ts/util/getIconPath.ts new file mode 100644 index 00000000..74500af0 --- /dev/null +++ b/hwe/ts/util/getIconPath.ts @@ -0,0 +1,8 @@ +export function getIconPath(imgsvr: boolean | 1 | 0, picture: string): string { + // ../d_shared/common_path.js 필요 + if (!imgsvr) { + return `${window.pathConfig.sharedIcon}/${picture}`; + } else { + return `${window.pathConfig.root}/d_pic/${picture}`; + } +} diff --git a/hwe/ts/util/hexToRgb.ts b/hwe/ts/util/hexToRgb.ts new file mode 100644 index 00000000..8c396f0d --- /dev/null +++ b/hwe/ts/util/hexToRgb.ts @@ -0,0 +1,8 @@ +export function hexToRgb(hex: string): { r: number; g: number; b: number; } | null { + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +} diff --git a/hwe/ts/util/isBrightColor.ts b/hwe/ts/util/isBrightColor.ts new file mode 100644 index 00000000..b7e1b745 --- /dev/null +++ b/hwe/ts/util/isBrightColor.ts @@ -0,0 +1,11 @@ +import { unwrap } from "./unwrap"; +import { hexToRgb } from "./hexToRgb"; + +export function isBrightColor(color: string): boolean { + const cv = unwrap(hexToRgb(color)); + if ((cv.r * 0.299 + cv.g * 0.587 + cv.b * 0.114) > 140) { + return true; + } else { + return false; + } +} diff --git a/hwe/ts/v_join.ts b/hwe/ts/v_join.ts index 74a5ff71..7cbc524c 100644 --- a/hwe/ts/v_join.ts +++ b/hwe/ts/v_join.ts @@ -1 +1,4 @@ -import { createApp } from 'vue' \ No newline at end of file +import { createApp } from 'vue' +import Join from './Join.vue'; + +createApp(Join).mount('#app') \ No newline at end of file diff --git a/hwe/v_join.php b/hwe/v_join.php new file mode 100644 index 00000000..e67a3e34 --- /dev/null +++ b/hwe/v_join.php @@ -0,0 +1,104 @@ +setReadOnly(); +$userID = Session::getUserID(); + +if (!$userID) { + die(WebUtil::errorBackMsg("잘못된 접근입니다!!!")); +} + + +//회원 테이블에서 정보확인 +$member = RootDB::db()->queryFirstRow("SELECT no,name,picture,imgsvr,grade from member where no= %i", $userID); +if (!$member) { + die(WebUtil::errorBackMsg("잘못된 접근입니다!!!")); +} + +$db = DB::db(); + +$gameStor = KVStorage::getStorage($db, 'game_env'); +$admin = $gameStor->getValues(['block_general_create', 'show_img_level', 'maxgeneral']); +if ($admin['block_general_create']) { + die(WebUtil::errorBackMsg("잘못된 접근입니다!!!")); +} + +$alreadyJoined = $db->queryFirstField('SELECT name FROM general WHERE owner = %i', $userID); +if ($alreadyJoined) { + die(WebUtil::errorBackMsg("이미 장수를 생성했습니다: {$alreadyJoined}", './')); +} + +$gencount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc<2'); +if ($gencount >= $admin['maxgeneral']) { + die(WebUtil::errorBackMsg("더 이상 등록할 수 없습니다.")); +} + + +$nationList = $db->query('SELECT nation,`name`,color,scout FROM nation'); +$nationList = Util::convertArrayToDict($nationList, 'nation'); +//NOTE: join 안할것임 +$scoutMsgs = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'scout_msg'); +foreach ($scoutMsgs as $nationID => $scoutMsg) { + $nationList[$nationID]['scoutmsg'] = $scoutMsg; +} + + +$availablePersonality = []; +foreach (GameConst::$availablePersonality as $personalityID) { + $personalityObj = buildPersonalityClass($personalityID); + $availablePersonality[$personalityID] = [ + 'name' => $personalityObj->getName(), + 'info' => $personalityObj->getInfo(), + ]; +} + +?> + + + + + <?= UniqueConst::$serverName ?>: 장수 생성 + + + + + + + + + + UniqueConst::$serverID, + 'nationList' => array_values($nationList), + 'config' => [ + 'show_img_level' => $admin['show_img_level'] + ], + 'member' => [ + 'name' => $member['name'], + 'grade' => $member['grade'], + 'picture' => $member['picture'], + 'imgsvr' => $member['imgsvr'], + ], + 'availablePersonality' => array_merge([ + 'Random' => ['name' => '???', 'info' => '무작위 성격을 선택합니다.'] + ], $availablePersonality), + 'stats' => [ + 'min' => GameConst::$defaultStatMin, + 'max' => GameConst::$defaultStatMax, + 'total' => GameConst::$defaultStatTotal, + 'bonusMin' => GameConst::$bornMinStatBonus, + 'bonusMax' => GameConst::$bornMaxStatBonus, + ] + ]) ?> + + + +
+ + + \ No newline at end of file diff --git a/src/sammo/APIHelper.php b/src/sammo/APIHelper.php index dd3edffd..c1cb0435 100644 --- a/src/sammo/APIHelper.php +++ b/src/sammo/APIHelper.php @@ -12,11 +12,16 @@ class APIHelper public static function launch(string $rootPath) { try { - $input = json_decode(file_get_contents('php://input')); + $rawInput = file_get_contents('php://input'); + $input = Json::decode($rawInput); } catch (\Exception $e) { Json::dieWithReason($e->getMessage()); } + if(!$input){ + Json::dieWithReason("input이 비어있습니다. {$rawInput}"); + } + if (!key_exists('path', $input)) { Json::dieWithReason('path가 지정되지 않았습니다.'); } diff --git a/src/sammo/TimeUtil.php b/src/sammo/TimeUtil.php index e451c35b..107b9dd1 100644 --- a/src/sammo/TimeUtil.php +++ b/src/sammo/TimeUtil.php @@ -88,50 +88,35 @@ class TimeUtil public static function now(bool $withFraction = false): string { $obj = new \DateTime(); - if (!$withFraction) { - return $obj->format('Y-m-d H:i:s'); - } - return $obj->format('Y-m-d H:i:s.u'); + return static::format($obj, $withFraction); } public static function nowAddDays($day, bool $withFraction = false): string { $obj = new \DateTime(); $obj->add(static::secondsToDateInterval($day * 3600 * 24)); - if (!$withFraction) { - return $obj->format('Y-m-d H:i:s'); - } - return $obj->format('Y-m-d H:i:s.u'); + return static::format($obj, $withFraction); } public static function nowAddHours($hour, bool $withFraction = false): string { $obj = new \DateTime(); $obj->add(static::secondsToDateInterval($hour * 3600)); - if (!$withFraction) { - return $obj->format('Y-m-d H:i:s'); - } - return $obj->format('Y-m-d H:i:s.u'); + return static::format($obj, $withFraction); } public static function nowAddMinutes($minute, bool $withFraction = false): string { $obj = new \DateTime(); $obj->add(static::secondsToDateInterval($minute * 60)); - if (!$withFraction) { - return $obj->format('Y-m-d H:i:s'); - } - return $obj->format('Y-m-d H:i:s.u'); + return static::format($obj, $withFraction); } public static function nowAddSeconds($second, bool $withFraction = false): string { $obj = new \DateTime(); $obj->add(static::secondsToDateInterval($second)); - if (!$withFraction) { - return $obj->format('Y-m-d H:i:s'); - } - return $obj->format('Y-m-d H:i:s.u'); + return static::format($obj, $withFraction); } public static function secondsToDateTime(float $fullSeconds, bool $isDateTimeImmutable = false, bool $isUTC = false): \DateTimeInterface @@ -188,6 +173,13 @@ class TimeUtil return $seconds; } + public static function format(\DateTimeInterface $dateTime, bool $withFraction): string{ + if (!$withFraction) { + return $dateTime->format('Y-m-d H:i:s'); + } + return $dateTime->format('Y-m-d H:i:s.u'); + } + /** * $baseYear, $baseMonth 부터 $afterMonth 개월 이내인지. $afterMonth 포함. * diff --git a/src/sammo/WebUtil.php b/src/sammo/WebUtil.php index 8425457a..cc93c471 100644 --- a/src/sammo/WebUtil.php +++ b/src/sammo/WebUtil.php @@ -1,4 +1,5 @@ join($path); } @@ -30,15 +31,17 @@ class WebUtil } } - public static function isAJAX(){ - return strtolower($_SERVER['HTTP_X_REQUESTED_WITH']??null) === 'xmlhttprequest'; + public static function isAJAX() + { + return strtolower($_SERVER['HTTP_X_REQUESTED_WITH'] ?? null) === 'xmlhttprequest'; } - public static function requireAJAX():void{ - if(!static::isAJAX()){ + public static function requireAJAX(): void + { + if (!static::isAJAX()) { Json::die([ - 'result'=>false, - 'reason'=>'no ajax' + 'result' => false, + 'reason' => 'no ajax' ]); } } @@ -81,23 +84,23 @@ class WebUtil //Use a switch statement to figure out the exact error. switch ($jsonError) { case JSON_ERROR_DEPTH: - $error .= 'Maximum depth exceeded! : '.$content; - break; + $error .= 'Maximum depth exceeded! : ' . $content; + break; case JSON_ERROR_STATE_MISMATCH: - $error .= 'Underflow or the modes mismatch! : '.$content; - break; + $error .= 'Underflow or the modes mismatch! : ' . $content; + break; case JSON_ERROR_CTRL_CHAR: - $error .= 'Unexpected control character found : '.$content; - break; + $error .= 'Unexpected control character found : ' . $content; + break; case JSON_ERROR_SYNTAX: - $error .= 'Malformed JSON : '.$content; - break; + $error .= 'Malformed JSON : ' . $content; + break; case JSON_ERROR_UTF8: - $error .= 'Malformed UTF-8 characters found! : '.$content; - break; + $error .= 'Malformed UTF-8 characters found! : ' . $content; + break; default: - $error .= 'Unknown error! : '.$content; - break; + $error .= 'Unknown error! : ' . $content; + break; } throw new \Exception($error); } @@ -105,89 +108,89 @@ class WebUtil return $decoded; } - public static function preloadAsset(string $path, string $type){ + public static function preloadAsset(string $path, string $type) + { $upath = \phpUri::parse($path); $path = $upath->join(''); - if(!$upath->scheme){ - if(!file_exists($upath->path)){ + if (!$upath->scheme) { + if (!file_exists($upath->path)) { return "\n"; } $mtime = filemtime($upath->path); - if($upath->query){ - $tail = '&'.$mtime; + if ($upath->query) { + $tail = '&' . $mtime; + } else { + $tail = '?' . $mtime; } - else{ - $tail = '?'.$mtime; - } - } - else{ + } else { $tail = ''; } return "\n"; } - public static function preloadCSS(string $path){ + public static function preloadCSS(string $path) + { return static::preloadAsset($path, 'style'); } - public static function preloadJS(string $path){ + public static function preloadJS(string $path) + { return static::preloadAsset($path, 'script'); } - public static function printJS(string $path, bool $isDefer=false){ + public static function printJS(string $path, bool $isDefer = false) + { //async 옵션 고려? $upath = \phpUri::parse($path); $path = $upath->join(''); - if(!$upath->scheme){ - if(!file_exists($upath->path)){ + if (!$upath->scheme) { + if (!file_exists($upath->path)) { return "\n"; } $mtime = filemtime($upath->path); - if($upath->query){ - $tail = '&'.$mtime; + if ($upath->query) { + $tail = '&' . $mtime; + } else { + $tail = '?' . $mtime; } - else{ - $tail = '?'.$mtime; - } - } - else{ + } else { $tail = ''; } - $typeText = $isDefer?'defer':''; + $typeText = $isDefer ? 'defer' : ''; return "\n"; } - public static function printCSS(string $path){ + public static function printCSS(string $path) + { $upath = \phpUri::parse($path); $path = $upath->join(''); - if(!$upath->scheme){ - if(!file_exists($upath->path)){ + if (!$upath->scheme) { + if (!file_exists($upath->path)) { return "\n"; } $mtime = filemtime($upath->path); - if($upath->query){ - $tail = '&'.$mtime; + if ($upath->query) { + $tail = '&' . $mtime; + } else { + $tail = '?' . $mtime; } - else{ - $tail = '?'.$mtime; - } - } - else{ + } else { $tail = ''; } return "\n"; } - public static function printStaticValues(array $values, bool $pretty=true){ - if(!count($values)){ + public static function printStaticValues(array $values, bool $pretty = true) + { + if (!count($values)) { return; } $lines = ["\n"; @@ -195,13 +198,14 @@ class WebUtil return join("\n", $lines); } - public static function htmlPurify(?string $text): string{ - if(!$text){ + public static function htmlPurify(?string $text): string + { + if (!$text) { return ''; } $config = \HTMLPurifier_HTML5Config::createDefault(); - $config->set('Filter.Custom', array (new \HTMLPurifier_Filter_YouTube())); + $config->set('Filter.Custom', array(new \HTMLPurifier_Filter_YouTube())); $config->set('HTML.SafeIframe', true); $config->set('URI.SafeIframeRegexp', '%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%'); //allow YouTube and Vimeo $def = $config->getHTMLDefinition(); @@ -210,19 +214,32 @@ class WebUtil return $purifier->purify($text); } - public static function drawMenu(string $path): string{ - if(!file_exists($path)){ + public static function errorBackMsg(string $msg, ?string $target=null): string + { + $jmsg = Json::encode($msg); + if(!$target){ + $moveNext = 'history.go(-1);'; + } + else{ + $moveNext = "location.replace('{$target}');"; + } + + return ""; + } + + public static function drawMenu(string $path): string + { + if (!file_exists($path)) { return ''; } $json = Json::decode(file_get_contents($path)); $result = []; - foreach($json as $menuItem){ + foreach ($json as $menuItem) { if (count($menuItem) == 2) { [$url, $title] = $menuItem; $targetAttr = ''; - } - else{ + } else { [$url, $title, $target] = $menuItem; $target = htmlspecialchars($target); $targetAttr = "target='$target' ";