Skip to content
175 changes: 122 additions & 53 deletions components/ILIAS/UICore/classes/class.ilTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -333,80 +333,149 @@ protected function fileExistsInSkin(string $path): bool
}

/**
* Resolves the full filesystem path to a template while taking into account
* UI framework structure, component hierarchy, and custom skin/style overrides.
*
* The method supports three template types:
* - Basic templates (default templates without UI or component context)
* <ilias-root>/templates/default/
* - Component templates (templates inside ILIAS components)
* <ilias-root>/components/ILIAS/<component>/templates/default/
* - UI framework templates (templates from the ILIAS UI framework)
* <ilias-root>/components/ILIAS/UI/src/templates/default/<ui-component>/
*
* Additionally, it checks whether a custom skin is active. If so, the method
* first looks for an overridden version of the template in the skin or style
* directories. If no matching override is found, it falls back to the default
* template.
*
* Search order when a custom skin is active:
* 1. Style/SubStyle-specific paths (UI and component)
* 2. Skin-specific paths (UI and component)
* 3. Default template (fallback)
*
* Special notes:
* - UI framework templates are automatically detected via the "/UI/" path segment
* - Component templates are determined via the `$a_in_module` parameter
* - UI components can be resolved in a more granular way
* - fileexistsinskin() is used to check for skin overrides
*
* @param string $a_tplname
* Relative path to the template (e.g. "tpl.std.html" or full UI path)
*
* @param string $a_in_module
* Optional module path of the component (e.g. "components/ILIAS/XYZ")
*
* @return string
* Fully resolved filesystem path to the template (skin, style, or default)
*
* @throws ilSystemStyleException
*/
protected function getTemplatePath(string $a_tplname, string $a_in_module = ''): string
{
$ilias_root = realpath(__DIR__ . '/../../../../') . '/';
$ilias_root = realpath(__DIR__ . '/../../../../');
$ui_component_base_path = 'components/ILIAS/UI/src';

if (str_starts_with($a_in_module, $ilias_root)) {
$a_in_module = str_replace($ilias_root, '', $a_in_module);
}
$skin = $this->getCurrentSkin();
$style = $this->getCurrentStyle();

if (str_ends_with($a_in_module, '/')) {
$a_in_module = rtrim($a_in_module, '/');
}
$default_path = $ilias_root;
$skin_base_path = $ilias_root . '/public/Customizing/skin';
$skin_path = $skin_base_path . '/' . $skin;
$style_path = $skin_base_path . '/' . $skin . '/' . $style;

$tpl_sub_path = '/templates/default/';
if (str_starts_with($a_tplname, 'components/ILIAS/UI/')) {
$a_in_module = 'components/ILIAS/UI/src';
$a_tplname = str_replace('components/ILIAS/UI/src/templates/default/', '', $a_tplname);
}
$is_custom_skin = !($skin === 'default' && $style === 'delos');

if (str_starts_with($a_tplname, $ilias_root)) {
$a_tplname = str_replace($ilias_root, '', $a_tplname);
}
$a_in_module = trim($a_in_module, '/');
$a_tplname = trim($a_tplname, '/');

// Special Cases for plugins
if (str_starts_with($a_tplname, 'Customizing/global/plugins/')) {
$a_tplname = "public/$a_tplname";
}
$template_type = 0;
$template_name = $a_tplname;
$component = $a_in_module;
$ui_component = null;

if (str_contains($a_tplname, 'public/Customizing/global/plugins')) {
$tpl_sub_path = '';
}

// Proceed with skin lookup
$base_path = $ilias_root;
$default = $base_path . $a_in_module . $tpl_sub_path . $a_tplname;
/////////////////////////////////////////////////
/// Split & sort everything
///
if(str_contains($component, 'public/Customizing/global/plugins') || str_contains($template_name, 'public/Customizing/global/plugins')) {
$template_type = 3;
} elseif(str_starts_with($component, 'components/')) {
$template_type = 1;
} elseif($component === '' && str_contains($template_name, '/UI/')) {
$template_type = 2;

$skin = $this->getCurrentSkin();
if ($skin === 'default') {
return $default;
}
$template_name = substr($a_tplname, strrpos($a_tplname, '/') + 1);
$ui_path = str_replace('/' . $template_name, '', $a_tplname);
$ui_path = str_replace($ui_component_base_path . '/templates/default/', '', $ui_path);
$ui_component = trim($ui_path, '/');

$style = $this->getCurrentStyle();
$base_skin_path = $ilias_root . 'public/Customizing/skin/' . $skin;

$paths = [
"$base_skin_path/$style/components/ILIAS/UI/src",
"$base_skin_path/$style/components/ILIAS/UI",
"$base_skin_path/$style/UI/src",
"$base_skin_path/$style/UI",
"$base_skin_path/components/ILIAS/UI/src",
"$base_skin_path/components/ILIAS/UI",
"$base_skin_path/UI/src",
"$base_skin_path/UI",
];
$component = $ui_component_base_path;
}

foreach ($paths as $path) {
if (is_dir($path)) {
$a_in_module = str_replace($base_skin_path . '/', '', $path);
/////////////////////////////////////////////////
/// Build paths
///
switch($template_type) {
case 1: // Component Template
$default_path .= '/' . $component . '/templates/default/';
$skin_path .= '/' . $component . '/';
$style_path .= '/' . $component . '/';
break;
case 2: // UI-Framework Template
$default_path .= '/' . $component . '/templates/default/';
if($ui_component !== null) {
$default_path .= $ui_component . '/';
}
break;
case 3: // Plugin Templates
if($component === '') {
return '/' . $a_tplname;
} else {
return '/' . $component . '/templates/default/' . $template_name;
}
default: // Basic Template
$default_path .= '/templates/default/';
break;
}
}

$from_style = $base_skin_path . '/' . $style . '/' . $a_in_module . '/' . $a_tplname;
if ($this->fileexistsinskin($from_style)) {
return $from_style;
/////////////////////////////////////////////////
/// Return default template
///
if (!$is_custom_skin) {
return $default_path . $template_name;
}

$from_skin = $base_skin_path . '/' . $a_in_module . '/' . $a_tplname;
if ($this->fileexistsinskin($from_skin)) {
return $from_skin;
/////////////////////////////////////////////////
/// Return custom skins template or fallback
///
$custom_skin_UI_paths = [
"$style_path/components/ILIAS/UI/src",
"$style_path/components/ILIAS/UI",
"$style_path/UI/src",
"$style_path/UI",
"$skin_path/components/ILIAS/UI/src",
"$skin_path/components/ILIAS/UI",
"$skin_path/UI/src",
"$skin_path/UI",
];

if($template_type === 2) {
foreach ($custom_skin_UI_paths as $custom_skin_UI_path) {
if ($this->fileexistsinskin($custom_skin_UI_path . '/' . $ui_component . '/' . $template_name)) {
return $custom_skin_UI_path . '/' . $ui_component . '/' . $template_name;
}
}
} else {
if ($this->fileexistsinskin($style_path . $template_name)) {
return $style_path . $template_name;
}
if ($this->fileexistsinskin($skin_path . $template_name)) {
return $skin_path . $template_name;
}
}

return $default;
return $default_path .$template_name;
}

/**
Expand Down
Loading