Benutzerdefinierte Themenfilter: URL-Parameter erreichen `TopicQuery.options` nicht

Während beim Erstellen eines Plugins mit benutzerdefinierten Themenlistenfiltern (z.B. nach Preis, Standort) unter Verwendung von URL-Abfrageparametern die URL korrekt aktualisiert wird (z.B. ...?market_item_statuses=Available), erscheinen die Parameter nicht in topic_query.options auf dem Server.

Einrichtung:

  1. Client-seitige Param-Registrierung (tecenc-discovery-params.js):

    // tecenc-discovery-params.js
    import { apiInitializer } from "discourse/lib/api";
    
    export default apiInitializer("1.37.3", (api) => {
      const MARKET_PARAMS_KEYS = [
        "market_price_min", "market_price_max", "market_location",
        "market_conditions", "market_warranty", "market_item_statuses"
      ];
      MARKET_PARAMS_KEYS.forEach(paramKey => {
        api.addDiscoveryQueryParam(paramKey, { replace: true, refreshModel: true });
      });
    });
    
  2. Serverseitiges Whitelisting, Versuch (plugin.rb):

    # plugin.rb
    module ::Tecenc
      MARKET_PARAMS_KEYS = [
        :market_price_min, :market_price_max, :market_location,
        :market_conditions, :market_warranty, :market_item_statuses
      ].freeze
    end
    
    # nach_initialisierung
    if SiteSetting.tecenc_enabled?
      if defined?(::TopicQuery.add_custom_param_handler)
        ::Tecenc::MARKET_PARAMS_KEYS.each do |param_key|
          ::TopicQuery.add_custom_param_handler(param_key) { |value| value } # Vereinfachung für die Kürze
        end
        Rails.logger.info "[Tecenc] Registriert mit add_custom_param_handler."
      elsif defined?(::TopicQuery) && ::TopicQuery.methods.include?(:extra_options_whitelist)
        current_whitelist = ::TopicQuery.extra_options_whitelist || []
        new_whitelist = (current_whitelist + ::Tecenc::MARKET_PARAMS_KEYS).uniq
        ::TopicQuery.extra_options_whitelist(*new_whitelist)
        Rails.logger.info "[Tecenc] Erweiterung der extra_options_whitelist."
      else
        Rails.logger.warn "[Tecenc] PLUGIN_WARN: Konnte keine Methode finden, um Parameter für TopicQuery zu whitelisten."
      end
    
  3. Serverseitige Filter-Logik (plugin.rb):

    # plugin.rb (innerhalb von nach_initialisierung / wenn aktiviert)
    ::TopicQuery.add_custom_filter(:"tecenc_filters") do |topics, topic_query|
      opts = topic_query.options
      Rails.logger.info "[Tecenc_TopicQuery] Opts: #{opts.inspect}" # Kritischer Log
    
      # market_params_present = ::Tecenc::MARKET_PARAMS_KEYS.any? { |p| opts[p].present? }
      # if market_params_present
      #   # ... Filter-Logik unter Verwendung von opts[key] ...
      # end
      topics # oder modifizierte_themen
    end
    

Das Problem (Logs):

  1. Parameter-Whitelist ist fehlgeschlagen:

    [Tecenc] PLUGIN_WARN: Konnte keine passende Methode (add_custom_param_handler oder extra_options_whitelist) finden, um benutzerdefinierte Parameter für TopicQuery zu whitelisten.
    
  2. opts in TopicQuery.add_custom_filter enthält unsere benutzerdefinierten Parameter nicht:
    Wenn URL ...?market_item_statuses=Available ist, zeigt das Log:

    [Tecenc_TopicQuery] Opts: {:category=>5, :filter=>"default", :topic_ids=>nil, :category_id=>5}
    

Unsere market_item_statuses (und andere benutzerdefinierte Parameter) sind nicht vorhanden.

Unsere Umgebung:

Fragen:

  1. Was ist die aktuelle Best Practice, um sicherzustellen, dass benutzerdefinierte URL-Query-Parameter in den aktuellen Discourse-Versionen bei topic_query.options ankommen?
  2. Warum könnten unsere Versuche, add_custom_param_handler oder extra_options_whitelist zu verwenden, mit der Warnung “Could not find a suitable method” fehlschlagen?
  3. Gibt es eine alternative Herangehensweise an die Parameterregistrierung mit TopicQuery, die wir verwenden sollten?

Jede Hilfe wäre sehr willkommen!

Gerade bemerkt, dass add_custom_param_handler überhaupt nicht als Methode bei TopicQuery verfügbar ist. Gibt es eine andere Möglichkeit, benutzerdefinierte Filter für Themen in neueren Discourse-Versionen zu erstellen?

TopicQuery singleton_methods: [:add_custom_filter, :apply_custom_filters, :new_filter, :public_valid_options, :remove_custom_filter, :remove_muted_tags, :results_filter_callbacks, :results_filter_callbacks=, :tracked_filter, :unread_filter, :valid_options, :validate?, :validators, :yaml_tag]

Bisheriger Fortschrittsbericht:

  1. Bestätigt, dass statische TopicQuery Whitelist-Methoden wie add_custom_param_handler oder extra_options_whitelist in meiner Discourse-Version nicht als Klassenmethoden verfügbar sind, daher wurden diese Ansätze aufgegeben.

  2. Ein Patch für ListController#build_topic_list_options implementiert, um meine benutzerdefinierten URL-Parameter (z. B. market_item_statuses, market_price_min) in die opts-Hash zu injizieren, bevor TopicQuery.new aufgerufen wird.

  3. Dieser Teil funktioniert jetzt! Wenn ich eine Anfrage wie /c/market/5/l/latest.json?filter=defaultmarket_item_statuses=Available stelle, bestätigen meine Server-Logs die Injektion:

    [TecencMarket_ListControllerExt_BuildOptsV3] Injekted into opts: market_item_statuses = Available
    
    

    Somit erhält TopicQuery.new(user, opts) jetzt opts, die meine benutzerdefinierten Parameter enthalten.

Aktueller Engpass: 500 Fehler & Filter-Block wird nicht erreicht

Trotzdem, dass die Parameter jetzt korrekt an den Initializer von TopicQuery übergeben werden, erhalte ich immer noch einen 500 Internal Server Error, wenn die Anfrage diese benutzerdefinierten Marktparameter enthält.

Um das zu isolieren, habe ich meinen TopicQuery.add_custom_filter(:"tecenc_market_filters")-Block auf das absolut Minimum reduziert.

# plugin.rb - Aktueller vereinfachter benutzerdefinierter Filterblock
if ::TopicQuery.respond_to?(:add_custom_filter)
  ::TopicQuery.add_custom_filter(:"tecenc_market_filters") do |topics, topic_query|
    original_topics_relation = topics 
    opts = topic_query.options
    log_prefix_query = "[TecencMarket_SimplifiedFilter_V1.1_Test]" # Mein Debug-Prefix

    Rails.logger.info "#{log_prefix_query} Opts empfangen von TopicQuery: #{opts.inspect}"

    if opts[:market_item_statuses].present?
      Rails.logger.info "#{log_prefix_query} 'market_item_statuses' IST VORHANDEN in opts: #{opts[:market_item_statuses]}"
    else
      Rails.logger.info "#{log_prefix_query} 'market_item_statuses' IST NICHT VORHANDEN in opts."
    end
    
    Rails.logger.info "#{log_prefix_query} Rückgabe der ursprünglichen Topics-Relation."
    original_topics_relation # Implizite Rückgabe
  end
  Rails.logger.info "[TecencMarket] Angewandter vereinfachter Filter (V1.1_Test)."
end

Beobachtungen mit diesem vereinfachten Filter:

  • Anfragen ohne meinen benutzerdefinierten Filterparameter (z. B. /c/market/5/l/latest.json?filter=default):

    • Der vereinfachte Filter-Block protokolliert korrekt:

      [TecencMarket_SimplifiedFilter_V1.1_Test] Opts empfangen von TopicQuery: {:category=>5, :filter=>"default", ...}
      [TecencMarket_SimplifiedFilter_V1.1_Test] 'market_item_statuses' IST NICHT VORHANDEN in opts.
      [TecencMarket_SimplifiedFilter_V1.1_Test] Rückgabe der ursprünglichen Topics-Relation.
      
      
    • Die Seite lädt mit einem 200 OK.

  • Anfragen mit meinem benutzerdefinierten Filterparameter (z. B. /c/market/5/l/latest.json?filter=defaultmarket_item_statuses=Available):

    • Das Log des ListController-Patches erscheint: [TecencMarket_ListControllerExt_BuildOptsV3] Injected into opts: market_item_statuses = Available

    • Ein Completed 500 Internal Server Error in ...ms tritt sofort danach auf.

    • Wichtig ist, dass KEINE Logs aus dem vereinfachten Filterblock erscheinen (keine [TecencMarket_SimplifiedFilter_V1.1_Test]... Zeilen) für diese fehlerhafte Anfrage.

Dies deutet darauf hin, dass der 500-Fehler nachdem TopicQuery mit dem opts-Hash initialisiert wird (der jetzt meine benutzerdefinierten Parameter enthält), aber vor oder unmittelbar beim Versuch, das von Discourse zentrale TopicQuery#apply_custom_filters-Verfahren auszuführen, tritt der Fehler auf.

Ich habe Schwierigkeiten, die spezifische Ruby-Ausnahme und den vollständigen Backtrace aus development.log zu isolieren, die unmittelbar vor der Zeile „Completed 500…“ bei den fehlerhaften Anfragen auftreten (die Log-Auszüge, die ich gesammelt habe, zeigen die 500-Zeile selbst, aber nicht die detaillierte Fehlermeldung davor).

Folgefrage:

Angesichts:

  1. Dass benutzerdefinierte Parameter erfolgreich in TopicQuery.options durch den ListController-Patch injiziert werden.

  2. Dass ein 500-Fehler auftritt, wenn diese benutzerdefinierten Parameter in opts vorhanden sind.

  3. Dass dieser 500-Fehler vor dem Ausführen eines extrem vereinfachten benutzerdefinierten Filterblocks passiert (der nur protokolliert und die ursprüngliche Relation zurückgibt).

  4. Dass dies in Discourse 3.5.0.beta3-dev passiert.

Was könnte dazu führen, dass TopicQuery selbst oder seine Methode apply_custom_filters einen Fehler wirft, noch bevor ein registrierter benutzerdefinierter Filterblock aufgerufen wird, speziell wenn das options-Hash diese plugin-spezifischen Schlüssel enthält? Könnte der vorherige LocalJumpError, den wir vermuteten, noch relevant sein, auch auf einer niedrigeren Ebene, also bei der Handhabung der Iteration oder des Aufrufs der Filterblöcke durch apply_custom_filters, selbst wenn mein vereinfachter Block nur ein implizites return ist?

Jegliche Hinweise darauf, was als Nächstes bei TopicQuery im Umgang mit diesen Arten von benutzerdefinierten Optionen überprüft werden sollte, oder Ratschläge, wie man den vollständigen Backtrace für den 500-Fehler in diesem Szenario möglichst zuverlässig erhält, wären äußerst hilfreich.