| 1 |
/** |
| 2 |
* Single place for Yatra storefront URL shapes (admin “View” / preview). |
| 3 |
* Plain taxonomy singles: `?{destination_base}={slug}` (same pattern as trip). Align with |
| 4 |
* {@see \Yatra\Core\Routing\PlainPageMatcher} and helpers.php. |
| 5 |
*/ |
| 6 |
|
| 7 |
/** Public single-entity routes the plugin exposes on the frontend */ |
| 8 |
export type YatraPublicEntity = |
| 9 |
| "trip" |
| 10 |
| "destination" |
| 11 |
| "activity" |
| 12 |
| "category"; |
| 13 |
|
| 14 |
/** URL bases from Settings (REST) — defaults match {@see SettingsService} */ |
| 15 |
export type YatraPermalinkBases = { |
| 16 |
trip_base: string; |
| 17 |
destination_base: string; |
| 18 |
activity_base: string; |
| 19 |
trip_category_base: string; |
| 20 |
}; |
| 21 |
|
| 22 |
/** |
| 23 |
* WordPress “Plain” permalink mode (?p=…); {@see AdminAssetsProvider::buildAdminLocalizedData} |
| 24 |
* sets `yatraAdmin.permalinkStructure` to `"plain"` when `permalink_structure` is empty. |
| 25 |
*/ |
| 26 |
export function isWordPressPlainPermalink(): boolean { |
| 27 |
if (typeof window === "undefined") { |
| 28 |
return false; |
| 29 |
} |
| 30 |
const ps = (window as { yatraAdmin?: { permalinkStructure?: string } }) |
| 31 |
?.yatraAdmin?.permalinkStructure; |
| 32 |
return ps === "plain"; |
| 33 |
} |
| 34 |
|
| 35 |
export function getYatraSiteUrlFromWindow(): string { |
| 36 |
if (typeof window === "undefined") { |
| 37 |
return ""; |
| 38 |
} |
| 39 |
return ( |
| 40 |
(window as { yatraAdmin?: { siteUrl?: string } }).yatraAdmin?.siteUrl || "" |
| 41 |
); |
| 42 |
} |
| 43 |
|
| 44 |
/** |
| 45 |
* Merge saved settings with `window.yatraAdmin.tripBase` when present. |
| 46 |
*/ |
| 47 |
export function resolveYatraPermalinkBases( |
| 48 |
fromSettings?: Partial<YatraPermalinkBases> | Record<string, unknown> | null, |
| 49 |
): YatraPermalinkBases { |
| 50 |
const ya = |
| 51 |
typeof window !== "undefined" |
| 52 |
? (window as { yatraAdmin?: { tripBase?: string } }).yatraAdmin |
| 53 |
: undefined; |
| 54 |
const s = fromSettings as Partial<YatraPermalinkBases> | null | undefined; |
| 55 |
return { |
| 56 |
trip_base: s?.trip_base ?? ya?.tripBase ?? "trip", |
| 57 |
destination_base: s?.destination_base ?? "destination", |
| 58 |
activity_base: s?.activity_base ?? "activity", |
| 59 |
trip_category_base: s?.trip_category_base ?? "trip-category", |
| 60 |
}; |
| 61 |
} |
| 62 |
|
| 63 |
/** Single trip plain: ?{tripBase}={slug} */ |
| 64 |
export function buildTripPlainUrl( |
| 65 |
baseSite: string, |
| 66 |
tripBase: string, |
| 67 |
slug: string, |
| 68 |
): string { |
| 69 |
const base = baseSite.replace(/\/$/, ""); |
| 70 |
const q = new URLSearchParams(); |
| 71 |
q.set(tripBase, slug); |
| 72 |
return `${base}/?${q.toString()}`; |
| 73 |
} |
| 74 |
|
| 75 |
/** Taxonomy single plain: ?{archiveBase}={slug} (same pattern as trip; mirrors PHP PlainPageMatcher). */ |
| 76 |
export function buildTaxonomyPlainUrl( |
| 77 |
baseSite: string, |
| 78 |
archiveBase: string, |
| 79 |
slug: string, |
| 80 |
): string { |
| 81 |
const base = baseSite.replace(/\/$/, ""); |
| 82 |
const key = (archiveBase || "").trim() || "destination"; |
| 83 |
const q = new URLSearchParams(); |
| 84 |
q.set(key, slug); |
| 85 |
return `${base}/?${q.toString()}`; |
| 86 |
} |
| 87 |
|
| 88 |
export type YatraSinglePublicUrls = { plainUrl: string; prettyUrl: string }; |
| 89 |
|
| 90 |
/** |
| 91 |
* Build both plain-query and path-style URLs for a single trip or taxonomy term. |
| 92 |
* Callers pick based on {@link isWordPressPlainPermalink} or REST `permalink`. |
| 93 |
*/ |
| 94 |
export function buildYatraSinglePublicUrls(params: { |
| 95 |
entity: YatraPublicEntity; |
| 96 |
slug: string; |
| 97 |
siteUrl?: string; |
| 98 |
bases?: Partial<YatraPermalinkBases> | null; |
| 99 |
}): YatraSinglePublicUrls { |
| 100 |
const baseSite = (params.siteUrl ?? getYatraSiteUrlFromWindow()).replace( |
| 101 |
/\/$/, |
| 102 |
"", |
| 103 |
); |
| 104 |
const bases = resolveYatraPermalinkBases(params.bases); |
| 105 |
const slug = (params.slug || "").trim(); |
| 106 |
|
| 107 |
switch (params.entity) { |
| 108 |
case "trip": |
| 109 |
return { |
| 110 |
plainUrl: buildTripPlainUrl(baseSite, bases.trip_base, slug), |
| 111 |
prettyUrl: `${baseSite}/${bases.trip_base}/${slug}`, |
| 112 |
}; |
| 113 |
case "destination": |
| 114 |
return { |
| 115 |
plainUrl: buildTaxonomyPlainUrl(baseSite, bases.destination_base, slug), |
| 116 |
prettyUrl: `${baseSite}/${bases.destination_base}/${slug}`, |
| 117 |
}; |
| 118 |
case "activity": |
| 119 |
return { |
| 120 |
plainUrl: buildTaxonomyPlainUrl(baseSite, bases.activity_base, slug), |
| 121 |
prettyUrl: `${baseSite}/${bases.activity_base}/${slug}`, |
| 122 |
}; |
| 123 |
case "category": |
| 124 |
return { |
| 125 |
plainUrl: buildTaxonomyPlainUrl( |
| 126 |
baseSite, |
| 127 |
bases.trip_category_base, |
| 128 |
slug, |
| 129 |
), |
| 130 |
prettyUrl: `${baseSite}/${bases.trip_category_base}/${slug}`, |
| 131 |
}; |
| 132 |
} |
| 133 |
} |
| 134 |
|
| 135 |
/** |
| 136 |
* Simple preview (no REST canonical): path-style when WP uses pretty permalinks, else plain query. |
| 137 |
*/ |
| 138 |
export function buildYatraSinglePreviewUrl(params: { |
| 139 |
entity: YatraPublicEntity; |
| 140 |
slug: string; |
| 141 |
siteUrl?: string; |
| 142 |
bases?: Partial<YatraPermalinkBases> | null; |
| 143 |
}): string { |
| 144 |
const { plainUrl, prettyUrl } = buildYatraSinglePublicUrls(params); |
| 145 |
return isWordPressPlainPermalink() ? plainUrl : prettyUrl; |
| 146 |
} |
| 147 |
|
| 148 |
/** |
| 149 |
* Archive / listing / booking hub URL (no item slug) — e.g. Settings → Permalink “View”. |
| 150 |
*/ |
| 151 |
export function buildYatraListingPublicUrl( |
| 152 |
baseSegment: string, |
| 153 |
siteUrl?: string, |
| 154 |
): string { |
| 155 |
const seg = (baseSegment || "trip").trim(); |
| 156 |
const raw = siteUrl !== undefined ? siteUrl : getYatraSiteUrlFromWindow(); |
| 157 |
const siteBase = raw.replace(/\/$/, ""); |
| 158 |
if (isWordPressPlainPermalink()) { |
| 159 |
if (!siteBase) { |
| 160 |
return `/?yatra_page=${encodeURIComponent(seg)}`; |
| 161 |
} |
| 162 |
return `${siteBase}/?yatra_page=${encodeURIComponent(seg)}`; |
| 163 |
} |
| 164 |
if (!siteBase) { |
| 165 |
return `/${seg}/`; |
| 166 |
} |
| 167 |
return `${siteBase}/${seg}/`; |
| 168 |
} |
| 169 |
|
| 170 |
/** |
| 171 |
* Customer account root for Settings → Customer “View Page”. |
| 172 |
* Matches {@see SettingsService::getAccountBase()} (last path segment) and the same plain/pretty rules as |
| 173 |
* {@see buildYatraListingPublicUrl}: `?yatra_page={base}` when WP permalinks are plain, `/{base}/` when pretty. |
| 174 |
*/ |
| 175 |
export function buildYatraAccountViewUrl( |
| 176 |
siteUrl: string, |
| 177 |
customerAccountPath: string, |
| 178 |
): string { |
| 179 |
const raw = (customerAccountPath || "").trim().replace(/^\/+/, ""); |
| 180 |
const parts = raw.split("/").filter((p) => p.length > 0); |
| 181 |
const segment = parts.length > 0 ? parts[parts.length - 1] : "my-account"; |
| 182 |
const slug = (segment || "my-account").trim(); |
| 183 |
return buildYatraListingPublicUrl(slug, siteUrl || undefined); |
| 184 |
} |
| 185 |
|