Link-Feld: CSS-Klasse hinzufügen mittels Fluid

Sinn und Zweck: aus dem Link-Feld des Backends (in dem neben der Zielseite auch target-, CSS-Klasse und title-Attribut stehen kann) den Wert an Link-Viewhelper übergeben, dabei aber eine zusäztliche CSS-Klasse anhängen.

<vhs:if.string.isNumeric value="{field.link}">
  <f:then>
    <dce:typolink parameter="{field.link} - link" />
  </f:then>
  <f:else>
    <dce:typolink parameter="{vhs:format.regularExpression(pattern: '/^([^ ]+)\s+([^ ]+)((\s+-)|(\s+[^ ]*)) (.+)/Ui', replacement: '\1 \2 \"link\5\" \6', subject: '{field.link}')}" />
  </f:else>
</vhs:if.string.isNumeric>

Update 2014-04-07

Nette Idee, aber die Tücken liegen wie so oft im Detail. Die Kombinationsmöglichkeiten aus internem Link/externem Link, Linkziel (target) gegeben/nicht-gegeben, Linktitle gegeben/nicht-gegeben und CSS-Klasse gegeben/nicht-gegeben ergeben, sind derart groß, dass der reguläre Ausdruck von oben doch nicht immer greift (z.B. falls nur eine externe URL gegeben ist).

Entwicklungshilfe seit TYPO3 6.0

TYPO3 hat zwei kleine Gemeinheiten in sich, die einem manchmal das Leben erschweren:

  • zum einen den Cache (bzw. inzwischen die Caches),
  • zum anderen seine Verschwiegenheit über genauere Fehlerursachen (in produktiven Umgebungen).

Ersteres lässt sich v.a. während der Extbase-basierten Entwicklung (neben altbekannten TypoScript-Einstellungen) über eine Änderung am CachingFramework lösen. Denn nach Änderungen im Model bzw. in den Annotationen im Controller oder Repository entstehen  Fehlermeldungen oftmals durch veraltete Einträge im Reflection Cache von Extbase, welcher Modelproperties und Annotationen speichert.

Die Verschwiegenheit bei Fehlern lässt sich mit einer Reihe von Schaltern beheben, sodass TYPO3 sehr auskunftfreudig wird.

Weiterlesen

tt_news: optionSplit vs. noTrimWrap – ungünstige Default-Einstellungen

Die Extension tt_news hat in Version 3.0 eine schöne Neuerung mitgebracht: optionSplit-Unterstützung für viele Marker. Über genau diese Neuerung kann man jedoch auch stolpern. Im aktuellen Fall wunderte ich mich über das Resultat des Markers ###NEWS_AUTHOR### in der LIST-Ansicht.

Von:Julian

So zusammengeklebt sieht das nicht schön aus. Da gibt’s doch bestimmt einen stdWrap, mit dem man da ein Leerzeichen dazwischen bekommt. Und in der Tat, es gibt den preAuthor_stdWrap, der auf das „Von:“ angewendet wird. Zu meiner Überraschung hatte dieser schon einen passenden Default-Wert im TypoScript:

plugin.tt_news.displayList.preAuthor_stdWrap.noTrimWrap = || |

Dann hilft wohl nur eine genauere Analyse…
Weiterlesen

Menü der Unterseiten – ggf. der Elternseite, falls Shortcut

Ein Menü aus Unterseiten lässt sich ganz leicht in TypoScript bauen. Hierzu einfach ein HMENU hernehmen, und via special = directory die passenden Einstellungen vornehmen:

20 = HMENU
20 {
    // Menü der Unterseiten der aktuellen Seite
    special = directory
    special.value.data = TSFE : id
    1 = TMENU
    1 {
        NO {
            // ...
        }
    }
}

Problem

Nun trifft man gelegentlich aber auf Seitenstrukturen, bei denen Shortcuts in Verwendung sind, d.h. die aktuelle Seite eigentlich eine Menü der Unterseiten der Elternseite anzeigen sollte.

Bildschirmfoto 2014-03-11 um 10.07.21Hier wäre „Seite 2“ der Shortcut auf die erste Unterseite, und wir würden uns wünschen, dass folglich auf „Seite 2.1“ ein Menü der Unterseiten von „Seite 2“ angezeigt wird.

Lösung

Die Lösung ist hier mittels override auch recht fix erreicht:

20 = HMENU
20 {
    // Menü der Unterseiten der aktuellen Seite (unabhaengig vom Treelevel)
    special = directory
    special.value.data = TSFE : id
    // Falls aktuelle Seite aus einem Shortcut der Parent-Site hervorging, dann Unterseiten dieser anzeigen
    special.value.override {
        cObject = CONTENT
        cObject {
            table = pages
            select {
                pidInList >
                pidInList.data = leveluid : -3
                // @todo: siehe "Update"
                //where = doktype = 4 AND ((shortcut_mode=0 AND shortcut = ###currentPage###) OR shortcut_mode=1)                 
                where = doktype = 4 AND (shortcut_mode=0 AND shortcut = ###currentPage###)                 
                markers {
                    currentPage.data = TSFE : id
                }
            }
            renderObj = COA
            renderObj {
                10 = TEXT
                10.field = uid
            }
        }
    }
    1 = TMENU
    1 {
        NO = 1
        NO {
           // ...
        }
    }
}

Über eine Datenbankabfrage suchen wir Seiten, die einerseits Elternseite unserer aktuellen Seite sind, zugleich aber auch von Typ „Shortcut“ (doktype=4) sind und als Ziel unsere aktuelle Seiten haben bzw. den Modus „First subpage of current page“ haben.

TYPO3 4.5-Spezialität:

Da uidInList erst aber 4.6 stdWrap-Eigenschaften hat, kann der Wert nicht dynamisch gesetzt werden, und kommt bei 4.5 der Defaultwert von pidInList = this in die Quere. Es muss also statt uidInList die Seiten-ID der Eltern-Eltern-Seite in die pidInList-Bedingung geschrieben werden. Diese ID erhält man am einfachsten aus der Rootline.

Update

Die Logik passt noch nicht für Modus „First subpage of current page“, falls wir uns nicht auf dieser ersten Unterseite befinden, sondern auf anderer Unterseite.
Hat jemand eine Idee, wie das mit berücksichtigt werden kann?

Zufälliges Bild aus Resourcen

Im TYPO3-Forum kam letzten die Frage nach einem zufälligem Bild aus dem Resourcen-Feld (media) einer bestimmten, festen Seite auf. Die Frage interessierte mich, gerade weils ich hier durch die Einführung von FAL Änderungen ergaben und viele Snippets aus dem Netz nicht (mehr) funktionieren.

Aus dem Ansatz des Threadautors entwickelt, ergab sich schließlich folgende Lösung:

temp.backImg = FILES
temp.backImg {
    files.cObject = CONTENT
    files.cObject {
        table = sys_file_reference
        select {
            // Page-ID der Seite, aus der Bilder entnommen werden sollen
            pidInList = 3
            where = tablenames='pages' AND fieldname='media'
            selectFields = uid_local
            orderBy = rand()
            max = 1
        }
        renderObj = TEXT
        renderObj.field = uid_local
    }
    renderObj = IMAGE
    renderObj {
        file.import.data = file:current:publicUrl
    }
}

Zunächst sieht das ganze etwas kompliziert aus. Es hat aber den Vorteil, dass mit diesem Ansatz wirklich sehr variable Lösungen möglich werden. So könnte statt auf die pages-Tabelle auch auf News-Datensätze, Produktdaten, Inhaltselemente odgl. zugegriffen werden, da die volle Breite der SQL-Abfrage bereitsteht.

Der einfachere Weg

Wenn man sich nicht zu sehr in Code schon reingedacht hat, und den Wald vor lauter Bäumen nicht mehr sieht, dann fällt einem sogar die einfachere Lösung ein (die letztens im Forum auch gesucht wurde):

temp.backImg = IMAGE
temp.backImg.file {
    import.data = levelmedia: 0
    import.listNum = rand
    treatIdAsReference = 1
}

Zu beachten ist hierbei aber, dass das TypoScript-Objekt gecacht wird, d.h. der „Zufall“ auch gecacht wird. Wenn dies unerwünscht ist, dann müsste ein *_INT-Objekt außenherum.
Alternative wäre, mehrere Bilder in HTML einzubetten und via JS (und damit am Cache vorbei) den Zufall zu handhaben (d.h. Bilder ein-/auszublenden).

Links

TYPO3 6.x – Mails mit Anhängen

Das prinzipielle Vorgehen zum Versand von Mails über die „neue“ Mail-API von TYPO3 hatte Jigal dereinst schön im Artikel „New mail API for the core“ erklärt.

Etwas tricky wird es in TYPO3 6.x durch die Einführung der Namespaces. Denn TYPO3 erweitert nur einige Klasse des Swiftmailers, nicht aber alle. Somit bewegen sich viele Aufrufe innerhalb der TYPO3-Namespaces (z.B. TYPO3\CMS\Core\Mail), während andere Klassen- und Methodenaufrufe kläglich scheitern, weil die Swiftmailer-Klassen nicht gefunden werden (z.B. Swift_Attachment::fromPath($path)).

Lösung

Die Lösung des Problems ist eigentlich ganz trivial: aus der eigenen (namespace-behafteten) Extension einfach wieder in den globalen Namespace wechseln, indem vor alle Swiftmailer-eigenen Klassen ein Backslash gesetzt wird.

$mail = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
$mail->setFrom(array($senderEmail => $senderName));
$mail->setTo(array($receiverEmail => $receiverName));
$mail->setSubject($subject);
$mail->setBody($body, 'text/html');

$attachment = \Swift_Attachment::fromPath($imgPath, 'image/jpeg');
$mail->attach($attachment);

$mail->send();

Quellen

  1. buzz.typo3.org: New mail API for the core (als PDF-Backup)
  2. [FLOW3-general] Swift Mailer Attachment (als PDF-Backup)

Externe URLs in Menüs

Seiten vom Typ „External URL“ werden von TYPO3 in Menüs standardmäßig nur als interne Links generiert, die dann via Redirect auf die externe Seite verweisen.

Manchmal möchte man aber die Seiten gleich direkt verlinkt haben. Christopher hat dazu ein Snippet online gestellt. Dort wird aber nicht das zwischenzeitlich eingeführte Feld „Protocol“ bzw. „urltype“ berücksichtigt. Daher habe ich das Snippet etwas gepimpt :-)

lib.extUrlMenu = HMENU
lib.extUrlMenu {
    1 = TMENU
    1 {
        wrap = <ul id="externalLinks"> | </ul>

        NO = 1
        NO {
            wrapItemAndSub = <li> | </li>

            doNotLinkIt = 1
            stdWrap.cObject = CASE
            stdWrap.cObject {
                key.field = doktype
                default = TEXT
                default {
                    field = title
                    typolink {
                        parameter.data = field:uid
                    }
                }

                3 < .default
                3 {
                    stdWrap.htmlSpecialChars = 1
                    typolink {
                        parameter {
                            data >
                            cObject = CASE
                            cObject.key.field = urltype
                            cObject.default = TEXT
                            cObject.default.value = http://
                            cObject.1 = TEXT
                            cObject.1.value = http://
                            cObject.4 = TEXT
                            cObject.4.value = https://
                            cObject.2 = TEXT
                            cObject.2.value = ftp://
                            cObject.3 = TEXT
                            cObject.3.value = mailto:
                            cObject.stdWrap.dataWrap = |{field:url}
                        }
                    }
                }
            }
        }
    }
}

Quellen

  1. TMENU with external links