Verwendung von veraltetem Code

  • Liebe Entwickler,

    im Laufe der vergangenen Versionen haben sich einige Komponenten angesammelt, die wir als veraltetet/deprecated markiert haben. Teilweise werden im Plugin-Store auch noch solche Komponenten verwendet, die seit Version 2.1 veraltet sind. Um diesen alten Code entfernen zu können, möchten wir hiermit auf relevanten Code aufmerksam machen und die Migration erläutern.

    In diesem Zuge möchten wir auch nochmals explizit darauf hinweisen, dass wir mittlerweile auch während der Entwicklung an neuen Versionen schon einen Migration Guide erstellen. So existiert mittlerweile auch schon eine Übersicht über Änderungen für Version 5.5, insbesondere eine Liste von Komponenten, die mit Version 5.5 veraltet sind bzw. entfernt werden.

    Im Folgenden haben wir eine Übersicht über einige veraltete Komponten erstellt, die wir bald entfernen möchten, aber teilweise noch in Paketen im Plugin-Store verwendet werden.

    PHP

    AttachmentBBCode::setAttachmentList()/AttachmentBBCode::setObjectID()

    Seit der Einführung der Embedded Objects-API mit Version 2.1, die neben Dateianhängen auch andere eingebundene Inhalte unterstützt, werden AttachmentBBCode::setAttachmentList() und AttachmentBBCode::setObjectID() nicht mehr benötigt, da die über diese Methoden gesetzten Werte nur dann verwendet werden, wenn AttachmentBBCode auf einen Dateianhang nicht über die Embedded Objects-API zugreifen kann.

    Wenn also die Embedded Objects-API verwendet wird, können diese beiden Methodenaufrufe entfernt werden. Ansonsten sollte dringend auf die Embedded Objects-API umgestelt werden.

    FileUtil::downloadFileFromHttp()

    FileUtil::downloadFileFromHttp() ist seit Version 2.0 veraltet und sollte, je nach unterstützten WoltLab Suite-Versionen durch HTTPRequest oder direkt durch Guzzle ersetzt werden.

    BlogDatabaseObject/CALENDARDatabaseObject/GalleryDatabaseObject/FilebaseDatabaseObject/WBBDatabaseObject

    App-spezifische DatabaseObject-Klassen werden seit Version 2.1 nicht mehr benötigt, da dass App-Präfix für die Datenbank-Tabellen von DatabaseObject selbst bestimmt wird. Es kann also direkt von DatabaseObject anstelle der App-spezifische DatabaseObject-Klasse geerbt werden.

    IEventListener

    IEventListener ist seit Version 2.1 veraltet und sollte durch IParameterizedEventListener bzw. AbstractEventListener ersetzt werden. Mit Version 5.5 werden wir neue Event-Klassen einführen, was wir bereits im Migration-Guide für Version 5.5 erklärt haben.

    ClassUtil::isInstanceOf()

    ClassUtil::isInstanceOf() ist seit Version 3.0 veraltet und sollte durch is_subclass_of() ersetzt werden.

    appendSession- und forceWCF-Parameter für LinkHandler::getLink()

    Der Session-Parameter appendSession und forceWCF werden seit Version 3.0 nur noch aus dem Parameter-Array von LinkHandler::getLink() gelöscht und ansonsten ignoriert. Sie können also aus dem Parameter-Array beim Methodenaufruf gelöscht werden.

    Mail

    Die Mail-Klasse ist seit Version 3.0 veraltet und sollte durch wcf\system\email\Email oder wcf\system\email\SimpleEmail ersetzt werden.

    UserProfile::getUserProfile() und UserProfile::getUserProfiles()

    UserProfile::getUserProfile() und UserProfile::getUserProfiles() sind seit Version 3.0 veraltet und sollten jeweils durch UserProfileRuntimeCache::getObject() und UserProfileRuntimeCache::getObjects() ersetzt werden, wobei UserProfileRuntimeCache::getObjects() für nicht-vorhandene Benutzer einen null-Eintrag zurückliefert.

    Event-Listeners und Cronjobs ohne Namen

    Seit Version 3.0 unterstützen Event-Listeners und Cronjobs ein name-Attribut, über das sie identifiziert werden können. Event-Listeners und Cronjobs ohne expliziten Namen sollten durch Event-Listeners und Cronjobs mit Namen ersetzt werden.

    IStackableUserNotificationObject

    IStackableUserNotificationObject ist seit Version 3.1 veraltet und wird nicht mehr verwendet. Das Interface sollte daher nicht mehr implementiert werden.

    EntryDataHandler/EventDataHandler/ImageDataHandler/PostDataHandler/CommentDataHandler

    Die DataHandler-Klassen wurde durch entsprechende RuntimeCache-Klassen ersetzt und sollten deshalb nicht mehr verwendet werden.

    Hinweis: filebase\system\file\FileDataHandler wird erst mit Version 5.5 veraltet sein und durch filebase\system\cache\runtime\FileRuntimeCache ersetzt.

    UserNotificationHandler::deleteNotifications()

    UserNotificationHandler::deleteNotifications() ist seit Version 2.1 veraltet und sollte durch Aufrufe von UserNotificationHandler::markAsConfirmed() (mit gleicher Methodensignatur) ersetzt werden.

    CryptoUtil-Methoden

    CryptoUtil::secureCompare() ist seit Version 5.2 veraltet und sollte durch \hash_equals() ersetzt werden. CryptoUtil::randomBytes() ist seit Version 5.2 veraltet und sollte durch \random_bytes() ersetzt werden. CryptoUtil::randomInt() ist seit Version 5.2 veraltet und sollte durch \random_int() ersetzt werden.

    Für die Kodierung von sicherheitsrelevanten Daten, die beispielsweise mit \random_bytes() genereriert werden, sollte ab Version 5.4 außerdem ein Constant Time Encoder genutzt werden.

    Callback

    Die Callback-Klasse ist seit Version 3.0 veraltet und sollte nicht mehr verwendet werden.

    Veraltete Seiten-Komponenten

    Seit der Überarbeitung der Seiten und Einführung von CMS-Seiten mit Version 3.0 sind IBreadcrumbProvider, IHistorySavingObjectTypeProvider::getActivePageMenuItem(), ISearchableObjectType::getActiveMenuItem(), ITrackablePage, IUserOnlineLocation und UserOnlineLocationHandler veraltet und sollten nicht mehr verwendet werden.

    AbstractHtmlInputNodeProcessorListener-Methoden

    AbstractHtmlInputNodeProcessorListener::replaceLinksWithBBCode() und AbstractHtmlInputNodeProcessorListener::setObjectTitles() sind seit Version 5.2 veraltet und sollten durch AbstractHtmlInputNodeProcessorListener::replaceLinks() ersetzt werden.

    SearchIndexManager::add() und SearchIndexManager::update()

    SearchIndexManager::add() und SearchIndexManager::update() sind seit Version 3.0 veraltet und sollten jeweils durch SearchIndexManager::set() ersetzt werden.

    SystemException

    SystemException ist zwar nicht offiziell veraltet, wird in neuem Code von uns nicht mehr verwendet. Wir verwenden stattdessen Exceptions aus der SPL oder eigene Exception-Klassen. In Plugins sollten deshalb soweit wie möglich auch keine SystemException mehr geworfen werden. Da SystemException von vorhandenem Code noch geworfen wird, müssen diese ggf. auch noch gefangen werden. Unter Umständen ist es aber möglich, stattdessen alle \Exception zu fangen.

    JavaScript

    WCF_CLICK_EVENT

    WCF_CLICK_EVENT sollte in JavaScript- und TypeScript-Code durch "click" ersetzt werden.

    WCF.ACP.Worker

    WCF.ACP.Worker ist seit Version 3.1 veraltet und kann einfach auf WoltLabSuite/Core/Acp/Ui/Worker umgeschrieben werden.

    Templates

    $__wcfVersion

    Die Template-Variable $__wcfVersion zum Brechen von Browser-Caches ist seit Version 2.1 veraltet und sollte durch LAST_UPDATE_TIME ersetzt werden.

    DateDiffModifierTemplatePlugin

    DateDiffModifierTemplatePlugin ist seit Version 3.1 veraltet und sollte durch DateIntervalFunctionTemplatePlugin ersetzt werden werden.

  • Seit wann entspricht WCF_CLICK_EVENT eigentlich bereits click? Im WSC 3.1 scheint das bereits der Fall zu sein (clickEvent wird nicht genutzt):

    JavaScript
        /* assigns a global constant defining the proper 'click' event depending on the browser,
           enforcing 'touchstart' on mobile devices for a better UX. We're using defineProperty()
           here because at the time of writing Safari does not support 'const'. Thanks Safari.
         */
        var clickEvent = ('touchstart' in document.documentElement || 'ontouchstart' in window || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0) ? 'touchstart' : 'click';
        Object.defineProperty(window, 'WCF_CLICK_EVENT', {
            value: 'click' //clickEvent
        });
  • Hallo,

    Seit wann entspricht WCF_CLICK_EVENT eigentlich bereits click? Im WSC 3.1 scheint das bereits der Fall zu sein (clickEvent wird nicht genutzt):

    Use click event globally for now · WoltLab/WCF@7932131
    We need to evaluate if we can use a 3rd party library to consistently use pointer events. Using 'touchstart' has its issues, but gets rid of the lame tap delay.
    github.com
  • IEventListener ist seit Version 2.1 veraltet und sollte durch IParameterizedEventListener bzw. AbstractEventListener ersetzt werden. Mit Version 5.5 werden wir neue Event-Klassen einführen, was wir bereits im Migration-Guide für Version 5.5 erklärt haben.

    Heißt das IParameterizedEventListener wird auf absehbare Zeit deprecated? Für mich wirkt die neue Implementation mit IEvent deutlich unflexibler. Standardmäßig komme ich nicht an die aufrufende Klasse und deren Properties und kann generell nur das modifizieren, was der Entwickler des Ausgangspakets vorsieht, wenn ich das richtig sehe.

    Abgesehen davon, warum sollte ich eine Klasse für einen Listener erstellen und sie explizit aufrufen statt den Part in einer Funktion/Trait/direkt im Code zu handeln? Der explizite Listener muss ja im Ausgangspaket bekannt sein und die entsprechede Klasse vorhanden. Wo ist da der Sinn - oder deute ich die Doku falsch?

  • Hallo,

    Heißt das IParameterizedEventListener wird auf absehbare Zeit deprecated?

    Neue Events werden auf Basis von IEvent implementiert. Bei bestehenden Events kommen wir auf absehbare Zeit wohl nicht um IParameterizedEventListener drum herum.

    Standardmäßig komme ich nicht an die aufrufende Klasse und deren Properties und kann generell nur das modifizieren, was der Entwickler des Ausgangspakets vorsieht, wenn ich das richtig sehe.

    Das ist korrekt und genau so gewollt.

    Abgesehen davon, warum sollte ich eine Klasse für einen Listener erstellen und sie explizit aufrufen statt den Part in einer Funktion/Trait/direkt im Code zu handeln?

    Das musst du falsch verstanden haben. Konzeptionell funktionieren die Listener und Events wie die bereits bekannten Listener und Events. Mir ist auch nicht klar, wie ich das besser als die Beispiele in den Docs erklären können sollte.

  • Das musst du falsch verstanden haben.

    Manchmal hilft ein Beispiel… Beim Tippen gerade festgestellt, dass ich den Zwischenschritt über eine eigene Klasse fehlinterpretiert habe. Man hört jetzt im Prinzip auf die Klasse, die dazwischen hängt. :)

    Das ist korrekt und genau so gewollt.

    Joa, relativ uncool. Also für Drittentwickler, die über die Vorstellungskraft des Entwicklers des Ausgangspakets hinaus gehen wollen.

  • Joa, relativ uncool. Also für Drittentwickler, die über die Vorstellungskraft des Entwicklers des Ausgangspakets hinaus gehen wollen.

    Ob da in Zukunft ein Class-Proxy-System kommt? Find da die Umsetzung im XF interessant und echt flexibel.

  • Hallo,

    Joa, relativ uncool. Also für Drittentwickler, die über die Vorstellungskraft des Entwicklers des Ausgangspakets hinaus gehen wollen.

    ich hätte in meiner ersten Antwort vermutlich noch ein wenig mehr ausführen sollen, weil sich in der Praxis eigentlich gar nichts ändert (bzw. die Flexibilität sogar steigt).

    1. Die Klassen sind ein sauberer Ersatz für das $parameters-Array, weil du komplette IDE-Unterstützung hast. Auch bei den $parameters bekommst du nur das, was der Entwickler dir bereitstellt.
    2. Die „alten“ Events waren nie als Freifahrtschein dafür gedacht an beliebigen Properties vom „feuernden“ Objekt rumzufummeln – hier muss ich erneut auf OO-Best-Practices verweisen. Dass das bislang möglich war ist also kein Feature, sondern eher der seit 2007 kaum überarbeiteten Architektur geschuldet, die zum Teil auch durch den schäbigen OO-Support in PHP um 2007 bedingt war. Diese feste Bindung an die Klasse die das Event feuert sorgt dafür, dass die bestehende Implementierung in der Praxis in Beton gegossen wird.
    3. Du kannst jetzt dasselbe logische Event an mehreren Stellen feuern. Bei dem Entwurf explizit als PoC-Beispiel genutzt wurde das in der Doku beispielhaft genannte UserLoggedIn-Event. Aktuell gibt es keine sinnvolle Möglichkeit zu erkennen, wann sich ein Benutzer konzeptionell einloggt, insbesondere wenn alternative Login-Möglichkeiten durch Plugins hinzukommen. Die Events in changeUser sind kein sinnvoller Indikator.
    4. Funktionieren die Events in der JavaScript-DOM-API, Javas Swing, den großen PHP-Frameworks (Laravel, Symfony) und PSR-14 ganz genau so. Dort scheint es offensichtlich auch zu funktionieren ;)
    5. Freuen wir uns natürlich über sinnvolle Vorschläge für Events. Insbesondere, da neue Events jetzt deutlich weniger invasiv in bestehenden Code integriert werden können. Es sind keine neuen Objekt-Properties von Nöten, die Events sind von der bestehenden Implementierung entkoppelt, was notwendiges Refactoring erleichtert, und auch dieser Pfusch mit $parameters entfällt.
  • Die Klassen sind ein sauberer Ersatz für das $parameters-Array, weil du komplette IDE-Unterstützung hast. Auch bei den $parameters bekommst du nur das, was der Entwickler dir bereitstellt.

    Die IDE Unterstützung ist prinzipiell super, ich hatte bisher halt immer instanceof verwendet oder phpDoc; je nach Anwendungsfall.

    Mir geht's weniger um die $parameter als um die Klassen-Properties, die man bisher relativ einfach überschreiben kann (teilweise), was Möglichkeiten schafft, die eventuell nicht ganz so vorgesehen waren oder es einfach nicht anders geht.

    Beispielsweise konnte ich einzelne Objekte aus der Liste herausnehmen oder auf einfache Art Bedingungen zu DatabaseObjectList-Objekten auf Seiten hinzufügen. Gut, effektiv hängt es schlussendlich von der genauen Implementierung der Events ab…

    Die „alten“ Events waren nie als Freifahrtschein dafür gedacht an beliebigen Properties vom „feuernden“ Objekt rumzufummeln – hier muss ich erneut auf OO-Best-Practices verweisen. Dass das bislang möglich war ist also kein Feature, sondern eher der seit 2007 kaum überarbeiteten Architektur geschuldet, die zum Teil auch durch den schäbigen OO-Support in PHP um 2007 bedingt war. Diese feste Bindung an die Klasse die das Event feuert sorgt dafür, dass die bestehende Implementierung in der Praxis in Beton gegossen wird.

    Dass das nicht dafür gedacht war, ist mir bewusst. Die komplette Klasse über den Autoloader auszutauschen ist aber noch mehr Blödsinn; musste ich aber tun, weil ihr eben keine Events eingebaut habt, die den Reaktionen z.B. doch wieder Wertungen zuführen könnten. Und für manche Anwendungen ist es eben notwendig, wenn nicht explizit für den Anwendungsfall Events implementiert werden - ich verweise hier einfach mal auf unsere qualitativen Diskussionen über Events hier und da, bei denen immer die Frage kommt "warum?" statt einfach mal "warum eigentlich nicht?".

    Ja, mir ist bewusst, dass man prinzipiell auch ein Objekt der Klasse Foo gegen ein Array hätte tauschen können und das dann vermutlich in der nächsten Funktion knallt, aber so viel Hirn traue ich den meisten doch zu. ;)

    Du kannst jetzt dasselbe logische Event an mehreren Stellen feuern. Bei dem Entwurf explizit als PoC-Beispiel genutzt wurde das in der Doku beispielhaft genannte UserLoggedIn-Event. Aktuell gibt es keine sinnvolle Möglichkeit zu erkennen, wann sich ein Benutzer konzeptionell einloggt, insbesondere wenn alternative Login-Möglichkeiten durch Plugins hinzukommen. Die Events in changeUser sind kein sinnvoller Indikator.

    Ja, die Glühbirne hat dann aufgeleuchtet, als ich's vorhin im Detail am Beispiel ausführen wollte. Das ist prinzipiell auch ganz cool bzw. sinnvoll.

    Freuen wir uns natürlich über sinnvolle Vorschläge für Events. Insbesondere, da neue Events jetzt deutlich weniger invasiv in bestehenden Code integriert werden können.

    Ich nehme dich beim Wort. ;)

    Ich werde mich damit vermutlich näher beschäftigen, wenn ihr anfangt umzubauen und mir die Möglichkeiten ausgehen.

  • Hallo,

    Die IDE Unterstützung ist prinzipiell super, ich hatte bisher halt immer instanceof verwendet oder phpDoc; je nach Anwendungsfall.

    Die IDE-Unterstützung funktioniert aber nicht mehr mit $parameters (ist beispielsweise in der Email-Klasse im Einsatz). Versuch mir mal ohne in den Code zu schauen zu sagen wie du den Versand einer E-Mail mit einem EventListener verhinderst. Mit den neuen Event-Klassen wäre das ein $event->preventDefault() (in Anlehnung an JavaScript).

    Beispielsweise konnte ich einzelne Objekte aus der Liste herausnehmen oder auf einfache Art Bedingungen zu DatabaseObjectList-Objekten auf Seiten hinzufügen. Gut, effektiv hängt es schlussendlich von der genauen Implementierung der Events ab…

    Das nutzen wir auch in unseren Plugins. Die Events hast du bei den Page|Form|Actions ja zwangsläufig weiterhin. In einer neuen Implementierung könnte die Page|Form|Action hypothetisch direkt IEvent implementieren, wenn es nur ein einziges sinnvolles Event für die Klasse gibt. Alternativ benutzt man irgendwie so etwas:

    PHP
    <?php
    final class BeforeSelect implements IEvent {
      public function __construct(MultipleLinkPage $page) { /* … */ }
      public function getObjectList(): DatabaseObjectList { return $page->objectList; }
    }
    
    // Benutzung in der UserListPage.
    EventHandler::getInstance()->fire(new BeforeSelect($this));

    Ich möchte nicht ausschließen, dass es da noch weitere Anpassungen gibt, wenn sich herausstellt, dass gewisse Dinge in der Praxis zu unschön werden. Das BeforeSelect-Event würde ich so wie beispielhaft dargestellt vermutlich nicht implementieren.

    ich verweise hier einfach mal auf unsere qualitativen Diskussionen über Events hier und da, bei denen immer die Frage kommt "warum?" statt einfach mal "warum eigentlich nicht?"

    Mit jeder neuen öffentlichen Schnittstelle und damit auch mit jedem Event geht man ein Commitment ein. Insbesondere mit dem bisherigen Konzept kommt dann wieder der Punkt mit dem Beton zum Einsatz: Wir müssen genau die Klasse mit genau den Properties beibehalten. Mit den unabhängigen Event-Klassen kann man das Event potentiell verschieben.

    Ein ganz konkretes Beispiel: https://github.com/WoltLab/WCF/issues/3608. Wenn es jetzt ein UserLoggedOut-Event gäbe, dann könnte man das Event in ein neues LogoutForm mitnehmen und ist nicht daran gebunden, dass der Logout über eine Action erfolgt. Das ist ein Implementierungsdetail was den Entwickler eigentlich gar nicht interessiert. Den Entwickler interessiert, dass ein Benutzer sich ausgeloggt hat – nicht, dass der Benutzer die LogoutAction erfolgreich benutzt hat.

    Grundsätzlich gilt aber natürlich weiterhin, dass man für etwaige Wünsche auch einen entsprechenden Use-Case mitbringen muss. Nicht immer ist die vorgeschlagene Lösung auch die konzeptionell sinnvollste Lösung. Stichwort: XY-Problem.

    Ja, mir ist bewusst, dass man prinzipiell auch ein Objekt der Klasse Foo gegen ein Array hätte tauschen können und das dann vermutlich in der nächsten Funktion knallt, aber so viel Hirn traue ich den meisten doch zu. ;)

    Ich würde es nicht auf fehlende „Hirnkapazität“ schieben, aber ich habe im Plugin-Store beispielsweise schon Plugins abgelehnt, die mittels Reflection dafür sorgen, dass Properties von private auf public gestellt wurden. Wenn das dann in einem Refactoring kaputt gehen würde, dann wäre natürlich wieder „WoltLab Schuld“, auch wenn die Intention dahinter durch das private mehr als deutlich sein sollte. Entsprechend sehe ich es auch als Aufgabe vom Framework an da entsprechende Guard-Rails bereitzustellen, damit man es gar nicht erst verkehrt machen kann.

  • Hallo,

    Add UserLoggedIn event and cancel lost password requests upon login by TimWolla · Pull Request #4356 · WoltLab/WCF
    Add a UserLoggedIn event Implement the UserLoggedIn event Cancel lost password requests when the user logs in
    github.com

    Es gibt jetzt einen ersten PR für ein UserLoggedIn-Event auf Basis der neuen Event-Klassen. Da ist dann auch ein beispielhafter EventListener mit drin.

    /cc gn5VmUKCtv6ekrMf (der schon Interesse gezeigt hat), Hanashi (der diverse externe Logins im Store hat).

  • Hallo,

    Könnte diese Liste bitte aktualisiert werden?

    Es müsste ja bereits feststehen, welche Methoden o.Ä. im Rahmen des 6.0-Releases wegfallen werden.


    Alternativ kann die Liste natürlich im Rahmen der Migrations-Doc überführt werden, allerdings habe ich eine derartige Liste dort beim letzten 5.5er vermisst (auch wenn die Migrations-Doc insgesamt sehr gut war, danke dafür!).

    VG

    Fr33chen

  • Sorry für das rauskramen des alten Threads. Als ich nach IEvent gesucht habe, kam nur diese bei raus.

    Ich versteh die Gründe für das neue IEvent für gewisse Events die nicht an eine bestimmte Klasse oder Ort gebunden sind. Ich versteh aber auch gn5VmUKCtv6ekrMf , weil man bei manchen Events eben genau diese in Beton gegossene Verbindung möchte, gerade die ganzen Action/Pages/Forms. "Zum Glück" wurde auch in 6.0 erstmal bei vorhandenen Events festgehalten, sollte das irgendwann mal angegangen werden, hoffe ich, dass ihr das mit bedacht macht, auch bei einem BeforeSelect geht es manchmal nicht um die ObjectList, sondern um irgendeinen state der in dem XYForm des Entwicklers gesetzt wurde und möchte gerne die ObjectList anhand des states anpassen. Als Beispiel, das können feste Events niemals abdecken, weil sie nicht erweitert werden können.

  • Es gibt von unserer Seite aus aktuell keine Planungen, die bestehenden, generischen Events abzulösen. Eventuell langfristig, aber absehbar ist da überhaupt nichts in der Pipeline.

    ass ihr das mit bedacht macht, auch bei einem BeforeSelect geht es manchmal nicht um die ObjectList, sondern um irgendeinen state der in dem XYForm des Entwicklers gesetzt wurde und möchte gerne die ObjectList anhand des states anpassen.

    Und genau das ist ein Paradebeispiel dafür, warum die bisherige Arbeitsweise aus der Perspektive eines Maintainers einen absoluten Albtraum darstellt. Die API-Surface ist als Folge dessen so gigantisch groß, dass jede noch so kleine Änderung zwangsläufig einen formalen Bruch der API-Kompatibilität zur Folge hat.

    Bei neuerem Code arbeiten wir absichtlich mit finalen Klassen und privaten Eigenschaften, sodass wir die öffentliche API so schlank wie möglich halten. Auf Anfrage können wir gezielt Daten nach außen freigeben, entweder durch das Setzen eines public oder einer neuen Methode, die die notwendigen Informationen bereitstellt ohne den internen State nach außen sichtbar zu machen.

  • Bei neuerem Code arbeiten wir absichtlich mit finalen Klassen und privaten Eigenschaften, sodass wir die öffentliche API so schlank wie möglich halten. Auf Anfrage können wir gezielt Daten nach außen freigeben, entweder durch das Setzen eines public oder einer neuen Methode, die die notwendigen Informationen bereitstellt ohne den internen State nach außen sichtbar zu machen.

    Als Plugin-Developer merkt man das leider sehr deutlich. An das Mobile Hauptmenü ist bis auf CSS leider gar nicht mehr ranzukommen und im Usermenü kann man nur noch listen von Elementen hinzufügen, die genau so aufgebaut sind, wie ihr das braucht. Keine Chance das groß anzupassen, denn so schön modular es aufgebaut ist, steckt hinter jedem MenuProvider ein UserMenuView die so viele private Methoden hat, dass es nur Friss oder Stirb vorgesehen ist. Einzige Möglichkeit ist, man zerpflückt sich das generierte HTML mühselig nachträglich. Andere Inhalte kann man über eine API hinzufügen, die sowohl neu hinzukommen ist und gleichzeitig "legacyMenu" heißt. Wenn das der zukünftige Weg ist, werden die Möglichkeiten sich gerade soweit erstrecken, wie ihr das für das WSC und eigene Apps braucht. Gute Nacht Plugin-Store.

    Edited 2 times, last by Warly (August 29, 2023 at 9:29 AM).

  • Hallo,

    das Usernenü stellt tatsächlich einen Sonderfall dar, weil die hier von dir angemerkten Einschränkungen so von mir gewollt sind und nichts mit der angesprochenen angepassten Vorgehensweise zu tun haben. Seit WCF 2.0 ist dies bereits die 3. Implementierung für das Usermenü, die auf Basis der zuvor gemachten Erfahrungen entstanden sind.

    Ein Problem der vorherigen Umsetzungen war stets, dass sehr viel Code redundant existierte und sich schleichend anders verhalten hat, insbesondere der Refresh war immer wieder fehlerhaft. Ein anderes Kernproblem war die Zweckentfremdung der Menüs für Anwendungsfälle, für die es überhaupt nicht vorgesehen war. Dabei geht es gar nicht so sehr um eine mangelhafte Konsistenz sondern darum, dass wir Annahmen darüber treffen müssen, welche Daten diese Elemente bereitstellen und wie diese zu interpretieren sind. Ein „Evergreen“ war die mobile Markierung für ungelesene Inhalte, die durch die Zweckentfremdung der Badges entstand.

    Ziel der neuen Implementierung in 5.5 war es daher dafür zu sorgen, dass eine Implementierung auf Basis von UserMenu sich tatsächlich auch wie ein solches verhält. Bei der Entwicklung ist daher auch legacyMenu entstanden, das die Abwärtskompatibilität zu den bisherigen Implementierungen gewährleistet.

    Aber auch hier gilt wieder: Wenn du einen Anwendungsfall hast, der aus deiner Ansicht ungenügend abgedeckt ist, dann melde dich bei uns (idealerweise direkt über GitHub!) und beschreibe diesen. Wir können dann zusammen schauen, welche Möglichkeiten sich dafür anbieten und eine passende Lösung ausarbeiten. Und genau das schrieb ich auch in dem von dir zitierten Text, es ist eben keine Einbahnstraße.

  • Ein anderes Kernproblem war die Zweckentfremdung der Menüs für Anwendungsfälle, für die es überhaupt nicht vorgesehen war. Dabei geht es gar nicht so sehr um eine mangelhafte Konsistenz sondern darum, dass wir Annahmen darüber treffen müssen, welche Daten diese Elemente bereitstellen und wie diese zu interpretieren sind. Ein „Evergreen“ war die mobile Markierung für ungelesene Inhalte, die durch die Zweckentfremdung der Badges entstand.

    Aber auch hier gilt wieder: Wenn du einen Anwendungsfall hast, der aus deiner Ansicht ungenügend abgedeckt ist, dann melde dich bei uns

    Genau da sehe ich das Problem. Weder ihr noch ich können unmöglich alle Anforderungen vorher absehen und genau das war die große Flexibilität bisher. Was bringt es, wenn ihr vllt hier und da die API öffnet, weil sich das jemand gewünscht hat, führt das nicht zu einem noch größeren Flickenteppich und schwer wartbarer API, als wenn man von Anfang an eine robuste aber einfach erweiterbare API aufbaut?

    Ich muss jetzt ins blaue Raten, aber auf einer Tippkick Seite möchte der Seitenbetreiber dem Nutzer vllt schnell und einfach seine Tipps anzeigen können, damit er sie schnell überprüfen und korrigieren kann. Spontan würde ich sagen, ist das Usermenü dafür perfekt geeignet, die Tipps sind User bezogen und das Usermenü ist schnell erreicht. Mit der neuen Umsetzung kann man das als Entwickler aber völlig vergessen, da Tipps weder "ungelesene Inhalte" sind, noch durch einfachen Titel und Text beschreibbar sind. Jetzt müsste ich als Entwickler irgendeiner Murkslösung mir ausdenken, um es doch ins Usermenü zu kriegen. Warum diese Beschränkung?

    Versteht mich nicht falsch, ich finde das neue Usermenü super, wenn man genau das haben möchte. Aber warum muss getView in WoltLabSuite/Core/Ui/User/Menu/Data/Provider.ts die konkrete Klasse UserMenuView zurückgeben, die so verbarrikadiert ist, dass man nichts machen kann? Warum kann es nicht ein Interface sein, dass die API erfordert, damit das Menü funktioniert? Wäre das wirklich eine so große und handlebare API, dass ihr es Entwicklern so schwer machen müsst? Das führt meiner Meinung nach nur dazu, dass Entwickler immer kreativere und fragilere Lösungen finden müssen, um Kundenwünsche zu erfüllen.

    Ihr habt in der Vergangenheit schon oft APIs geändert und breaking changes eingeführt, da reicht ja allein die Migration zu Typescript, die größtenteils gebridged wurde, aber nicht eben auch nicht zu 100%. Und das ist völlig fein, kommuniziert das und man kann sich darauf einstellen. Jetzt aber alles zu verbauen, dass man erst gar nicht rankommt, ist meiner Meinung nach absolut der falsche Weg.

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!