Beiträge der Kategorie TYPO3 v8

TYPO3 E-Mail-Adressen in JsonView verschlüsseln

Ich leistete Support bei einem Projekt (d.h. ich hatte es nicht selbst programmiert) und hatte mit einer Ansprechpartner-Liste zu tun, die mit Ajax (JSON-Format) nachgeladen wurde. Bei dieser Site sollte die TYPO3 E-Mail-Adressverschlüsselung aktiviert werden. Für die Ansprechpartner-Liste war ein Controller geschrieben, der die Ansprechparter aus dem Repository holte und ins JSON-Format umwandelte, ein Fluid-Template wurde nicht benutzt. Als ich die E-Mail-Adressverschlüsselung aktiviert hatte (hier nur ein Beispiel), griff sie an der Stelle nicht und die E-Mail-Adressen wurden unverschlüsselt ausgeliefert.

config.spamProtectEmailAddresses = 2
config.spamProtectEmailAddresses_atSubst = (at)

Da ich nicht viel umbauen wollte, hatte ich die E-Mail-Adresserschlüsselung in den Controller implementiert. Wenn man sich den Fluid EmailViewHelper naschaut, dann ist die entscheidende Zeile eigentlich folgende:

list($linkHref, $linkText) = $GLOBALS['TSFE']->cObj->getMailTo($email, '');

Da ich letztens über die JsonView gelesen hatte, ließ mir die Aufgabe keine Ruhe. Wie könnte man die JsonView verwenden und dabei die in TYPO3 eingestellte E-Mail-Adressverschlüsselung beibehalten?

Ich habe eine kleine Demo-Extension, in der ich Personen-Datensätze verwalte mit Name, Email und noch ein paar weiteren Feldern. Im AjaxController aktiviere ich die JsonView und konfiguriere sie. In der Konfiguration gebe ich 2 Felder an, die nicht in der Datenbank existieren. Dann füge ich dem Model getter-Funktionen für diese zwei Felder hinzu.

Controller

class AjaxController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
 
    protected $defaultViewObjectName = JsonView::class;
 
    /**
     *
     */
    public function personListAction()
    {
        $jsonViewConfiguration = [
            'persons' => [
                '_descendAll' => [
                    '_exclude' => ['pid'],
                    '_only' => ['name', 'email', 'emailHref', 'emailText']
                ]
            ]
        ];
        $personRepository = $this->objectManager->get(PersonRepository::class);
        $persons = $personRepository->findAll();
        $this->view->setVariablesToRender(['persons']);
        $this->view->setConfiguration($jsonViewConfiguration);
        $this->view->assign('persons', $persons);
    }
}

Model

class Person extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
    [...]
    /**
     * @return string
     */
    public function getEmailHref()
    {
        list($linkHref, $linkText) = $GLOBALS['TSFE']->cObj->getMailTo($this->email, '');
        return $linkHref;
    }
 
    /**
     * @return string
     */
    public function getEmailText()
    {
        list($linkHref, $linkText) = $GLOBALS['TSFE']->cObj->getMailTo($this->email, '');
        return $linkText;
    }
}

JSON Output

[
{
"email": "bruce@wayne-enterprises.com",
"emailHref": "javascript:linkTo_UnCryptMailto('ocknvq,dtwegBycapg\\/gpvgtrtkugu0eqo');",
"emailText": "bruce(at)wayne-enterprises.com",
"name": "Bruce Wayne"
},
[...]

Wirklich glücklich bin ich mit dieser Lösung nicht. Ich habe das Gefühl, dass ich Darstellungslogik, die eigentlich in den View gehört, im Model unterbringe. Mir würde es besser gefallen, wenn man Prozessoren für Objekte definieren könnte. Leider gibt die Konfiguration des JsonView das im Moment nicht her.

Fluid f:comment-ViewHelper und Inline JavaScript

In Vorbereitung auf die TYPO3 Developer Prüfung schaue ich mir gerade vieles in TYPO3 genauer an. So wie im Moment die Standard Fluid-ViewHelper. Dabei bin ich beim f:comment ViewHelper hängen geblieben. Die Dokumentation beschreibt da einen Fall, denn ich so nicht reproduzieren konnte. Mein TYPO3 8.7.19 verhält sich so:

Inhalte gewrappt in f:comment werden nicht ausgegeben – weder im Quellcode, noch sichtbar.

<f:comment>
    <p>Wrapped in f:comment: Anzahl Einträge {data -> f:count()} </p>
</f:comment>

Inhalte gewrappt in CDATa werden ebenfalls nicht ausgegeben. Das ist der Dokumentation noch anders beschrieben.

<![CDATA[<p>Wrapped in CDATA: Anzahl Einträge {data -> f:count()} </p>]]>

Es gibt allerdings einen neuen ViewHelper f:format.cdata, der Inhalt bei der Ausgabe in CDATA wrappt. Eigentlich toll.

<f:format.cdata><p>Wrapped in f:format.cdata: Anzahl Einträge {data -> f:count()} </p></f:format.cdata>

Problem dabei ist, dass dann folgendes im Quellcode ausgegeben wird:

<![CDATA[<p>Wrapped in f:format.cdata: Anzahl Einträge 10 </p>]]>

Der Browser (in meinem Fall Chrome) stellt auf der Seite ]]> dar. Wünschenswert wäre, dass auf der Seite gar keine Ausgabe erfolgt. Ich habe mich noch nie ausführlich mit CDATA beschäftigt, weiß daher nicht, ob es an f:format.cdata oder meinem Browser liegt.

Und nun zum nächsten Problemchen: Inline JavaScript. Ich hatte etwas recherchiert und die Vorschläge, wie man Fluid vom Parsen von Inline-JavaScript abhält, beziehen sich alle auf Wrappen in CDATA. Was ja eben nicht funktioniert. Also f:format.cdata ViewHelper benutzen:

<script type="text/javascript">
    <f:format.cdata>
        function sayHello() {
            alert("hello world");
        }
        sayHello();
    </f:format.cdata>
</script>

Allerdings wirft der obige Code einen JavaScript-Fehler. Der Browser stört sich an dem < am Beginn von CDATA. Eine funktionierende Lösung sieht damit so aus:

<script type="text/javascript">
    //<f:format.cdata>
        function sayHello() {
            alert("hello world");
        }
        sayHello();
    //</f:format.cdata>
</script>

Gibt es denn eine Möglichkeit, einen Block auszugeben, den aber von Fluid nicht parsen zu lassen? Wofür könnte man es brauchen? Ich werde weiter schauen…