diff --git a/src/Glpi/Application/View/Extension/FrontEndAssetsExtension.php b/src/Glpi/Application/View/Extension/FrontEndAssetsExtension.php index 1d75f696f9b..f2f0727c8be 100644 --- a/src/Glpi/Application/View/Extension/FrontEndAssetsExtension.php +++ b/src/Glpi/Application/View/Extension/FrontEndAssetsExtension.php @@ -293,14 +293,53 @@ public function configJs(): string $cfg_glpi += Config::getSafeConfig(true); } + // Common config keys used by front-end code. + // These will be immediately available while others will be lazy-loaded via a proxy handler. + $common_configs = [ + 'root_doc', 'url_base', 'planning_begin', 'planning_end', 'planning_work_days', 'toast_location', + 'is_demo_dashboards', 'priority_1', 'priority_2', 'priority_3', 'priority_4', 'priority_5', 'priority_6', + 'date_format', 'refresh_views', + ]; + $common_config = array_filter( + $cfg_glpi, + static fn($key) => in_array($key, $common_configs, true), + ARRAY_FILTER_USE_KEY + ); + $common_config = json_encode($common_config); + $plugins_path = \array_combine( Plugin::getPlugins(), - \array_map(fn(string $plugin_key) => "/plugins/{$plugin_key}", Plugin::getPlugins()) + \array_map(static fn(string $plugin_key) => "/plugins/{$plugin_key}", Plugin::getPlugins()) ); - - $script = sprintf('window.CFG_GLPI = %s;', json_encode($cfg_glpi, JSON_PRETTY_PRINT)) - . "\n" - . sprintf('window.GLPI_PLUGINS_PATH = %s;', json_encode($plugins_path, JSON_PRETTY_PRINT)); + $plugins_path = json_encode($plugins_path); + + $script = << { + if (prop in target) { + return Reflect.get(target, prop, receiver); + } + // Note there was a request for a config not in the common set to indicate a potential optimization + console.debug("Lazy loading a CFG_GLPI property that was not available by default: " + prop + '. This may be an optimization opportunity.'); + // Hydrate the missing config via a synchronous AJAX call + $.ajax({ + type: 'GET', + url: CFG_GLPI.root_doc + '/Session/Config/' + prop, + async: false, + dataType: 'json', + success: (value) => { + target[prop] = value; + }, + error: () => { + console.warn('Failed to load config property ' + prop); + target[prop] = undefined; + } + }); + return Reflect.get(target, prop, receiver); + } + }); + window.GLPI_PLUGINS_PATH = $plugins_path; +JS; return Html::scriptBlock($script); } diff --git a/src/Glpi/Controller/Session/ConfigController.php b/src/Glpi/Controller/Session/ConfigController.php new file mode 100644 index 00000000000..d3e1ddd01f2 --- /dev/null +++ b/src/Glpi/Controller/Session/ConfigController.php @@ -0,0 +1,60 @@ +. + * + * --------------------------------------------------------------------- + */ + +namespace Glpi\Controller\Session; + +use Config; +use Glpi\Controller\AbstractController; +use Glpi\Exception\Http\NotFoundHttpException; +use Glpi\Http\Firewall; +use Glpi\Security\Attribute\SecurityStrategy; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Attribute\Route; + +final class ConfigController extends AbstractController +{ + #[Route("/Session/Config/{key}", name: "get_config_value")] + #[SecurityStrategy(Firewall::STRATEGY_AUTHENTICATED)] + public function content(Request $request): Response + { + $safe_config = Config::getSafeConfig(true); + $key = $request->get('key'); + if (!array_key_exists($key, $safe_config)) { + throw new NotFoundHttpException(); + } + return new JsonResponse($safe_config[$key]); + } +}