refactor: unify bag and admin layout routing
This commit is contained in:
@@ -6,8 +6,9 @@ use Config\Roles;
|
||||
|
||||
if (! function_exists('admin_effective_lg_idx')) {
|
||||
/**
|
||||
* 현재 로그인한 관리자가 작업 대상으로 사용하는 지자체 PK.
|
||||
* Super/본부 관리자 → admin_selected_lg_idx, 지자체 관리자 → mb_lg_idx, 그 외 null.
|
||||
* 관리자 화면·사이트 메뉴·Bag 등에서 쓰는 작업 지자체 PK.
|
||||
* Super/본부 → admin_selected_lg_idx(미선택 시 null).
|
||||
* 지자체관리자·지정판매소·일반 사용자 → mb_lg_idx(없으면 null).
|
||||
*/
|
||||
function admin_effective_lg_idx(): ?int
|
||||
{
|
||||
@@ -16,7 +17,9 @@ if (! function_exists('admin_effective_lg_idx')) {
|
||||
$idx = session()->get('admin_selected_lg_idx');
|
||||
return $idx !== null && $idx !== '' ? (int) $idx : null;
|
||||
}
|
||||
if ($level === Roles::LEVEL_LOCAL_ADMIN) {
|
||||
if ($level === Roles::LEVEL_LOCAL_ADMIN
|
||||
|| $level === Roles::LEVEL_SHOP
|
||||
|| $level === Roles::LEVEL_CITIZEN) {
|
||||
$idx = session()->get('mb_lg_idx');
|
||||
return $idx !== null && $idx !== '' ? (int) $idx : null;
|
||||
}
|
||||
@@ -24,6 +27,23 @@ if (! function_exists('admin_effective_lg_idx')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('resolve_site_menu_lg_idx')) {
|
||||
/**
|
||||
* site 상단 메뉴(menu 테이블) 조회용 지자체 PK.
|
||||
* admin_effective_lg_idx() 우선(메뉴 관리·Bag과 동일), 없으면 mb_lg_idx, 그다음 기본 1.
|
||||
*/
|
||||
function resolve_site_menu_lg_idx(): int
|
||||
{
|
||||
$lgIdx = admin_effective_lg_idx();
|
||||
if ($lgIdx !== null) {
|
||||
return $lgIdx;
|
||||
}
|
||||
$raw = session()->get('mb_lg_idx');
|
||||
|
||||
return ($raw !== null && $raw !== '') ? (int) $raw : 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('get_admin_nav_items')) {
|
||||
/**
|
||||
* 관리자 상단 메뉴 항목 (DB menu 테이블, admin 타입, 현재 지자체·mb_level 기준, 평면 배열).
|
||||
@@ -130,11 +150,7 @@ if (! function_exists('get_site_nav_tree')) {
|
||||
function get_site_nav_tree(): array
|
||||
{
|
||||
try {
|
||||
$lgIdx = session()->get('mb_lg_idx');
|
||||
// 시민 등 지자체 정보가 세션에 없으면 기본 지자체(1) 기준으로 메뉴를 보여 준다.
|
||||
if ($lgIdx === null || $lgIdx === '') {
|
||||
$lgIdx = 1;
|
||||
}
|
||||
$lgIdx = resolve_site_menu_lg_idx();
|
||||
$typeRow = model(\App\Models\MenuTypeModel::class)->getByCode('site');
|
||||
if (! $typeRow) {
|
||||
return [];
|
||||
@@ -156,3 +172,319 @@ if (! function_exists('get_site_nav_tree')) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('current_nav_request_path')) {
|
||||
/**
|
||||
* 메뉴 활성·mm_link 비교용 현재 경로 (라우트 기준, base_url 뒤 세그먼트).
|
||||
* request->getPath() · uri_string() · SiteURI::getRoutePath() 중 비어 있지 않은 값을 사용.
|
||||
*/
|
||||
function current_nav_request_path(): string
|
||||
{
|
||||
helper('url');
|
||||
|
||||
$request = service('request');
|
||||
// 프레임워크 권장: uri_string() = baseURL 기준 경로 (우선)
|
||||
$candidates = [trim(uri_string(), '/')];
|
||||
if ($request instanceof \CodeIgniter\HTTP\IncomingRequest) {
|
||||
$candidates[] = trim((string) $request->getPath(), '/');
|
||||
}
|
||||
$uri = $request->getUri();
|
||||
if ($uri instanceof \CodeIgniter\HTTP\SiteURI) {
|
||||
$candidates[] = trim($uri->getRoutePath(), '/');
|
||||
}
|
||||
|
||||
$path = '';
|
||||
foreach ($candidates as $c) {
|
||||
if ($c !== '') {
|
||||
$path = $c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (str_starts_with($path, 'index.php/')) {
|
||||
$path = substr($path, strlen('index.php/'));
|
||||
}
|
||||
|
||||
// baseURL 에 경로가 있으면(서브폴더 설치) URI 앞에 붙은 동일 접두 제거
|
||||
$basePath = parse_url(config(\Config\App::class)->baseURL, PHP_URL_PATH);
|
||||
$basePath = is_string($basePath) ? trim($basePath, '/') : '';
|
||||
if ($basePath !== '' && $path !== '' && ($path === $basePath || str_starts_with($path, $basePath . '/'))) {
|
||||
$path = $path === $basePath ? '' : substr($path, strlen($basePath) + 1);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('normalize_menu_link_for_url')) {
|
||||
/**
|
||||
* menu.mm_link 를 base_url() 인자로 쓸 수 있는 상대 경로로 정규화합니다.
|
||||
* http(s)://... 전체 URL이면 path 만 사용하고, 앞뒤 공백·슬래시를 정리합니다.
|
||||
*/
|
||||
function normalize_menu_link_for_url(?string $mmLink): string
|
||||
{
|
||||
$s = trim((string) $mmLink);
|
||||
if ($s === '') {
|
||||
return '';
|
||||
}
|
||||
if (str_contains($s, '://')) {
|
||||
$path = parse_url($s, PHP_URL_PATH);
|
||||
$s = is_string($path) ? trim($path, '/') : '';
|
||||
} else {
|
||||
$s = trim($s, '/');
|
||||
}
|
||||
|
||||
while (str_starts_with($s, 'index.php/')) {
|
||||
$s = substr($s, strlen('index.php/'));
|
||||
}
|
||||
if (str_starts_with($s, 'public/')) {
|
||||
$s = substr($s, strlen('public/'));
|
||||
}
|
||||
|
||||
$basePath = parse_url(config(\Config\App::class)->baseURL, PHP_URL_PATH);
|
||||
$basePath = is_string($basePath) ? trim($basePath, '/') : '';
|
||||
if ($basePath !== '' && $s !== '' && ($s === $basePath || str_starts_with($s, $basePath . '/'))) {
|
||||
$s = $s === $basePath ? '' : substr($s, strlen($basePath) + 1);
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('mgmt_url')) {
|
||||
/**
|
||||
* 업무 화면 링크: 정식 URL 은 /bag/* (adminAuth). 포장 단위 CRUD 는 packaging-units/manage 로 치환.
|
||||
*/
|
||||
function mgmt_url(string $path): string
|
||||
{
|
||||
helper('url');
|
||||
$path = trim($path, '/');
|
||||
// bag/packaging-units 는 조회 전용(Bag) — CRUD 는 /bag/packaging-units/manage/* 로 분리
|
||||
if ($path === 'packaging-units') {
|
||||
$path = 'packaging-units/manage';
|
||||
} elseif (str_starts_with($path, 'packaging-units/')) {
|
||||
$path = 'packaging-units/manage/' . substr($path, strlen('packaging-units/'));
|
||||
}
|
||||
|
||||
return site_url('bag/' . $path);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('work_area_home_url')) {
|
||||
/**
|
||||
* 지자체 미선택 등으로 돌아갈 때: bag 업무 중이면 대시보드, 관리자면 admin 홈.
|
||||
*/
|
||||
function work_area_home_url(): string
|
||||
{
|
||||
helper('url');
|
||||
$seg1 = service('request')->getUri()->getSegment(1);
|
||||
|
||||
return ($seg1 === 'bag') ? site_url('dashboard') : site_url('admin');
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('format_ymd_korean')) {
|
||||
/**
|
||||
* Y-m-d 날짜를 '2026년 1월 5일' 형식으로 (월·일은 숫자, 월명은 한글 '월').
|
||||
*/
|
||||
function format_ymd_korean(?string $ymd): string
|
||||
{
|
||||
if ($ymd === null || trim($ymd) === '') {
|
||||
return '—';
|
||||
}
|
||||
$t = \DateTimeImmutable::createFromFormat('Y-m-d', trim($ymd));
|
||||
if ($t === false) {
|
||||
return $ymd;
|
||||
}
|
||||
|
||||
return $t->format('Y') . '년 ' . (int) $t->format('n') . '월 ' . (int) $t->format('j') . '일';
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('parse_ymd_from_triple')) {
|
||||
/**
|
||||
* 연·월·일 GET 값으로 Y-m-d 생성 (유효하지 않은 날짜는 null).
|
||||
*/
|
||||
function parse_ymd_from_triple(?string $y, ?string $m, ?string $d): ?string
|
||||
{
|
||||
if ($y === null || $y === '' || $m === null || $m === '' || $d === null || $d === '') {
|
||||
return null;
|
||||
}
|
||||
$yi = (int) $y;
|
||||
$mi = (int) $m;
|
||||
$di = (int) $d;
|
||||
if ($yi < 1000 || $yi > 9999 || ! checkdate($mi, $di, $yi)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return sprintf('%04d-%02d-%02d', $yi, $mi, $di);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('site_nav_resolved_link_path')) {
|
||||
/**
|
||||
* 사이트 상단 메뉴 URL 세그먼트. mm_link(DB)만 사용 (비어 있으면 빈 문자열).
|
||||
*
|
||||
* @param string|null $mmName 호환용(미사용).
|
||||
*
|
||||
* @return string base_url() 인자 세그먼트(앞뒤 슬래시 없음)
|
||||
*/
|
||||
function site_nav_resolved_link_path(?string $mmLink, ?string $mmName = null): string
|
||||
{
|
||||
return normalize_menu_link_for_url($mmLink);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('menu_link_candidate_paths')) {
|
||||
/**
|
||||
* 활성 비교용 경로 후보. DB에 "menus" 처럼 짧게 넣은 경우 실제 URI가 admin/menus·bag/… 일 수 있어,
|
||||
* 현재 요청 경로에 맞게 admin/·bag/ 접두를 붙인 후보도 만든다. (슬래시 포함·admin 단독은 그대로 1개만)
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
function menu_link_candidate_paths(?string $mmLink, string $currentPath): array
|
||||
{
|
||||
$p = normalize_menu_link_for_url($mmLink);
|
||||
if ($p === '') {
|
||||
return [];
|
||||
}
|
||||
if (str_contains($p, '/') || $p === 'admin') {
|
||||
$cands = [$p];
|
||||
if (preg_match('#^bag/packaging-units/manage(/.*)?$#', $p, $m)) {
|
||||
$cands[] = 'admin/packaging-units' . ($m[1] ?? '');
|
||||
} elseif (preg_match('#^admin/packaging-units(/.*)?$#', $p, $m)) {
|
||||
$cands[] = 'bag/packaging-units/manage' . ($m[1] ?? '');
|
||||
} elseif (str_starts_with($p, 'admin/')) {
|
||||
$cands[] = 'bag/' . substr($p, strlen('admin/'));
|
||||
} elseif (str_starts_with($p, 'bag/')) {
|
||||
$cands[] = 'admin/' . substr($p, strlen('bag/'));
|
||||
}
|
||||
|
||||
return array_values(array_unique($cands));
|
||||
}
|
||||
$out = [$p];
|
||||
if (str_starts_with($currentPath, 'admin/') || $currentPath === 'admin') {
|
||||
$out[] = 'admin/' . $p;
|
||||
}
|
||||
if (str_starts_with($currentPath, 'bag/') || $currentPath === 'bag') {
|
||||
$out[] = 'bag/' . $p;
|
||||
}
|
||||
|
||||
return array_values(array_unique($out));
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('menu_link_preferred_href_path')) {
|
||||
/**
|
||||
* base_url() 용 경로: 짧게 저장된 mm_link 는 현재 요청 기준 admin/·bag/ 후보 중 가장 알맞은 것 사용.
|
||||
*/
|
||||
function menu_link_preferred_href_path(?string $mmLink, string $currentPath): string
|
||||
{
|
||||
$cands = menu_link_candidate_paths($mmLink, $currentPath);
|
||||
if ($cands === []) {
|
||||
return '';
|
||||
}
|
||||
foreach ($cands as $c) {
|
||||
$cl = strtolower($currentPath);
|
||||
$cc = strtolower($c);
|
||||
if ($cl === $cc || str_starts_with($cl, $cc . '/')) {
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
foreach ($cands as $c) {
|
||||
if (str_contains($c, '/')) {
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
|
||||
return $cands[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('menu_single_path_matches_request')) {
|
||||
/**
|
||||
* 단일 정규 경로가 현재 요청 path 와 일치하는지.
|
||||
*
|
||||
* @param list<string> $dashboardPathAliases
|
||||
*/
|
||||
function menu_single_path_matches_request(string $path, string $currentPath, array $dashboardPathAliases = []): bool
|
||||
{
|
||||
if ($path === '') {
|
||||
return false;
|
||||
}
|
||||
$pathLower = strtolower($path);
|
||||
$currentLower = strtolower($currentPath);
|
||||
$aliasesLower = array_map(strtolower(...), $dashboardPathAliases);
|
||||
|
||||
if ($dashboardPathAliases !== []
|
||||
&& in_array($pathLower, $aliasesLower, true)
|
||||
&& in_array($currentLower, $aliasesLower, true)) {
|
||||
return true;
|
||||
}
|
||||
if ($currentLower === $pathLower) {
|
||||
return true;
|
||||
}
|
||||
if ($pathLower === 'admin') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return str_starts_with($currentLower, $pathLower . '/');
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('menu_link_matches_request')) {
|
||||
/**
|
||||
* 메뉴 mm_link(DB)가 현재 요청과 같은 메뉴인지. 비어 있으면 false.
|
||||
*
|
||||
* @param list<string> $dashboardPathAliases
|
||||
*/
|
||||
function menu_link_matches_request(?string $mmLink, string $currentPath, array $dashboardPathAliases = []): bool
|
||||
{
|
||||
foreach (menu_link_candidate_paths($mmLink, $currentPath) as $cand) {
|
||||
if (menu_single_path_matches_request($cand, $currentPath, $dashboardPathAliases)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('site_nav_link_matches_current')) {
|
||||
/**
|
||||
* 사이트 상단 메뉴 활성 여부 (경로 후보·대시보드 별칭은 menu_link_matches_request 와 동일).
|
||||
*
|
||||
* @param list<string> $dashboardPathAliases
|
||||
*/
|
||||
function site_nav_link_matches_current(?string $mmLink, string $currentPath, array $dashboardPathAliases = []): bool
|
||||
{
|
||||
return menu_link_matches_request($mmLink, $currentPath, $dashboardPathAliases);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('session_user_nav_display')) {
|
||||
/**
|
||||
* 상단 메뉴바용: 로그인 사용자 이름·역할 표시
|
||||
*
|
||||
* @return array{name: string, role_label: string}|null
|
||||
*/
|
||||
function session_user_nav_display(): ?array
|
||||
{
|
||||
if (! session()->get('logged_in')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$name = trim((string) session()->get('mb_name'));
|
||||
if ($name === '') {
|
||||
$name = (string) session()->get('mb_id');
|
||||
}
|
||||
|
||||
$level = (int) session()->get('mb_level');
|
||||
$roleLabel = config('Roles')->getLevelName($level);
|
||||
|
||||
return [
|
||||
'name' => $name,
|
||||
'role_label' => $roleLabel,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user