Skip to content

Deprecation helper#19

Draft
amulet1 wants to merge 2 commits intohorde:FRAMEWORK_6_0from
horde6:deprecation_helper
Draft

Deprecation helper#19
amulet1 wants to merge 2 commits intohorde:FRAMEWORK_6_0from
horde6:deprecation_helper

Conversation

@amulet1
Copy link
Copy Markdown
Contributor

@amulet1 amulet1 commented Mar 16, 2026

1. Add DeprecationHelper utility class

  • Emit deprecation notices pointing to the actual call site in user code
  • Transparent redirection of deprecated classes to their replacements via class_alias()
  • Resolve call site by walking the backtrace past autoloader frames

The helper can be used to redirect to another class by replacing the old class file with these 2 lines:

<?php
Horde\Util\DeprecationHelper::redirectClass('Horde_Array', 'Horde\Util\ArrayUtils');

Of course it would be nicer to have a single root helper class, so we could do this:

DeprecationHelper::redirectClass('OldClass', 'NewClass');

or

DeprecationHelper::redirectClass('OldClass', NewClass::class);

In addition to the actual redirecton it also calls trigger_error (or, optionally, error_log) to output deprecation notice with exact location of the deprecated code. It relies on autoloader to load old class, so only the first occurrence gets reported (overhead is small).

The debug mode output example in case of trigger_error:
[horde] PHP ERROR: The Horde_Array class is deprecated. Switch to Horde\Util\ArrayUtils (.../vendor/horde/util/lib/Horde/Variables.php:364)

And in case of error_log (if 3rd parameter is false):
DEPRECATED: The Horde_Array class is deprecated. Switch to Horde\\Util\\ArrayUtils (.../vendor/horde/util/lib/Horde/Variables.php:364)

TODO: It might be a good idea to adjust Horde's error handler to suppress backtrace output for E_USER_DEPRECATED case (the helper already reports exact location).

2. Deprecate Horde_Array class (redirect to PSR-4 implementation)

This provides a working example, but many other classes could be redirected the same way, provided their methods/parameters are 100% compatible.

TODO: Add more helper methods for other scenarios (e.g. emit custom message and pinpoint location of the caller) for deprecated method or method parameters.

amulet1 added 2 commits March 16, 2026 13:44
- Emit deprecation notices pointing to the actual call site in user code
- Allow to redirect deprecated class names to their replacements via class_alias()
- Resolve call site by walking the backtrace past autoloader frames

To be expanded.
@amulet1 amulet1 requested review from TDannhauer and ralflang March 16, 2026 18:11
@ralflang
Copy link
Copy Markdown
Member

At least horde/util has no hard dependencies on anything notable. I will check details later.

Copy link
Copy Markdown
Member

@ralflang ralflang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with putting the helper here if you don't want a dedicated component for it.
I don't agree with log spamming library users for using a migration path we actively offer and still use in 25+ places though.

Do not use this on Horde_Array right now.

@amulet1
Copy link
Copy Markdown
Contributor Author

amulet1 commented Mar 17, 2026

It feels like a way to for many cases where we have unused cone in src/ (such as Horde\Util\ArrayUtils and many others). If we do not do it for Horde_Array (why?), then what is the criteria?

Let's deprecate redundant code in lib/ where the equivalent code already exist in src/ or else remove code in 'src/' if we are not migrating to it. Anything else (e.g. partial migrations!) would cause future issues.

Let's agree to never change existing methods except for one of these specific cases:

  • method is clearly for internal use only
  • we still fully support existing functionality and parameters (e.g. we are adding new optional parameters).

If anything needs to be changed in incompatible way (even if just method signature), let's do this:

  • implement it as new method (i.e. method with a new name!)
  • announce deprecation of the old method (e.g. in the changelog/docs/mailing lists), mark is deprecated
  • possibly adjust old method to rely on the new method
  • migrate to the new method in all Horde packages
  • (eventually) eliminate old method (assuming 3rd parties, if any, migrated as well)

If we do not do it this way, we will create issues. Note, this obviously does not apply to new classes.

Once again, my main concern is existing duplicated and unused code (such as Horde\Util\ArrayUtils vs Horde_Array). Either we migrate to it or else drop it. Changing the duplicate to deviate from the original code and then trying to migrate to it is bad idea for many reasons mentioned before. The path should be "migrate->change" or "change->migrate", not "break and migrate".

@ralflang
Copy link
Copy Markdown
Member

ArrayUtils isn't unused though.

@amulet1
Copy link
Copy Markdown
Contributor Author

amulet1 commented Mar 20, 2026

With classmap in composer.json the Deprecationhelper is useless, anyway.

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.

2 participants