From 989dbf9da8b282013a54147545027cb145640093 Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Tue, 26 May 2026 14:22:25 +0300 Subject: [PATCH] Name the preload-required predicate Compress the "do we need to load WP records?" condition into `preload_required?(context)` so the call site reads as intent rather than a tangle of two unrelated signals. The reasoning (semantic mode needs row lookup; static-HTML output needs type/subject for the anchor) moves to a comment on the predicate, where it belongs. --- .../matchers/resource_links_matcher.rb | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/open_project/text_formatting/matchers/resource_links_matcher.rb b/lib/open_project/text_formatting/matchers/resource_links_matcher.rb index f2bd67083d8..772b98a4333 100644 --- a/lib/open_project/text_formatting/matchers/resource_links_matcher.rb +++ b/lib/open_project/text_formatting/matchers/resource_links_matcher.rb @@ -166,14 +166,9 @@ module OpenProject::TextFormatting # Doc-level preload called by `PatternMatcherFilter`. Save/restores # the cache so a nested `format_text` (e.g. custom-field formatter # re-entering the pipeline) doesn't clobber the outer render. - # Fires when semantic identifiers need resolving or when a - # static-HTML channel needs the WP record to compose the - # type/subject/status anchor; other channels render `#N` from the - # matched id alone and the as-text path short-circuits on - # `text_only?` before consulting the cache. def self.with_preloaded_resources(doc, context) previous = RequestStore.store[CACHE_KEY] - return yield unless Setting::WorkPackageIdentifier.semantic? || context[:as_static_html] + return yield unless preload_required?(context) identifiers = collect_work_package_identifiers(doc) return yield if identifiers.empty? @@ -184,6 +179,17 @@ module OpenProject::TextFormatting RequestStore.store[CACHE_KEY] = previous end + # Two channels need the WP record at render time: semantic mode (to + # resolve `PROJ-7` to a row) and static-HTML output (to compose the + # type/subject anchor of a quickinfo macro). Classic-mode rich HTML + # and the as-text channel both render from the matched id alone — + # the latter short-circuits on `text_only?` before consulting the + # cache. + def self.preload_required?(context) + Setting::WorkPackageIdentifier.semantic? || context[:as_static_html] + end + private_class_method :preload_required? + def self.collect_work_package_identifiers(doc) identifiers = Set.new doc.search(".//text()").each do |node|