From a6c51f6e75d0b040fa833b108921c10da8221961 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Fri, 21 Jul 2023 16:29:19 -0700 Subject: [PATCH] Civi::url() - Add support for path-variables --- Civi.php | 4 ++++ Civi/Core/Url.php | 36 +++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/Civi.php b/Civi.php index e9d0dcab55..c7c48001d9 100644 --- a/Civi.php +++ b/Civi.php @@ -244,6 +244,9 @@ class Civi { * Ex: Link to a dynamically generated asset-file. * $url = Civi::url('assetBuilder://crm-l10n.js?locale=en_US'); * + * Ex: Link to a static asset (resource-file) in one of core's configurable paths. + * $url = Civi::url('[civicrm.root]/js/Common.js'); + * * Ex: Link to a static asset (resource-file) in an extension. * $url = Civi::url('ext://org.civicrm.search_kit/css/crmSearchTasks.css'); * @@ -257,6 +260,7 @@ class Civi { * - 'backend://' (Back-end page-route for staff) * - 'service://` (Web-service page-route for automated integrations; aka webhooks and IPNs) * - 'current://' (Whichever UI is currently active) + * - 'asset://' (Static asset-file; see \Civi::paths()) * - 'assetBuilder://' (Dynamically-generated asset-file; see \Civi\Core\AssetBuilder) * - 'ext://' (Static asset-file provided by an extension) * An empty scheme (`//hello.txt`) is equivalent to `current://hello.txt`. diff --git a/Civi/Core/Url.php b/Civi/Core/Url.php index bedea2aaa2..91b20d81ce 100644 --- a/Civi/Core/Url.php +++ b/Civi/Core/Url.php @@ -93,6 +93,9 @@ final class Url { if ($logicalUri[0] === '/') { $logicalUri = 'current:' . $logicalUri; } + elseif ($logicalUri[0] === '[') { + $logicalUri = 'asset://' . $logicalUri; + } $parsed = parse_url($logicalUri); $this->scheme = $parsed['scheme'] ?? NULL; @@ -413,17 +416,25 @@ final class Url { $result = \Civi::service('asset_builder')->getUrl($assetName, $assetParams); break; - case 'ext': - $parts = explode('/', $this->getPath(), 2); - $result = \Civi::resources()->getUrl($parts[0], $parts[1] ?? NULL, FALSE); - if ($this->query) { - $result .= '?' . $this->query; + case 'asset': + if (preg_match(';^\[([\w\.]+)\](.*)$;', $this->getPath(), $m)) { + [, $var, $rest] = $m; + $result = rtrim(\Civi::paths()->getVariable($var, 'url'), '/'); + if ($preferFormat === 'relative') { + $result = \CRM_Utils_Url::toRelative($result); + } + $result .= $rest . $this->composeSuffix(); } - if ($this->fragment) { - $result .= '#' . $this->fragment; + else { + throw new \RuntimeException("Malformed asset path: {$this->getPath()}"); } break; + case 'ext': + $parts = explode('/', $this->getPath(), 2); + $result = \Civi::resources()->getUrl($parts[0], $parts[1] ?? NULL, FALSE) . $this->composeSuffix(); + break; + default: throw new \RuntimeException("Unknown URL scheme: {$this->getScheme()}"); } @@ -452,6 +463,17 @@ final class Url { return $this->htmlEscape ? htmlentities($result) : $result; } + private function composeSuffix(): string { + $result = ''; + if ($this->query) { + $result .= '?' . $this->query; + } + if ($this->fragment) { + $result .= '#' . $this->fragment; + } + return $result; + } + private static function detectFormat(): string { // Some environments may override default - e.g. cv-cli prefers absolute URLs // WISHLIST: If handling `Job.*`, then 'absolute' -- 2.25.1