* 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');
*
* - '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`.
if ($logicalUri[0] === '/') {
$logicalUri = 'current:' . $logicalUri;
}
+ elseif ($logicalUri[0] === '[') {
+ $logicalUri = 'asset://' . $logicalUri;
+ }
$parsed = parse_url($logicalUri);
$this->scheme = $parsed['scheme'] ?? NULL;
$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()}");
}
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'