Skip to content

fix: define ILIAS_HTTP_PATH for cron-triggered assignments#5

Open
thomas-neumann-axtesys wants to merge 1 commit into
ingoj:release_9_testing_improvements_2from
axtesys:fix/ilias-http-path
Open

fix: define ILIAS_HTTP_PATH for cron-triggered assignments#5
thomas-neumann-axtesys wants to merge 1 commit into
ingoj:release_9_testing_improvements_2from
axtesys:fix/ilias-http-path

Conversation

@thomas-neumann-axtesys
Copy link
Copy Markdown

Fix: Fatal Undefined constant ILIAS_HTTP_PATH when plugin is triggered from cron

Summary

UserSetting::doAssignements() fatals with
Error: Undefined constant "ILIAS\Repository\Form\ILIAS_HTTP_PATH"
when the plugin is reached via cron authentication. The portfolio-related
side effects (and other GUI-coupled service constructions) transitively
require ILIAS_HTTP_PATH, but ILIAS does not define that constant in CLI
context until ilCronManagerImpl::run() — which happens after
ilCronStartUp::authenticate(), where the event chain that lands in this
plugin originates.

This PR defines ILIAS_HTTP_PATH from ilias.ini.php ([server] http_path)
at the top of doAssignements() when it is not already defined, using the
same helper ILIAS itself uses in ilCronManagerImpl::run(). The guard is a
no-op in HTTP context.

Reproduction

  1. An active UserDefault rule with on_update = true and a portfolio_name
    set.
  2. The cron user's account has profile_incomplete = 1 (a required core
    field or UDF is empty), or login_attempts > 0 on ILIAS ≥ 9.2 — both
    conditions cause ilAuthFrontend::handleAuthenticationSuccess to call
    $user->update() and fire the Services/Object update event.
  3. Run cron: php cli/cron.php run-jobs <cron_user> <client_id>.

Result on ILIAS ≥ 9.0: fatal before any cron job runs.

Stack trace (abridged)

#21 Error in .../Services/Repository/Service/Form/class.FormAdapterGUI.php:96
#20 FormAdapterGUI::getOnLoadCode  ← references ILIAS_HTTP_PATH
#19 FormAdapterGUI::initJavascript
#18 Portfolio\InternalGUIService::initGUIServices
#17 Portfolio\InternalGUIService::__construct
#16 Portfolio\InternalService::__construct   ← eagerly builds GUI service
#15 Portfolio\Service::internal
#14 ilPortfolioAccessHandler::__construct    ← pulled in by removePortfolio()
#13 UserDefaults\UserSetting::removePortfolio
#12 UserDefaults\UserSetting::doAssignements    ← guard added here
#11 ilUserDefaultsPlugin::handleEvent
#10 ilAppEventHandler::raise
#9  ilObject::update (fires Services/Object 'update')
#8  ilObjUser::update
#7  ilAuthFrontend::handleAuthenticationSuccess  ← $user->update() at line 302 (profile incomplete) or 327 (login attempts reset)
#6  ilAuthFrontend::authenticate
#5  ilCronStartUp::authenticate
#4  RunActiveJobsCommand::execute

Root cause

ILIAS_HTTP_PATH is normally defined by:

  • HTTP requests: ilInitialisation::buildHTTPPath().
  • CLI cron: ilCronManagerImpl::run():
    if (!defined('ILIAS_HTTP_PATH')) {
        define('ILIAS_HTTP_PATH', ilUtil::_getHttpPath());
    }
    which reads [server] http_path from ilias.ini.php.

RunActiveJobsCommand calls $cron->authenticate() before the manager
loop, so the constant is still undefined when the auth-success event fires
and lands in this plugin. From doAssignements(), any branch that ends up
constructing portfolio access / GUI services (most directly removePortfolio()
via ilPortfolioAccessHandler, but the same root cause applies to other
branches that touch GUI-coupled services) hits
FormAdapterGUI::getOnLoadCode() and dereferences the missing constant.

The chain has been reachable since ILIAS 9.0 (when
FormAdapterGUI::getOnLoadCode() started referencing ILIAS_HTTP_PATH), but
typically only becomes fatal in cron once the cron user falls into one of
the $user->update() branches in ilAuthFrontend::handleAuthenticationSuccess
— most commonly because the cron user has profile_incomplete = 1.

Fix

src/UserSetting/UserSetting.php

Add use ilUtil; and guard the entry to doAssignements():

 use ilPortfolioTemplatePage;
 use ilUserDefaultsPlugin;
+use ilUtil;
 ...
 public function doAssignements(ilObjUser $user): void
 {
+    // ILIAS_HTTP_PATH is normally set by the HTTP bootstrap, and in CLI cron by
+    // ilCronManagerImpl::run(). The plugin can however be reached earlier in the
+    // cron flow (via ilCronStartUp::authenticate() -> $user->update()), before
+    // that define has happened, while still pulling in GUI services that require
+    // it. Mirror the core fallback here so any branch of doAssignements is safe.
+    if (!defined('ILIAS_HTTP_PATH')) {
+        define('ILIAS_HTTP_PATH', ilUtil::_getHttpPath());
+    }
+
     $this->setUsrObject($user);
     if ($this->isValid()) {
         $this->generatePortfolio();
         ...

ilUtil::_getHttpPath() returns the value of [server] http_path from
ilias.ini.php in CLI context — the same source ILIAS uses in
ilCronManagerImpl::run(). No new configuration is required beyond what cron
already needs.

Prerequisite

[server] http_path must be set in the global ilias.ini.php. This is
already an ILIAS requirement for cron in general — ilCronManagerImpl::run()
relies on the same value.

Mirror ilCronManagerImpl::run()'s defined()/define() fallback at the top
of doAssignements(). The plugin is reached during cron auth, before the
core fallback runs, while still pulling in GUI services that require the
constant.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant