Skip to content

Improve identity driver class resolution logic#110

Open
TDannhauer wants to merge 2 commits into
FRAMEWORK_6_0from
fix/identity_driver_class_resolution
Open

Improve identity driver class resolution logic#110
TDannhauer wants to merge 2 commits into
FRAMEWORK_6_0from
fix/identity_driver_class_resolution

Conversation

@TDannhauer
Copy link
Copy Markdown
Contributor

Summary

Fix application-specific identity driver resolution in Horde_Core_Factory_Identity so drivers whose class names use an uppercase application prefix (notably IMP) are found reliably, including when the identity class has not yet been autoloaded.

Problem

When code requests an application identity via Horde_Core_Factory_Identity::create(null, $driver), the factory builds the class name as:

Horde_String::ucfirst($driver) . '_Prefs_Identity';

For the imp driver this yields Imp_Prefs_Identity, while the actual class defined in IMP is IMP_Prefs_Identity.

That mismatch surfaces as:

Cannot create IMP_Identity
  Root cause: imp identity driver does not exist.

When it shows up

The failure is easiest to reproduce on a "cold" request where IMP_Prefs_Identity has not been loaded yet:

  • Navigating to another app (e.g. Ingo) in smart mobile / responsive view while IMP code still needs IMP_Identity
  • Cross-app calls (registry, topbar, hooks) that touch IMP before IMP's autoload path has registered
  • Any path that calls IMP_Factory_IdentityHorde_Core_Factory_Identity::create(null, 'imp') without a prior full IMP page load

Once IMP_Prefs_Identity is loaded, PHP's case-insensitive class aliases can mask the bug, which makes it intermittent and environment-dependent.

Root cause

Driver Old resolved class Actual class
imp Imp_Prefs_Identity IMP_Prefs_Identity

class_exists('Imp_Prefs_Identity') returns false until the real class file is loaded. Composer's classmap indexes IMP_Prefs_Identity, not Imp_Prefs_Identity, so autoload does not help for the wrong name.

Solution

Extend the default branch of create() to:

  1. Try multiple class name conventionsucfirst($driver) and strtoupper($driver) before failing.
  2. Explicitly load the identity driver file — if no class is found, require_once {fileroot}/lib/Prefs/Identity.php from the registry and re-check both candidates with class_exists(..., false).

This keeps existing behaviour for normal apps (kronolithKronolith_Prefs_Identity) and fixes acronym-style apps (impIMP_Prefs_Identity) without hard-coding IMP.

Changes

File: lib/Horde/Core/Factory/Identity.php

Before (default branch):

$class = Horde_String::ucfirst($driver) . '_Prefs_Identity';
if (!class_exists($class)) {
    throw new Horde_Exception($driver . ' identity driver does not exist.');
}

After (default branch):

  • Resolve class via candidate list: {Ucfirst}_Prefs_Identity, {UPPER}_Prefs_Identity
  • Fallback: load {registry fileroot}/lib/Prefs/Identity.php if present
  • Only then throw "{driver} identity driver does not exist."

The special-case handling for driver === 'horde' (Bug #9936 / Horde_Prefs_HordeIdentity) is unchanged.

Test plan

  • Horde_Core_Factory_Identity::create(null, 'imp') returns IMP_Prefs_Identity on a fresh request (no prior IMP bootstrap).
  • $injector->getInstance('IMP_Identity') succeeds when IMP factories are bound.
  • Existing drivers still work: create(null, 'kronolith'), create() (default Horde_Core_Prefs_Identity), create(null, 'horde').
  • Invalid driver still throws: create(null, 'nonexistent_app').
  • Manual: open Ingo from smart mobile / responsive view while logged in; no IMP_Identity / "identity driver does not exist" errors in Horde log.

Suggested unit test (optional)

// After require bootstrap with registry + injector
$identity = $injector->getInstance('Horde_Core_Factory_Identity')->create(null, 'imp');
$this->assertInstanceOf('IMP_Prefs_Identity', $identity);

Backward compatibility

  • No API changes to Horde_Core_Factory_Identity::create().
  • No config changes required.
  • Apps with conventional {Ucfirst}_Prefs_Identity naming are unaffected.
  • Only apps using an all-caps prefix (currently IMP) gain correct resolution.

Related

  • Consumer: IMP_Factory_Identity in horde/imp calls create(null, 'imp').
  • Similar pattern may apply to other acronym app IDs if added in the future; this fix generalises via strtoupper($driver).

Enhance identity driver class loading by checking multiple class names and requiring a file if necessary.
@TDannhauer TDannhauer requested a review from ralflang May 19, 2026 22:13
This test suite verifies the functionality of the Horde_Core_Factory_Identity class, ensuring correct resolution of identity drivers and handling of various scenarios, including driver creation and error throwing for unknown drivers.
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