EXT:DCE – Upgrade to FAL-based files

Die Dynamic Content Elements (DCE) speichern Datei-Felder nun auch per FAL-Relation, also via File Abstraction Layer von TYPO3. Leider gibt es hierfür keinen Upgrade-Wizard. Man kann sich aber mit ein wenig PHP-Code passende SQL-Befehle generieren, um das Upgrade der Extension durchzuführen und die eigenen Content-Elemente entsprechend anzupassen.

Weiterlesen

Kategorien in EXT:solr nutzen

Schnell kommt man an den Punkt, an dem man Solr zusammen mit Kategorien bzw. Hierarchien als Facetten nutzen möchte. Die kurze Zusammenfassung meiner ersten Erfahrungen und Lösungswege:

Datenstruktur

Die zu kategorisierenden Datensätze müssen mittels System Kategorien (sys_category) gruppiert werden. Hierfür braucht gar nicht viel im TCA rumhantiert zu werden, da der TYPO3 Core das passende Hilfsmittel (ExtensionManagementUtility::makeCategorizable()) liefert .

Kategorien indizieren

Wie die Kategorie-Zuordnung mit indiziert wird, erklärt Steffen in seinem Blog-Beitrag „EXT:solr – Use categories as hierarchical facets„.
(Inzwischen ist „category“ als Feld in Solr vorhanden, sodass kein dynamisches Feld mehr nötig ist (category_stringM => category))

plugin.tx_solr.index {
  fieldProcessingInstructions {
    category = categoryUidToHierarchy
  }
  queue.MYTYPE.fields {
    category = SOLR_RELATION
    category {
      localField = categories
      foreignLabelField = uid
      multiValue = 1
    }
  }
}

Durch den Beitrag stößt man auch auf die Details der Implementierung, v.a. die Field Processors und den konkreten categoryUidToHierarchy (Classes/FieldProcessor/CategoryUidToHierarchy.php). Beim Blick in den Code wird klar, dass er nur mit Systemkategorien arbeitet.

Frontend-Ausgabe

Seit die Solr-Extension auf Fluidtemplates aufbaut, ist die Konfiguration der Facette vereinfacht (Früher war ein HMENU nötig):

plugin.tx_solr {
  search {
    faceting {
      facets {
        category {
          label = Category
          field = category
          type = hierarchy
        }
      }
    }
  }
}

Damit nutzt Solr automatisch das Hierarchy-Partial, und man bekommt einem Baum aus Kategorie-UIDs und der Anzahl der enthaltenen Datensätze angezeigt.

Und die Kategorie-Titel? Dafür braucht es einen kleinen Kniff mit TypoScript und eine kleine Änderung am Fluid-Template.

Via TypoScript legen wir uns ein cObject bereit, das uns den Titel einer System-Kategorie ausgibt:

lib.tx_solr.sys_category_title = RECORDS
lib.tx_solr.sys_category_title {
   source.current = 1
   tables = sys_category
   dontCheckPid = 1
   conf.sys_category = TEXT
   conf.sys_category.field = title
   conf.sys_category.htmlSpecialChars = 1
}

Im Hierarchy-Partial ersetzen wir in der Section ‚hierarchyTree‘ das {childNode.label} gegen:

<f:cObject typoscriptObjectPath="lib.tx_solr.sys_category_title">{childNode.label}</f:cObject>

 

Fertig!

 

Links

(Artikel basiert auf TYPO3 8.7.16 und EXT:solr 8.0.3)

Solr in TYPO3: alte Datensätze ausschließen

Ziel: alte Datensätze aus den Trefferlisten verbannen. Wen interessieren uralte News oder Schulungstermine, die bereits vorbei sind? Solr berücksichtigt in der Score-Berechnung zwar das Alter, aber dennoch war die Ergebnisliste mit zu vielen veralteten Treffern überfrachtet.

Lösungsansatz

Relativ einfach lässt sich die Index-Queue der TYPO3-Solr-Extension konfigurieren. Über die additionalWhereClause einfach eine Bedingung setzten, dass das Erstellungsdatum von News-Meldungen innerhalb der letzten 1,5 Jahre liegen muss:

plugin.tx_solr.index.queue {
  pressAnnouncements {
    table = tt_news
    additionalWhereClause = tstamp > UNIX_TIMESTAMP(date_sub(now(), interval 18 month))
  }
}

Prima, wir sind fertig – dachte ich auch. Bald zeigte sich nämlich, dass die Bedingung irgendwie nicht zum gewünschten Ergebnis führte, sondern uralte Meldungen weiterhin gefunden wurden.

So funktioniert das nicht!

Weiterlesen

Direct Mail und gemischte Protokolle (HTTP und HTTPS)

Wenn Direct Mail plötzlich falsche Inhalte verschickt – aber wir haben nix gemacht…also, eigentlich nix. Vor einigen Tagen wurde für eine TYPO3-Instanz mit mehreren Seitenbäumen und Domains das Protokoll konsequent auf HTTPS umgestellt und eine entsprechende RewriteRule hinterlegt. Alles prima – bis der nächste Newsletter versendet werden sollte: der hatte statt seines Inhaltes die Startseite als Inhalt :-\

In der Erinnerung „Wir haben da doch letztens…“, haben wir die RewriteRule einmal deaktiviert – und siehe da, der Newsletter lief wieder. Was aber läuft mit Umschreibung auf HTTPS schief?

Weiterlesen

Indexed Search: Seitentitel indizieren

Relativ einfach lässt sich den von TYPO3 generierte Seitentitel für die Ausgabe im Frontend wegnehmen und via headerData mit einem beliebigen TypoScript-Objekt befüllen. Leider ignoriert die Indexed Search dies und greift stattdessen auf eine interne (und via TS unzugängliche) Variable zurück. Chris (SwiftLizard) hat schon vor laaaanger Zeit das Problem bemerkt und auch einen Lösungsweg gefunden.

Danke, mir hat das tiefes Suchen im Core erspart :-)

Forcing indexed search to display the title you want.
(als PDF-Backup, Extension als Backup)

EXT:comments: Labels via TypoScript

Die Extension „comments“ lässt sich sehr schnell integrieren udn sehr gut für eigene Anwendungsfälle konfigurieren. Einzige Ausnahme: man möchte Sprachlabels ändern, was normalerweise via TypoScript möglich ist:

plugin.tx_comments_pi1 {
    _LOCAL_LANG {
        de {
            pi1_template.add_comment = Schreiben Sie einen Kommentar
        }
   }
}

Leider zeigt das (in Version 1.7.1) keinerlei Wirkung :-(

Ursachenforschung

Eine Ausgabe des $LOCAL_LANG-Arrays, welches via \TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_loadLL() geladen wird, zeigt bereits, dass das gesetzte neue Label überhabt nicht ausgelesen wird.

Die main()-Methode der Extension bekommt jedoch mittels $conf die TS-Konfiguration übergeben. Folglich muss der Fehler irgendwo dazwischen liegen. Dazwischen gibt es aber nur einen Aufruf: $this->fixLL();
Dieser Aufruf ist (laut phpdoc-Kommentar) ein Workaround für einen Bug #7154. Der enthaltene Link führt inzwischen leider ins Leere… Der Workaround wurde im Jahr 2008 in die Extension eingebaut. Ob er überhaupt noch nötig ist, wurde nicht weiter geprüft.
Die fixLL()-Methode durchläuft via foreach das Sprach-Array aus der TS-Konfiguration und ruft die interne Methode fixLL_internal() auf. Im PHP-Code fällt dort schnell etwas auf:

    /**
     * Helper function for fixLL. Called recursively.
     *
     * @param    array        $LL    Current array
     * @param    array        $ll    Result array
     * @param    string        $prefix    Prefix
     * @return    void
     */
    function fixLL_internal($LL, $ll, $prefix = '') {
        while (list($key, $val) = each($LL)) {
            if (is_array($val))    {
                $this->fixLL_internal($val, $ll, $prefix . $key);
            } else {
                $ll[$prefix.$key] = $val;
            }
        }
    }

 

Die Methode gibt nichts zurück (@return void) und verändert keine Klassenvariablen. Wie also soll hier etwas bearbeitetes die Methode verlassen? Und warum ist $ll als „Result array“ kommentiert, wenn es doch nirgends als Ergebnis ankommt?

Lösung

Die Lösung des Problem ist das Ergänzen eines „&“ in der Methodendeklaration:

    function fixLL_internal($LL, &$ll, $prefix = '')

 

Und wenn man dann seine Debugging-Session beendet hat, findet man auch den passenden Bugtracker-Eintrag – samt Patch :-(

 

Links

Neueste Meldung als Default in tt_news-SingleView

Ruft man die Detailseite des tt_news-Plugins ohne gültige News-ID auf, so erhält man die nur wenig interessante Information, dass eben keine ID übergeben wurde. Oftmals schöner bzw. gewünscht wird hier aber stattdessen eine Default-Inhalt – z.B. die aktuellste Meldung.

Mit ein wenig TypoScript ist das schnell zusammengebaut

plugin.tt_news.noNewsIdMsg_stdWrap.override.if.isFalse.data = GPvar:tx_ttnews|tt_news
plugin.tt_news.noNewsIdMsg_stdWrap.override.cObject = CONTENT
plugin.tt_news.noNewsIdMsg_stdWrap.override.cObject {
  table = tt_news
  select {
    // Seiten-ID der tt_news-Artikel
    pidInList = 8
    orderBy = datetimedesc
    max = 1
  }
}