Web Programming Weeks SS17

Aus THM-Wiki
Wechseln zu: Navigation, Suche
Kurs
Kursname Web Programming Weeks SS 17
Kurstyp Projektkurs
Dozent Priefer, Rost, Dalmulder
Semester SS 17
Studiengang Bachelor, Master Informatik


Diese Seite dokumentiert die Ergebnisse der Gruppenprojekte.


Gruppe 1

Das Team

Name GitHub-Account
Clarissa Philipp Heggi93
Jannik Michel JannikMichel
Leon Peulings CiverBlack/Metal-Homer
Lavinia Popa-Rössel lavipr
Perrez Djouda perrez
Christian Djombissi Wameni christianboulbi
Oualid Meddah THMmeddah
Marcel Kugler AresRoxx10

Teil 1:

Repository

Pull-Request

Teil 2: Compare-Plugin:

Repository 2 Branches: displayDiff (Joomla 3) und 4.0-dev

Pull-Request

Aufgaben

Die Aufgabe bestand darin die multilinguale Funktionalität von Joomla zu erweitern. Dazu soll ein Core-Plugin entwickelt werden. Mehrsprachige Artikel sollen zukünftig auf ihre Aktualität überprüft werden, um die Verwaltung zu vereinfachen. Diese Aufgabe lässt sich in zwei Teilbereiche ausgliedern.

Teil 1

Eine (farbliche) Darstellung implementieren, in der man sehen kann, ob die gleichen Artikel in unterschiedlichen Sprachen auf dem gleichen Stand sind. Der Nutzer muss als unaktuell markierte Artikel manuell überprüfen, gegebenenfalls anpassen und abschließend als aktuell bestätigen.

Exsistieren mehrere Artikel in unterschiedlichen Sprachen mit dem selben Inhalt, können diese bereits untereinander verknüpft werden, um die Zusammengehörigkeit zu kennzeichenen. Um die oben genannte Funktionalität zu vereinfachen soll zusätzlich eine Master-Slave-Beziehung zwischen den Artikeln realisiert werden. Konkret bedeutet dies, dass innerhalb einer Artikelgruppe ein Artikel exsistiert der als Hauptartikel festgelegt wird(Master). Alle zugehörigen Artikel sollten sich im Idealfall vom Hauptartikel ableiten und bilden seine Slaves. In der Anwendung werden dann alle Slaves als unaktuell markiert, sobald sich der Master verändert.

Teil 2

Im Bearbeitungsfenster des multilingualen Bereichs soll ein Fenster angezeigt werden können, indem die Versionsunterschiede des Masterartikels angezeigt werden. Dabei soll die letzte gespeicherte und die aktuelle Version verglichen werden. Die Differenzen sollen farblich markiert werden ähnlich wie bei dem bereits vorhandenen Versionsvergleich [Administrator>>Components>>Articles>>Article-View>>Versions>>Compare]. Der Anwender kann so erkennen welche Änderungen seit der letzten Version vorgenommen wurden und die slave-Texte entsprechend anpassen.

Teil 1

Projektdokumentation

Zu Beginn wurde das Projekt auf eigene Teilbereiche aufgegliedert.
1. Neue Datendanktabelle (item_associations)erstellen, für die Master/Slave Beziehungen zwischen Artikeln in mehreren Sprachen.

  Attribute: id, parentid, approved.

2. Plugin implementieren Hier werden Vier Anwendungsfälle unterschieden, die die Werte in der Tabelle "item_associations" modifizieren sollen:

        - Alle neuen angelegten Artikel sind Master und ihr Attribut "approved" wird automatisch auf "1" in der Tabelle gesetzt.
        - Alle assoziierten Artikel(Slaves) zu einem Master-Artikel bekommen als "Parentid" die "id" des Master-Artikels und das
          Attribut "approved" wird auf 0 gesetzt.
          wird beim Anlegen in der Tabelle auf "0" gesetzt.
        - Beim Editieren eines Master-Artikels wird das Attribut "approved" in der Tabelle "item_associations" für jeden Slave-Artikel
          auf "0" gesetzt.
        - Beim Editieren eines Slave-Artikels wird sein Attribut "approved" in der Tabelle auf "0" gesetzt.

3. Approved Button integrieren. Wenn ein Kindartikel angelegt wurde, muss er noch mal im Komponent Multilingual Associations von einem User überprüft werden. Es gibt vier Fälle die auftretten können, wenn auf Button "Approved" geklickt wurde.

        -Der Master und Slave-Artikel sind noch nicht in unserer Tabelle(item_associations) gespeichert.
         Es müssen die beiden Artikel in der Tabelle mit folgenden Werten gespeichert werden. 
            Master-Artikel(id-masterartikel,0,1);
            Kindartikel (id-kindartikel,id-masterartikel,1)
        -Der Master und Slave-Artikel sind in unserer Tabelle gespeichert.
           Der Status von einem Kindartikel muss auf 1 gesetzt werden. 
        -Der Master-Artikel ist schon in unserer Tabelle gespeichert und der Slave-Artikel noch nicht.
            Der Slave-Artikel muss in der Datenbank mit folgenden Werten gespeichert werden.  
            Slave-Artikel (id-kindartikel,id-masterartikel,1)
            Bevor ein Slave-Artikel in der Datenbank gespeichert wird, muss zuerst geprüft werden,ob sein Master-Artikel auch schon 
            in der Tabelle vorhanden ist. Um Slave ohne Master-Artikel in der Tabelle zu vermeiden.  
        -Der Master-Artikel ist noch nicht in unserer Tabelle gespeichert und der Slave-Artikel schon.
            Der Master-Artikel muss in der Datenbank mit folgenden Werten gespeichert werden. 
            Masterartikel (id-Masterartikel,0,1) und der Status vom Slave-Artikel wird  auf 1 gesetzt

3. Darstellung der Assoziationen und der nicht Assoziationen von Artikeln in mehreren Sprachen.
Es können drei verschiedene Zustände zwischen Artikel bestehen:

        - grün, Assoziation und aktueller Artikel (Approved=1)
        - gelb, Assoziation und Artikel nicht aktuell (approved=0)
        - grau, keine Assoziation (Nicht in item_associations enthalten)

Implementierungsdetails

Als erstes haben wir eine neue Datenbanktabelle angelegt für die Umsetzung einer Master/Slave Beziehung zwischen Artikeln in mehreren Sprachen.

CREATE TABLE item_associations
(
   id INTEGER(11) NOT NULL,
   parentid INTEGER(11) NOT NULL,
   approved tinyint(1) NOT NULL,
   PRIMARY KEY(id)
);


Danach haben wir ein Plugin implementiert das in die neue Tabelle Zustände reinschreibt, sobald ein Artikel angelegt wird. Da beim anlegen von Artikel Probleme entstanden sind, mussten wir ein neues Event triggern, nachdem die Daten von Verknüpfungen in die Tabelle associations geschrieben wurde.

	        /**
	        * The event to trigger after saving the associations.
	        *
	        * @var    string
	        * @since  __DEPLOY_VERSION__
	        */
	        protected $event_after_save_associations = null;
-------------------------------------------------------------------------------------------------------------

		if (isset($config['event_after_save_associations']))
		{
			$this->event_after_save_associations = $config['event_after_save_associations'];
		}
		elseif (empty($this->event_after_save_associations))
		{
			$this->event_after_save_associations = 'onContentAfterSaveAssociations';
		}
--------------------------------------------------------------------------------------------------------------
// Trigger the after save event for associations
\JFactory::getApplication()->triggerEvent($this->event_after_save_associations, array($context, $table, $isNew));


In der Komponente "Multilingual Associations" wird die Assoziation von verschiedenen Artikeln dargstellt. Die Spalte "Not Associations" wurde entfernt, da sie für weitere Verwendungen nicht mehr gebraucht wird. In der Spalte Associations werden die Verknüpfungen und nicht Verknüpfungen wie folgt in der jeweiligen Sprache dargestellt:

        - grün, Assoziation und aktueller Artikel 
        - gelb, Assoziation und Artikel nicht aktuell 
        - grau, keine Assoziation (Nicht in item_associations enthalten)


Wenn ein Artikel selektiert ist und ein rotes Ausrufezeichen nach der selektierten Sprache steht, ist der Artikel nicht aktuell. Wenn ein Artikel nicht aktuell ist muss er manuell als aktuell bestätigt werden. Dafür haben wir einen "Save Approved" Button in der Komponente "Multilingual Association" implementiert. Wenn man zwei Artikel gegenüber stehen hat wird mit mit dem Button "Save Approved" bestätigt das die rechte Seite(Slave) aktuell ist.

Wenn man eine Sprache installiert, muss man in der Sprache-Datei wie in C:\xampp1\htdocs\WPW3\administrator\language\en-GB\en-GB.com_associations.ini folgende Werte in der entsprechenden Sprache hinzufügen.
COM_ASSOCIATIONS_SAVE_APPROVED="Save Approved"
COM_ASSOCIATIONS_NOT_APPROVED_NOPARENT="reference is not the master"
COM_ASSOCIATIONS_MESSAGE_APPROVED="approved"
COM_ASSOCIATIONS_NOTCHILD="firstly save the Target Article

Probleme

Es ging als erstes darum, die Struktur von Joomla zu verstehen, da keiner von der Gruppe früher mit diesem Framework gearbeitet hatte. Danach war es die Überlegung, wann das Plugin aufgerufen werden soll. Zusammen mit der Gruppe sind wir auf die Idee gekommen, dass das Plugin aufgerufen werden soll, nachdem ein Artikel in der Joomla-Datenbank gespeichert wurde. Beim Anlegen von Master-Artikeln hatte alles gut funktioniert. Ein großes Problem war aber das Anlegen von assoziativen Artikeln. Der alte Vorgang war:

- Anlegen von Artikel 
- Aufruf des Plugins für die Verwaltung der Daten in der Tabelle "item_associations"
- Anlegen der Assoziationsdaten

Aus dieser Beschreibung ist klar zu sehen, dass nur der Master-Artikel in der Tabelle "item_assoziations" gespeichert war. Man musste also zwei mal auf den "Save Button" klicken, um die Slave-Artikel auch zu speichern. Durch viele Diskussionen mit der Gruppe konnten wir dieses Problem lösen.

Ein großes Problem war die Differenzierung zwischen dem Anlegen von assoziativen Artikeln in der "Content-Area" und dem Anlegen von assoziativen Artikel durch das Komponente "Multilingual Associations". Wir sind von der Idee gegangen, dass alle neue Angelegten Artikel Master sein sollen. Aber wenn man die Artikel mit Hilfe dem "Multilingual Associations" anlegen will, werden Target Artikel als Master angelegt, obwohl die normalerweise Slave sind. Wir könnten keine Informationen finden, womit wir die Differenzierung machen könnten. Wir hatten aber auch nicht mehr genug Zeit, diese Hürde zu meistern.

Ein Weiteres Problem war die Umstellung von Joomla 3.8 auf Joomla 4.0. In der Vierten Version wurden viele Dateien gelöscht, einige Klassen nicht mehr unterstützt und die Verzeichnisstruktur wurde auch geändert. Durch die gute Dokumentation von Joomla 4.0 könnten wir dieses Problem lösen.

Außerdem sind wir auf einige Probleme bei der Implementierung unseres Buttons gestoßen

Wir haben zuerst in Joomla 3.8 unsere Erweiterungen entwickelt. Im joomla 3.8 ist die Formatierung der Datei Media/com_associations/js/sidebyside.js sehr schlecht, die ganze Seite auf eine Zeile,was uns die Arbeit mit dieser Datei schwer gemacht hat. Bei der Umstellung von Joomla 3.8 auf Joomla 4 haben wir auch Probleme mit JFactory gehabt, was uns auch viel Zeit gekostet hat

Related Issues

Issue 1. Für eine weitere Entwicklung macht es Sinn, dass das von uns entwickelte Plugin auch auf das Löschen von Artikeln zu erweitern, dazu muss die Tabelle item_associations eine Referenz auf andere Tabellen haben.
Issue 2. Da unsere jetzige Implementierung von Artikel funktioniert, sollten außerdem Content-Elemente wie "categories, Fields,.." betrachtet werden.
Issue 3. Momentan kann in einer Master/Save Beziehung sich der Slave nicht verändern, zur Verbeserung sollte sich der Slave auch nachträglich zum Master ändern lassen.
Issue 4. Normalerweise soll bei einer Master/Slave Verbindung, nur der Master als Referenz dienen um zu Bestätigen ob der Artikel aktuell ist. Momentan kann man auch einen Artikel als aktuell setzen, wenn die Referenz kein Master ist oder nicht aktuell ist.

Teil 2

Projektdokumentation

Planung: In der bestehenden Joomla-Installation gibt es bereits einen Versionsvergleich. Manuell können zwei Versionen eines Artikels ausgewählt werden, die im folgenden miteinander verglichen werden. Die Anzeige des Vergleichs markiert alle hinzugefügten Inhalte grün und alle entfernten Inhalte rot. Nach unserer Aufgabenstellung können wir diesen Vergleich direkt übernehmen, da wir ebenfalls zwei Versionen vergleichen müssen. Desweiteren soll die Vergleichsausgabe in einem eigenen Fenster angezeigt werden. Der Editor soll während der Anzeige nicht nutzbar sein, der Slave-Artikel soll jedoch weiterhin zu bearbeiten sein. Auch diese Funktionialität ist schon teilweise vorhanden. Als Vorlage für das Fenster kann die "Page Break"-Funktion dienen, bei der ebenfalls ein Fenster erzeugt wird und der Editor im Hintergrund gesperrt wird.

Durchführung: In den ersten Tagen haben wir uns eingehend mit der detaillierten Planung des Vorgehens beschäftigt. Zunächst haben wir uns mit den bereits implementierten Features auseinander gesetzt, die wir für unsere Zwecke nutzen wollten. Weiterhin gab es einige Disskussionen über die genau Umsetzung der Planung. Anschließend musste die Planung in die Tat umgesetzt werden. Als erstes mussten die beiden Texte herausgefiltert werden, die miteinander verglichen werden sollte. Der erste Text ließ sich aus der Datenbank entnehmen. Es handelt sich dabei um die vorletzte gespeicherte Version des Artikels. Der zweite Text entstammt dem Editorfenster. Wenn nach dem Öffnen des Artikels im Editor keine Änderungen vorgenommen wurden, entspricht er der letzten gespeicherten Version. Wurden Änderungen vorgenommen, ist es dementsprechend sinnvoll auch die hinzugefügten Änderungen in der Vergleichsübersicht anzuzeigen.

Im Editor wird ein neuer Button erzeugt, der die 'Compare'-Funktionalität aufruft. Der Button wird als Kopie des 'Page Break'-Buttons erstellt und entsprechend angepasst. Klickt man auf den Button wird ein Fenster erzeugt, das die Vergleichsübersicht beinhaltet. Sobald das Fenster geladen wird, wird eine JavaScript-Methode angestoßen, die die beiden Texte nach den o.g. Verfahren lädt und anschließend vergleicht. Die dazu verwendete Vergleichsmethode entstammt der diff_patch_match-Klasse, welche bereits im Joomla-Core enthalten ist. Die Methode liefert einen Text zurück, in dem beiden Versionen zusammengefügt sind und die Unterschiede mit HTML-Tags markiert wurden. Der zurückgelieferte Text wird dann direkt an des neue Fenster übergeben und angezeigt.

Nachdem die Grundfunktionalität gewährleistet war, mussten noch einige Ergänzungen implementiert werden. So steht die 'Compare'-Funktion nur im Menüpunkt 'Multilingual Associations' zur Verfügung. Desweiteren muss auch eine sinnvolle Ausgabe im Fenster erscheinen, wenn bisher nur eine Version des Artikels exsistiert und ein Vergleich noch kein Ergebnis liefert. Auch das Ein- und Ausblenden der HTML-Tags sollte möglich sein. Dazu wurde die bereits in 'Compare' enthaltene Funktionalität kopiert und der neuen Umgebung angepasst. Neben funktionalen Anpassungen, war es uns auch wichtig eine ansprechende Gestaltung des Plugins umzusetzen. Bei dem Vergleich mit dem 'Page Break'-Plugins fiel uns auf, dass sich das öffnende Fenster nur selten an den Editor anpasst. Häufig erschien es sehr weit unten auf der Seite, sodass man zunächst das Gefühl hatte es wäre gar nicht aufgetaucht. Das Fenster unseres Plugin passt sich durch ein JavaScript dynamisch an das Eingabefeld des Editors. Es nimmt die gleiche Größe und Position an.

Während der Entwicklung des Plugins haben wir mit der Joomla-Version 3.9 gearbeitet. Damit die Erweiterung auch in der neuen Version 4.0 verfügbar ist, wurde sie nach ihrer Fertigstellung auch auf dieser Umgebung getestet. Dabei ergaben sich einige Probleme die behoben werden mussten. Zum einen haben wir bei der ursprünglichen Version die Klasse 'BaseModel' verwendet. Diese exsistiert in Joomla 4.0 nicht und musste durch die Klasse 'Model' ersetzt werden. Weiterhin gab es einige Probleme mit den neu eingeführten Namespaces. Einige verwendeten Methoden waren in ihrer Funktionalität eingeschränkt da sie die Verwendungen von Namesspaces nicht unterstützten. Diese Methoden mussten ersetzt werden.

Die letzte Schwierigkeit war das Verschwinden einiger JavaScript-Dateien, die für den Versionsvergleich der Texte essentiell waren. Hier orientierten wir uns erneut an der, auch in Joomla 4.0 bereits lauffähigen, 'Compare'-Funktion. In unserem JavaScipt mussten einige Übergabeparameter und Rückgabewerte angepasst werden, bis die Funktionalität wieder hergestellt war. Auch die designtechnischen Änderungen wurde nicht übernommen.

Implementierungsdetails

Grundliegender Aufbau

Der Quellcode des Plugins befindet sich in insgesamt 4 Dateien. Den Kern bilden zwei Dateien im Plugin-Ordner (Joomla\plugins\editors-xtd\showdiff\...). Hier liegt die xml-Datei(showdiff.xml), die das Plugin beschreibt. Hier wird auch auf die php-Datei und die Sprachdateien verwiesen. Die php-Datei(showdiff.php), die ebenfalls in dem Ordner zu finden ist, erzeugt den Button Editor und erzeugt die Verlinkung zur php-Datei, die das Fenster erzeugt. Das Fenster, das den verglichenen Text ausgibt, wird ebenfalls durch eine php-Datei erzeugt(showdiff.php), die innerhalb des Administrator-Ordners(Joomla\administrator\components\com_content\tmpl\article\...) abgelegt ist. Das Popup wird mit Hilfe eines Templates erzeugt. Weiterhin befindet sich hier die Funktionalität, welche den Text aus dem Editor ausließt und der HTML-Code, der innerhalb des Fensters angezeigt wird. Die letzte Datei ist eine JavaScript-Datei(admin-article-showdiff.js), die im Media-Ordner(Joomla\media\com_content\js\...) hinterlegt ist. Beim Laden des Popup wird sie angestoßen und führt den Vergleich der beiden Texte durch. Zusätzlich sorgt sie auch für die Design-Anpassungen des Fensters.

Weitere Ausführungen

In der Klasse .../media/com_contenthistory/js/diff_match_patch.js ist die Methode diff_main(a,b,c,d) zu finden, die einen Vergleich mehrerer Dokumente durchführt. Als Übergabeparamter können unterschiedliche Typen übergeben werden. In unserem Fall übergeben wir zwei HTML-Dokumente (beide Dokumente müssen selbstverständlich im gleichen Format sein, um einen korrekten Vergleich durchführen zu können). Der Rückgabewert des Methodenaufrufs ist ein Array, in welchem zu jedem Textabschnitt hinterlegt ist, in welche Kategorie er fällt (Hinzugefügt, Entfernt, Unverändert).

Um den Rückgabewert verständlich anzeigen zu können, wird die Methode make_pretty_diff(diff_text) aufgerufen. Diese Methode entstammt dem unter .../media/com_contenthistory/js/pretty_text_diff.js zu findenden Script. Um sie auch für uns nutzbar zu machen, wurde die Funktion in unseren Code kopiert. Der Methode wird jeweils ein Element des erzeugten Vergleichsarray übergeben. Die Methode wandelt das Element in einen gültigen HTML-Tag um. Elemente die unverändert geblieben sind, werden als <span>-Element zurückgegeben. Elemente die neu hinzugekommen sind, werden in ein <ins>-Element eingeschlossen, sodass sie in der Ausgabe grün hinterlegt werden. Alle entfernten Elemente erscheinen durch das verwendete <del>-Tag rot und durchgestrichen. Die Tags sind in der .../media/com_contenthistory/css/jquery.pretty-text-diff.css beschrieben. Die einzelenen Elemente werden schlussendlich wieder zusammengefügt und gemeinsam ausgegeben.

   var dmp = new diff_match_patch();
   diff_html = dmp.diff_main(text1, text2);
   diff_html.forEach(function (elem) {
            
       innerHTML += make_pretty_diff(elem);
   });
   document.getElementById("diff_area").innerHTML = innerHTML;

Um dem User zu ermöglichen den Text sowohl mit als auch ohne HTML-Tags anzuzeigen wurde eine zweiter String angelegt welcher vor der Anwendung von make_pretty_diff(diff_text) von allen HTML-Tags bereinigt wird.

   ...
   diff_text = dmp.diff_main(clean_tags(text1), clean_tags(text2));
   diff_text.forEach(function (elem){
      innerText += make_pretty_diff(elem);
   });
   document.getElementById("diff_area").innerHTML = '<div class="diff_html" style="display: none">' + innerHTML + '</div> <div class="diff_text" style="display: table-cell">' + innerText + '</div>';

Dazu wurde der Text mit dem Regulären Ausdruck <.*?> nach HTML-Tags durchsucht und diese wurden anschließend entfernt. Durch die verschiedenen Klassen diff_text und diff_html können die beiden Texte durch .hide bzw .show ein und ausgeblendet werden.

Als letztes erfolgte die Design-Anpassung. Dazu greifen wir auf das Textfeld des Editors zu und lesen die Werte wie Position und Größe aus. Diese werden dann via JavaScript auf das Popup-Fenster übertragen. Sobald der korrekte Text angezeigt wird, befindet sich das Fenster auch an seiner neuen Position.

Umstellung auf Joomla 4.0

Wie bereits beschrieben, musste bei der Integration des Plugins in Joomla 4.0 einige Änderungen vorgenommen werden. Um den Text des Editors auslesen zu können, muss das Model der Klasse ContentHistory angesprochen werden. In der Version 3.9 wird die Klasse BaseModel verwendet, die eine Instanz des benötigten Models zu erzeugen.

BaseModel::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_contenthistory/models/');

/** @var ContentHistoryModelHistory $contentHistory */
$contentHistory  = BaseModel::getInstance('History', 'ContenthistoryModel');

Die Klasse BaseModel exsistiert in Joomla 4.0 nicht mehr. Ihre Funktionaltiät ist größtenteils in der Klasse Joomla\CMS\Model\Model zu finden. Hier gibt es allerdings Probleme mit den Namespaces. Die von uns instanziierte Klasse Joomla\Component\Contenthistory\Administrator\Model\History befindet sich in ihrem eigenen Namespace. Die Methode 'getInstance()' kann diesen Namespace nicht entgegennehmen und daher die gewünscht Klasse nicht instanziieren. Namesspaces bringen aber auch den Vorteil, dass Klassen direkt eingebunden werden. In der neuen Version kann die Erzeugung des Objekts daher über den Konstruktor erfolgen und die Verwendung der Klasse Model entfällt.

/** @var Joomla\Component\Contenthistory\Administrator\Model\History $contentHistory */
$contentHistory = new History;

Alle weiteren Anpassungen fanden in der JavaScript-Datei statt. Die ursprünglich verwendete Klasse diff_match_patch und die zugehörigen Methoden existieren in Joomla 4.0 nicht mehr. Stattdessen wird bei dem Versionsvergleich in der Artikelansicht die Funktionalität der Datei admin_compare_compare.js verwendet. Da die gewünschten Methoden mit einem EventListener verknüpft sind, können wir sie nicht aus unserem Code heraus aufrufen. Wir haben die entsprechenden Aufrufe daher in unsere Datei kopiert und modifiziert. Der Vergleich wird nun von der Methode JsDiff.diffWords(text1, text2) übernommen, die als statische Methode ohne Objektinstanz aufgerufen werden kann. Da sie, anders als diff_main(a,b,c,d), Objekte als Rückgabewert liefert, muss auch die Schleife für die Anzeige angepasst werden. Wir erzeugen nun direkt HTML-Objekte, die an das Dokument angehängt werden. Sämtliche HTML-Attribute können dadurch direkt in der JavaScript-Datei gesetzt werden. Dadurch bietet sich der Vorteil, dass der Wechsel zwischen den unterschiedlichen Anzeigen (mit und ohne HTML-Tags) unverändert bleiben kann. Die neuen Elemente erhalten die entsprechenden Klassen (vgl. obige Beschreibung) und können mit Hilfe des Buttons gewechselt werden.

diff_html = JsDiff.diffWords(text1, text2);
fragment = document.createDocumentFragment();

diff_html.forEach(function (part) {
    color = part.added ? '#a6f3a6' : part.removed ? '#f8cbcb' : '';
    span = document.createElement('span');
    span.style.backgroundColor = color;
    span.style.borderRadius = '.2rem';
    span.appendChild(document.createTextNode(part.value));
    span.className = "diff_html";
    span.style.display = "none";
    fragment.appendChild(span);
});

.../*Gleiches Vorgehen für Alternativtext*/...

spanParent = document.createElement('div');
spanParent.id = "diff_area";
spanParent.appendChild(fragment);

document.getElementById("diff_area").replaceWith(spanParent);
}

Probleme

Als erstes ging es darum zu evaluieren welche Textvergleiche Sinn ergeben. Zur Auswahl standen drei Versionen eines Artikels. Die erste ist die vorletzte gespeicherte Version. Bei der zweiten Version handelt es sich um die letzte Speicherung. Die dritte Version entsteht nur dann, wenn der Artikel geöffnet ist, und im Editor bearbeitet wird. Die dort eingegebenen Änderungen sollen schließlich mit berücksichtigt werden. Da beim Öffnen des Editors jeweils die letzte gespeicherte Version (= 2. Version) angezeigt wird, sind wir zu dem Entschluss gekommen, dass es nur sinnvoll ist die Differenzen zwischen der vorletzten gespeicherten Version (=1) und der aktuell angezeigten Version (=3) anzuzeigen. Alle Änderungen der zweiten Version sind dann automatisch enthalten.

Um möglichst geschickt nach dem dry(don't-repeat-yourself)-Prinzip vorzugehen, war eine Einarbeitung in die bestehenden Komponenten und Plugins notwendig. Durch den Umfang des Projekts hat diese Arbeit länger gedauert als geschätzt. Besonders die Verwendung von internen Weiterleitungen oder Templates erschwerten das Verständnis erheblich. Durch gemeinsamen Austausch und Diskussion konnten wir die Hürde meistern. Gegen Ende des Projekts zeigten sie die Früchte des Aufwands: Der von uns implementierte Code ist relativ übersichtlich und klar strukturiert.

Ein großes Problem war die Umstellung von Joomla 3.9 auf Joomla 4.0. Mit dem Versionsprung, werden die Verzeichnisse neu strukturiert und einige Dateien gelöscht. Da wir die Funktionalität bereits enthaltener Klassen benutzten, waren unsere Methoden nicht mehr nutzbar. Einige Teile des Codes mussten umstrukturiert und Teile ausgetauscht (vgl. Implementierungsdetails) werden. Hätten wir direkt auf Joomla 4.0 entwickelt, wären wir diesen Problemen aus dem Weg gegangen. Im nachhinein war unser Weg aber kein Nachteil, da die Dokumentation von Joomla 3.x besser ist und es so einfacher war, die vorhandene Funktionalität nachzuvollziehen.


Den Datenbank Zugriff haben wir komplett über ein anderes Model geregelt (ContenthistoryModel). Problem dabei war, dass dieses Model einen Zustand hat. Aus dem Zustand kommt die ID des Artikels. Da der Zustand aber erst initialisiert wird nachdem man einmal darauf zugegriffen hat, muss man erstmal den Zustand aufrufen und danach setzen.

Related Issues

In der weiteren Entwicklung ergibt es Sinn die gewählten Texte für den Vergleich anzupassen. Um dem Nutzer immer alle Änderungen anzeigen zu können, die im gewählten Slave-Element noch nicht aktualisiert wurden, sollte ansatt der vorletzten gespeicherten Version eine dynamische Auswahl stattfinden. Dazu müsste in den Slave-Elementen hinterlegt sein, seit welcher Änderung sie nicht mehr als aktuell gelten. Bei Vergleich müsste dann die hinterlegte und die aktuelle Version verwendet werden. So könnte auch nach mehrmaligem Speichern noch wichtige Änderungen angezeigt werden. Wir würde hier ein Dropdown-Menü in der Vergleichsübersicht vorschlagen. Der Nutzer kann im Editor des Slave-Elements die Version ablesen, seit dem der Slave nicht mehr aktuell ist. Er kann dann den Vergleich auf die entsprechende Version konfigurieren.

Pull-Request für das deutsche Language-File, um die deutsche Sprachdatei hinzufügen zu können.

Während der Umstellung auf 4.0 fiel uns auf, dass viele der Funktionalitäten der ursprünglichen *Compare"-Funktion der Versionsverwaltung entfernt wurden. Mit dieser Umstellung fielen uns einige Probleme auf und wir haben eine neue Issue eröffnet, um das Wiedereinführen dieser Funktionalitäten anzustoßen. Diese findet sich unter #17786.

Zudem funktioniert das Speichern in Joomla nicht mehr, wenn man als Datenbank MySQL (PDO) nutzt. Deswegen wurde eine weitere Issue eröffnet #17803.


Gruppe 2

Das Team von Gruppe 2 hat es sich zur Aufgabe gemacht einen Pre Update Check für Joomla-Updates zu implementieren.

Das Team

Name GitHub-Account
Samuel Schepp SamuelSchepp
Kevin Linne Kev1n337
David Donges DrDreave

Repository Pull Request

Aufgaben

Fehler beim Erstellen des Vorschaubildes: Datei fehlt
Mockup der Anzeige des Pre Update Checks

Der Pre Update Check soll Nutzer über die Kompatibilität Ihres Systems und installierter Erweiterungen mit einem Joomla-Update informieren. Diese Überprüfung soll dem Nutzer angezeigt werden, bevor er die Installation des Updates startet. Die Kompatibilitätsprüfung besteht aus drei Kategorien.

  • Es werden Server-Optionen unter der Überschrift "Pre Update Check" überprüft, wie der Datenbank-Support oder die installierte PHP-Version.
  • Unter "Recommended Settings" erden Einstellungen verglichen mit den empfohlenen Optionen, z.B. die Aktivierung des Safe-Modes oder des ZIP-Supports.
  • Im "3rd Party Extensions Pre-Update Check" wird die Kompatibilität von installierten Erweiterungen überprüft.

Das Problem wurde in Pull Request #16494 diskutiert und beispielhaft mit einem Mockup demonstriert. Außerdem wurden schon ein paar Funktionen zur verfügung gestellt, um ein potentielles Update per JUpdate zu prüfen.

Projektdokumentation

Zu Beginn des Projekts musste die Organisationsstruktur und der Entwicklungsprozess genauer definiert werden. Wir haben uns dabei für die Verwendung eines Kanban-Boards entschieden, in dem wir einzelne Prozesse verwalten und Informationen sammeln. Zum Einsatz kam dabei das Tool Trello. In Trello haben wir Spalten für die Entwicklungsstadien angelegt.

Summary of Changes

Based on https://github.com/joomla/joomla-cms/pull/16494 we continued developing the Pre-Update Checker for Joomla! 3.9. Like the Joomla! installation process, the com_joomlaupdate component now checks PHP options, settings and extension compatibility.

Test Instructions

These instructions are based on a Joomla 3.9 installation. Change values accordingly. The path / represents the Joomla! installation directory.

Test Joomla! Pre-Update Check

1. Create file list.xml at /

<extensionset>
	<extension element="joomla" type="file" version="4.0.0" targetplatformversion="3.9" detailsurl="http://localhost/extension_sts.xml" />
</extensionset>

2. Create file extension_sts.xml at /

<updates>
	<update>
		<name>Joomla! 3.7</name>
		<description>Joomla! 3.7 CMS</description>
		<element>joomla</element>
		<type>file</type>
		<version>4.0.0</version>
		<infourl title="Joomla!">https://www.joomla.org/announcements/release-news/5711-joomla-3-7-5-release.html</infourl>
		<downloads>
			<downloadurl type="full" format="zip">https://downloads.joomla.org/cms/joomla3/3-7-5/Joomla_3.7.5-Stable-Update_Package.zip</downloadurl>
		</downloads>
		<tags>
			<tag>stable</tag>
		</tags>
		<maintainer>Joomla! PLT</maintainer>
		<maintainerurl>https://www.joomla.org</maintainerurl>
		<section>STS</section>
		<targetplatform name="joomla" version="3.[23456789]" />
		<php_minimum>5.3.10</php_minimum>
	</update>
</updates>

3. Components -> Joomla! Update -> Options

Custom URL: localhost/list.xml

4. Save & Close

There should be a fake update to Joomla 4.

5. Change your PHP or webserver settings to trigger a failed compatibility check.

display_errors = On

file_uploads = Off

output_buffering = On

6. Run chmod -w configuration.php to disable write on the configuration file.

7. Visit the update site and check the compatibilty results.

Test Extension Compatibility

1. Install some extensions, which are not compatible with your hacked Joomla! target version (4.0.0).

2. Change the XML URL of any incompatible extension in the table #__update_sites in the column location to an own custom XML file.

3. Put the following contents in your XML update file. Replace version 1.5 with the actual installed version of your selected extension.

<updates>
	<update>
		<version>1.5</version>
		<downloads>
			<downloadurl type="full" format="zip">https://fakeurl</downloadurl>
		</downloads>
		<targetplatform name="joomla" version="4.0.0" />
	</update>
</updates>

4. Check the extensions compatiblity result.

5. Change the column manifest_cache in the table #__extensions of the hacked extension by changing the field version to an older one. This should trigger a compatiblilty, but based on a newer version.

Test Database compatibility

Add your current database type (e.g. mysqli) to $unsupportedDatabaseTypes in function isDatabaseTypeSupported() in file ./administrator/components/com_joomlaupdate/models/default.php

Expected result

You should see a full report on compatibility of the update. PHP options, settings and extensions should be marked accordingly.

Fehler beim Erstellen des Vorschaubildes: Datei fehlt
Pre-Update Checker: PHP Options und Settings
Fehler beim Erstellen des Vorschaubildes: Datei fehlt
Pre-Update Checker: Extension Kompatibilität

Actual result

No results, since this is a new feature.

Documentation Changes Required

The following page should be updated with recent screenshots and descriptions. https://docs.joomla.org/J3.x:Updating_from_an_existing_version

Implementierungsdetails

Die ersten beiden Tabellen "Pre-Update Check" und "Recommended settings" laden analog zur Installationsroutine PHP-Einstellungen, vorhandene Module und Möglichkeiten, welche die aktuell laufende PHP Version bietet. Die Prüfungen und empfohlenen Werte sind hartkodiert und werden nicht durch eine XML-Datei definiert.

Die Tabelle "3rd Party Extensions Pre-Update Check" lädt die Kompatibilität asynchron per Javascript. Dabei wird ein GET-Request an den com_joomlaupdate Controller gesendet, welcher die aktuelle Extension-ID und die Ziel-Joomla-Version enthält. Nun wird die Kompatibilität serverseitig geprüft, indem die hinterlegten XML-Dateien der Extensions geladen und eine passende Version per Regex gesucht. Dies wird durch die Klasse JUpdate übernommen. Dadurch wird ein langsames Laden der Seite, aufgrund der serverseitigen URL-Requests, verhindert.

GET /administrator/index.php?option=com_joomlaupdate&task=update.fetchExtensionCompatibility&extension-id=10027&joomla-target-version=4

prüft, ob die Extension 10027 mit Joomla 4 kompatibel ist. Das Resultat wäre ein JSON-String mit dem Prüfresultat {state: 1}. Dabei steht state für

0: INCOMPATIBLE
1: COMPATIBLE
2: MISSING_COMPATIBILITY_TAG
3: SERVER_ERROR

Um die Liste aller 3rd-Party-Extension zu bekommen, wird ein SQL Select auf der Tabelle #__extensions ausgeführt und alle Zeilen selektiert, welche eine extension_id von >= 10000 haben. Diese wird durch einen Left-Join mit den Tabellen #__update_sites_extensions und #__update_sites verknüpft, um die Update-XML-URLs zu bekommen. Teilweise sind nur Sprachkonstanten als Extensiontitel hinterlegt (z.B. PLG_SYSTEM_AKEEBAUPDATECHECK_TITLE). Diese werden durch das manuelle Laden der entsprechenden Sprachen in korrekte Titel übersetzt.

Extensions, die zu einem Paket gehören, werden nicht angezeigt.

Spezialfälle

Unter bestimmten Umständen prüfen wir zusätzliche Optionen.

Joomla version >= 4:

  • Database Types (sqlsrv and sqlazure will cause "Your host doesn't support the minimum requirements for Joomla")

PHP version is < 7:

  • Magic Quotes (+ Runtime)
  • Register Globals
  • Safe Mode

Issues

  1. Laut Datenbankstruktur wäre es möglich, mehrere Update XML-Dateien für eine Extension hinterlegen zu können.
    Diese tritt jedoch nur auf, wenn eine "HTTP"-URL durch eine "HTTPS"-URL ersetzt wird.
    Lösung: Nach Absprache mit Roland reicht es, die jeweils erste URL zu nutzen.
  2. Die Funktionen, welche die PHP Einstellungen prüft, sind Duplikate des Joomla! Installers.
    Lösung: Aufschieben für einen anderen PR.
  3. Die Funktionen, welche die Titel der Extensions aus den entsprechenden Sprachen lädt, ist ein Duplikat aus der com_installer Komponente.
    Lösung: Aufschieben für einen anderen PR.
  4. JUpdate liefert nur die neuste, kompatible Version. Es ist daher nicht möglich zu Prüfen, ob die installierte Version auch kompatibel ist.
    Lösung: Wir zeigen an, dass die Extension ein Update benötigen könnte.

Nach dem PR

  1. Es wurden einige Codestyle Probleme aufgezeigt, die durch uns korrigiert wurden.
  2. Nach weiterer Evaluation wurden die oben beschriebenen Spezialfälle entwickelt.
  3. Wir haben den Pre-Update Checker in einen eigenen Tab verschoben.
  4. Der Branch wurde anschließend gemergt, ohne dass 2 Testangaben notwendig waren.

Gruppe 3

Das Team

Name GitHub-Account
Lukas Maximilian Kimpel eXsiLe95
Murat Saygili Murat75
Dennis Sehrt Dennissehrt
Lukas Schmitt Schmidie64

Repository

Aufgaben

1. Entfernen des FOF vom Joomla! Core

Joomla! bietet die Möglichkeit einer Zwei-Wege-Authentifizierung (Two-Factor-Authentication/TFA). Diese wurde bisher über ein Frame über dem eigentlichen Joomla! Framework realisiert, Frame on Frame (FOF) genannt.

Dieses Frame stellt eine Abhängigkeit dar, von der Joomla! in der neuen Version 4 Abstand nehmen will. Daher war es unsere Aufgabe, die [https://wiki.thm.de/Web_Programming_Weeks_SS16#Refactor_2FA_from_FOF_to_Joomla_core angefangene Arbeit der Vorjahresgruppe] fertigzustellen.

Leider wurde am ersten Tag unserer Entwicklung diese Aufgabe bereits von George Wilson gelöst. Daher bestand unsere Aufgabe, einen umfangreichen Test zu dem Issue zu erstellen.

2. Refaktorisierung der Kategorieansicht

Die Kategorieansicht von Joomla! birgt aktuell einige Probleme. Zwar werden die Kategorien in der Standardsortierung korrekt in einer Baumstruktur angezeigt, jedoch nicht bei anderer Sortierung. Außerdem werden immer alle Kategorien angezeigt, auch wenn nur Zugriff auf einige wenige Elemente besteht. Beim Filtern nach bestimmten Kategorien werden diese zwar eingerückt dargestellt, allerdings gibt es keine Information über den Zweig der Hierarchie. Folglich kann nicht bestimmt werden, welche Kategorie zu welchem Zweig gehört, wenn es mehrere Kategorien gleichen Namens gibt. Unsere Aufgabe lautete daher, eine sinnvolle Lösung zu finden, zu diskutieren und diese letztendlich umzusetzen.

Projektdokumentation

1. Entfernen des FOF vom Joomla! Core

Erstellen des Tests

Die Änderungen an Joomla! betreffen die Login Möglichkeiten und sind sicherheitsrelevant. Daher ist ein ausführlicher und umfassender Test mit allen möglichen Eventualitäten unabdingbar.

Daher haben wir uns Gedanken darüber gemacht, welche Möglichkeiten es beim Login gibt.

Testing instructions

Wie auch zu sehen im Issue:

Fehler beim Erstellen des Vorschaubildes: Datei fehlt
Login Error Message
  1. Fresh installation of Joomla! 4.0-dev
  2. Enable TFA in administrator
    1. Go to Extensions > Plugins
      1. Enable Two Factor Authentication - Google Authenticator
      2. Enable Two Factor Authentication - YubiKey
  3. Create users
    1. Go to Users > Manage
    2. Create a new user
    3. Edit the new user and enable Two Factor Authentication
      1. Go to Two Factor Authentication Tab
      2. Select Google Authenticator as Authentication Method
      3. Follow the on screen instructions to set up Google Authenticator
    4. Create a new user
    5. Edit the new user and enable Two Factor Authentication
      1. Got to Two Factor Authentication Tab
      2. Select YubiKey as Authentication Method
      3. Follow the on screen instructions to set up YubiKey Authenticator
  4. Go to frontend/site <yourinstallpath>/index.php
    1. Test without TFA
      1. Try to log in with superuser with wrong password
      2. Try to log in with superuser with additional secret key (is always wrong)
      3. Login with superuser without TFA
      4. Log out
      5. Go to `<youtinstallpath>/index.php/login`
      6. Try to log in with superuser with wrong password
      7. Try to log in with superuser with additional secret key (is always wrong)
      8. Login with superuser without TFA
      9. Log out
    2. Test with Google TFA
      1. Try to log in with Google TFA user with wrong password but no secret key
      2. Try to log in with Google TFA user with wrong password and wrong secret key
      3. Try to log in with Google TFA user with wrong password but correct secret key
      4. Try to log in with Google TFA user with correct password but no secret key
      5. Try to log in with Google TFA user with correct password but incorrect secret key
      6. Login with the user with Google TFA with the login box
      7. Log out
      8. Go to <youtinstallpath>/index.php/login
      9. Try to log in with Google TFA user with wrong password but no secret key
      10. Try to log in with Google TFA user with wrong password and wrong secret key
      11. Try to log in with Google TFA user with wrong password but correct secret key
      12. Try to log in with Google TFA user with correct password but no secret key
      13. Try to log in with Google TFA user with correct password but incorrect secret key
      14. Login with the user with Google TFA with the login box
      15. Log out
    3. Test with YubiKey
      1. Try to log in with YubiKey TFA user with wrong password but no secret key
      2. Try to log in with YubiKey TFA user with wrong password and wrong secret key
      3. Try to log in with YubiKey TFA user with wrong password but correct secret key
      4. Try to log in with YubiKey TFA user with correct password but no secret key
      5. Try to log in with YubiKey TFA user with correct password but incorrect secret key
      6. Login with the user with YubiKey TFA with the login box
      7. Log out
      8. Go to `<youtinstallpath>/index.php/login`
      9. Try to log in with YubiKey TFA user with wrong password but no secret key
      10. Try to log in with YubiKey TFA user with wrong password and wrong secret key
      11. Try to log in with YubiKey TFA user with wrong password but correct secret key
      12. Try to log in with YubiKey TFA user with correct password but no secret key
      13. Try to log in with YubiKey TFA user with correct password but incorrect secret key
      14. Login with the user with YubiKey TFA with the login box
      15. Log out
  5. Go to backend/administrator <yourinstallpath/administrator
    1. Test without TFA
      1. Try to log in with superuser with wrong password
      2. Try to log in with superuser with wrong password and additional secret key (is always wrong)
      3. Try to log in with superuser with correct password and additional secret key (is always wrong)
      4. Login with superuser without TFA
      5. Log out
    2. Test with Google TFA
      1. Try to log in with Google TFA user with wrong password but no secret key
      2. Try to log in with Google TFA user with wrong password and wrong secret key
      3. Try to log in with Google TFA user with wrong password but correct secret key
      4. Try to log in with Google TFA user with correct password but no secret key
      5. Try to log in with Google TFA user with correct password but incorrect secret key
      6. Login with the user with Google TFA with the login box
      7. Log out
    3. Test with YubiKey TFA
      1. Try to log in with YubiKey TFA user with wrong password but no secret key
      2. Try to log in with YubiKey TFA user with wrong password and wrong secret key
      3. Try to log in with YubiKey TFA user with wrong password but correct secret key
      4. Try to log in with YubiKey TFA user with correct password but no secret key
      5. Try to log in with YubiKey TFA user with correct password but incorrect secret key
      6. Login with the user with YubiKey TFA with the login box
      7. Log out
Gefundene Fehler

Während des Tests sind uns einige Fehler im Originalzustand von Joomla! 4 aufgefallen. Versucht man sich im Administrator-Bereich Joomla!s anzumelden mit einem Benutzer, der keine TFA aktiviert hat, wird dennoch das Feld "Secret Key" verlangt.

Da dies jedoch nicht Issue-related ist (es also nicht mit dieser Aufgabe zu tun hatte), haben wir hierfür ein eigenes Issue und einen eigenen Pull-Request erstellt.

Die Arbeit von George Wilson konnten wir mit unserem Test als einwandfrei und erfolgreich getestet markieren, sodass dieser Pull-Request schon am Folgetag der Entwicklung in den laufenden Entwicklungsbranch von Joomla! 4 gemerged werden konnte. Auch unser Bugfix für das gefundene Problem wurde in den Entwicklungsbranch gemerged.

Entfernen des `required` Status
Fehler beim Erstellen des Vorschaubildes: Datei fehlt
Entfernen des `required` Status

In der Datei administrator/modules/mod_login/tmpl/default.php wurden die HTML Statements required und aria-required="true" entfernt. Hierdurch kann eine Abfrage ohne eingegebenes Secret Key durchgeführt werden. Das Secret Key Field wird dennoch überprüft, wenn die Zweiwege-Authentifizierung für den Benutzer aktiviert und eingerichtet ist.

2. Refaktorisierung der Kategorieansicht

Fehler beim Erstellen des Vorschaubildes: Datei fehlt
SQL Fehlermeldung
Ungültiges SQL verhindert das Speichern von Modulen für Administrator

Bei dem Erstellen eigener Module im Backend für den Administratorbereich haben wir einen Fehler gefunden, der das Speichern eines Moduls ohne `content` Feld nicht zuließ. Dies war zum Beispiel der Fall, wenn man ein Administrator Menü speichern wollte. Generell tritt der Fehler jedoch nicht bei allen Installationen auf, da gewisse MySQL Datenbankserver mit der falschen SQL Syntax dennoch umgehen konnten.

Unser Bugfix wurde in dem Pull Request #17752 angelegt und dokumentiert. Da dieser Pull Request für Joomla! 4 gilt und eine Überarbeitung des Datenbankschemas bevorsteht, steht noch nicht fest, ob der Pull Request (vorrübergehend) gemerged werden wird.

Außerdem haben wir nachträglich einen Pull Request für Joomla! 3 erstellt, um auch dort das fehlerhafte SQL zu entfernen.

Fehler beim Erstellen des Vorschaubildes: Datei fehlt
Anpassungen am SQL Code
Summary of Changes

Edited content field on table #__modules to be NULL by default.

Testing Instructions
  1. Get a fresh installation of Joomla! 4
  2. Go to Extensions > Modules
  3. Create a new module for Administrator (e.g. Administrator Menu)
  4. Give it a name and try to save it
Expected result

Module gets saved and can be added to a custom menu

After the Fix

after I got the said error (see above), I tried to figure out why there is no value in the SQL request for content I figured out that the type TEXT doesn't allow anything else but NULL as a default value.

Related Issues

Remove FOF From Joomla Core

Overlapping header / add margin-bottom to header

Removed required state for Secret Key field

Invalid SQL prevents saving of modules for Administrator

Categories view discussion

Forked Joomla Repository