Issue #3615029: Extract image, menu and page URL services from MyrestHelper

MyrestHelper was a 6604-line god object: 139 methods and 16 injected dependencies covering image handling, paragraphs, menus, facets, reviews and prices. Nothing could be unit tested in isolation and every consumer pulled in the whole dependency graph.

First extraction pass, chosen by measuring how many calls each group of methods makes back into the rest of the class:

  • MyrestImageBuilder, 12 methods. Image, media, video, SVG and base64 handling. It made no calls into the rest of the helper at all, so it came out with no coupling to unpick. Needs 4 of the 16 constructor arguments.
  • MyrestMenuBuilder, 3 methods. Menu tree building. Takes MyrestImageBuilderInterface for the menu item images it needs.
  • MyrestPageUrlResolver, 10 methods. Aliases of the listing pages, plus aliasAddLanguagePrefix(), which the normalizer calls through the facade. Needs 2 arguments.

Each service has an interface, so consumers type-hint the contract rather than the implementation.

MyrestHelper keeps all 24 public methods, now delegating, so no caller changes. They are annotated @deprecated in myrest:1.1.0 and removed from myrest:2.0.0 to point at the new services.

Testing: MyrestHelperTest updated for the new constructor. The base64 and SVG cases moved to a new MyrestImageBuilderTest, where they exercise the real implementation instead of going through the facade.

The remaining groups are recorded in the issue. The paragraph builder is the largest at roughly 1450 lines but is entangled with images, articles, discounts and prices, so it needs its own issue rather than being forced into this one.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

Closes #3615029

Merge request reports

Loading