Fluid / Extbase

Configuration RealURL pour une extension développée sous Extbase

Publié le

Voici une configuration RealURL pour une extension que vous auriez développé sous Extbase. On admet ici que deux paramètres sont passés :

  • tx_monextension_nomplugin[controller]
  • tx_monextension_nomplugin[action]

A adapter en fonction du nom du contrôleur et de vos actions.

‘fixedPostVars’ => array(
    ‘_DEFAULT’ => array (
        array(
            ‘GETvar’ => ‘tx_monextension_nomplugin[controller]’,
            ‘valueMap’ => array(
                ‘article’ => ‘Acticle’,
            ),
            ‘noMatch’ => ‘bypass’,
                ),
        array(
            ‘GETvar’ => ‘tx_monextension_nomplugin[action]’,
            ‘valueMap’ => array(
                ‘list’ => ‘list’,
                ‘new’ => ‘new’,
                ‘create’ => ‘create’,
                ‘edit’ => ‘edit’,
                ‘update’ => ‘update’,
                ‘delete’ => ‘delete’,
                ),
            ‘noMatch’ => ‘bypass’,
        ),
    ),
),

Publicités

FLOW3 / Extbase – Vérification du paramètre __hmac dans les formulaires

Publié le Mis à jour le

Si vous travailler sous Extbase, vous savez certainement que les champs de vos formulaires sont mappées sur les données de vos modèles. Par exemple, si je veux ajouter un article sur mon blog, je vais devoir compléter les champs suivants :
– Titre
– Catégorie(s)
– Introduction
– Texte

Ces champs existent dans ma table « posts » (title / category / short … pour simplifier les noms) mais c’est le modèle qui est chargé de décrire chaque champ, le format attendu et propose les différentes méthodes d’accès à ces valeurs. D’ailleurs, si vous décortiquez une extension créée avec Extbase, vous noterez que chaque entité ou objet à son propre fichier de déclaration… C’est le modèle.

Vous pouvez ainsi effectuer des opérations de mise à jour, d’édition ou de suppression de données très simplement ! Le contrôleur vous renverra éventuellement des erreurs après consultation du modèle.

C’est alors qu’est apparu un problème de sécurité dans les formulaires généré sous FLOW3 et Extbase. En effet, un utilisateur mal intentionné pourrait modifier un formulaire et contourner ainsi le modèle de chaque objet.

La solution qui a été trouvée, est de vérifier que le formulaire n’a pas été modifié entre l’affichage et le renvoi des données en GET ou POST, sinon, c’est considéré comme une attaque. Et comment ?

En fait, le framework collecte une liste de champs qui peuvent être envoyés depuis un formulaire. Cette liste est protégée par une une clé privée et un hash. Pour informations, un hash est une sorte de clé calculée à partir de données et permet d’accéder rapidement à ces dernières. La liste est le hash de la liste sont stockés dans un paramètre __hmac dans le formulaire et sur le serveur. Si le paramètre __hmac n’est pas valide, une exception est envoyée.

Personnellement, il m’arrive de créer des formulaires en Typoscript pour interroger un contrôleur hors de son contexte afin de me renvoyer une liste d’enregistrement. La conception d’une formulaire en Typoscript est aisée et plus rapide. En revanche, sans paramètre __hmac, une exception s’affiche lors de l’envoi du formulaire. Comment faire ?

J’ai trouvé une solution simple sur le Wiki suivant : http://wiki.typo3.org/User:Layne_obserdia/Extbase

Ajoutez @dontverifyrequesthash dans les annotations qui précèdent le contrôleur indexAction par exemple.

Créer son propre ViewHelper avec Fluid

Publié le

Aujourd’hui, je me suis penché sur la création de formulaires avec Fluid. Les formulaires sont bien pratiques comme vous le savez, puisqu’il permettent aux internautes d’intéragir avec une application. Fluid offre une quantité importante de ViewHelpers (ou aides de vue) pour générer le code HTML souhaité.

Pour la création de formulaires, les ViewHelpers se situent dans un sous dossier « Form » (Classes/ViewHelpers/Form). Chaque fichier situé dans ce dossier, permet de créer un type d’élément (ou champ) de formulaire : bouton radio, menu déroulant, champ de type textarea, bouton submit, etc.

Prenons l’exemple d’un champ de sélection :

<f:form.select name= »region » options= »{1: ‘Alsace’, 2: ‘Aquitaine’, 3:’Auvergne’} »  />

Il s’agit ici d’un exemple classique. On indique des couples valeur/titre, comme dans un tableau associatif en javascript. Si l’on souhaite injecter des valeurs provenant directement de la base de données, il faudra interroger le repository du modèle concerné avec la méthode findAll() par exemple ; dans ce cas là, ce n’est pas un tableau que l’on passe mais un objet.

Dans le contrôleur :
$regions = $this->regionRepository->findAll();
$this->view->assign(‘regions’, $regions);

Dans un gabarit Fluid :
<f:form.select name= »region » options= »{regions} » optionValueField= »uid » optionLabelField= »title » />

Notez que l’on spécifie ici les paramètres optionValueField et optionLabelField pour indiquer respectivement le champ utilisé pour la valeur de chaque option et l’intitulé. C’est obligatoire pour éviter d’avoir à la place un label composé du nom du modèle et de l’uid, ce qui ne voudrait pas dire grand chose.

Ainsi, on aurait donc le code suivant généré dans le navigateur :

<select name= »tx_monextension_nomplugin[region] »>
<option value= »1″>Alsace</option>
<option value= »2″>Aquitaine</option>
<option value= »3″>Auvergne</option>
etc…
</select>

Ce qu’il nous manque tout de même, c’est une option vide ou personnalisée dans notre menu de sélection pour  inviter l’utilisateur à faire un choix dans le menu déroulant. Or, si l’on regarde le ViewHelper « Tx_Fluid_ViewHelpers_Form_SelectViewHelper », rien n’indique la possibilité d’ajouter une option personnalisée  avant la liste.

J’ai vu une « feature request » à ce sujet sur Forge. Ca serait bien utile, non ?
Oui et non. En fait, le problème peut-être contourné très facilement et proprement !

Nous allons faire une sorte de « Xclass ». Alors, ce genre de manipulation ici est plutôt recommandé dans Fluid, contrairement aux extensions TYPO3 où il y a toujours un risque ; on recommande d’ailleurs l’exploitation de hooks mais je m’égare… revenons à nos moutons. Bref, la création de ViewHelpers est encouragée et dans notre cas, c’est indispensable.

Sachez que l’implémentation est aisée. Nous allons recopier la structure des dossiers du ViewHelper « Tx_Fluid_ViewHelpers_Form_SelectViewHelper » dans notre extension.

Nous avons donc :
mon_extension/Classes/ViewHelpers/Form/SelectViewHelper.php
Dans ce fichier, nous allons créer une classe étendue de Tx_Fluid_ViewHelpers_Form_SelectViewHelper. Elle portera le nom de notre extension : Tx_MonExtension_ViewHelpers_Form_SelectViewHelper. La notation UpperCamelCase doit être respectée. Comme vous le voyez, le nom indique le chemin vers le fichier.

Nous allons ensuite modifier la fonction initializeArguments pour ajouter notre argument personnalisé. En effet, nous allons indiquer à Fluid la valeur que nous souhaitons ajouter à notre liste d’options. Fluid doit donc être au courant du paramètre attendu et de son format.

/**
* Initialize arguments.
*
* @return void
*/
public function initializeArguments() {
parent::initializeArguments();

$this->registerArgument(‘defaultOption’, ‘string’, ‘Value to prepend to the options’, FALSE);
}

parent::initializeArguments() permet d’initialiser les arguments de la classe parent.

Ensuite, nous allons modifier la fonction getOptions. Cette fonction retourne un tableau associatif, composé des options du champ de sélection. Le code ci-dessous permet d’ajouter la valeur de notre argument ‘defaultOption’ à la liste d’options provenant du repository.

/**
* Get parent options plus the new one
* Render the option tag
*
* @return array an associative array of options, key will be the value of the option tag
*
*/
protected function getOptions() {
return array($this->arguments[‘defaultOption’]) + parent::getOptions();
}

Ces deux fonctions doivent être contenues dans la classe Tx_MonExtension_ViewHelpers_Form_SelectViewHelper.

Exemple :

class Tx_MonExtension_ViewHelpers_Form_SelectViewHelper extends Tx_Fluid_ViewHelpers_Form_SelectViewHelper {

// methodes

}

Ensuite, comme nous appelons le ViewHelper de notre extension, nous devons spécifier un nouvel espace de nom dans notre gabarit.

{namespace monext=Tx_MonExtension_ViewHelpers}

Puis :

<monext:form.select name= »region » options= »{regions} » optionValueField= »uid » optionLabelField= »title » defaultOption= »Sélectionnez une région » />

Deux remarques :
– monext:form.select a remplacé f:form.select. L’intitulé monext est arbitraire. Vous faites comme bon vous semble. La seule contrainte, c’est de faire le lien avec l’espace de nom (namespace).
– On a utilisé le paramètre « defaultOption » pour passer la valeur par défaut. A titre personnel, j’utilise plutôt Tx_Extbase_Utility_Localization. Il s’agit d’un helper qui permet de lire les fichiers locallang. J’assigne ensuite la valeur retournée en tant que valeur de l’argument « defaultOption ».

Au final :

<select name= »tx_monextension_nomplugin[region] »>
<option value= »0″>Sélectionnez une région</option>
<option value= »1″>Alsace</option>
<option value= »2″>Aquitaine</option>
<option value= »3″>Auvergne</option>
etc…
</select>

Comme vous le voyez, c’est simple mais encore faut-il savoir par où commencer ! C’était le but de cet article. Si vous souhaitez progresser sur le sujet, je vous recommande l’installation de l’extension sjr_offers qui contient plusieurs ViewHelpers.

N’hésitez pas à commenter cet article 🙂

TYPO3 Fluid : incorporer du flash facilement avec la Grid View

Publié le

J’utilise de plus en plus l’objet FLUIDTEMPLATE et la Grid View (templating Jetts) pour m’affranchir des contraintes du back office de TYPO3 et permettre aux contributeurs de mettre à jour facilement leur site internet. C’est vrai qu’avec TemplaVoilà, ça serait plus facile mais j’évite depuis un bon moment cette méthode de templating.

Je ne vais pas revenir sur mes raisons. Ce n’est pas l’objet de ce post 🙂 Dernièrement, après avoir utilisé l’assistant et modifié moi-même le résultat pour fusionner par exemple des cellules, je me suis heurté à un petit souçi. Ce n’est pas grand chose mais la solution délivrée ici est toute simple et vous permettra, peut-être, de ne pas perdre de temps.

Dans une colonne de mon back office, je devais ajouter du code pour une petite animation en Flash. En modifier le fonctionnement du RTE (voir ce lien), on peut à priori ajouter facilement du code HTML contenant les balise embed, object et param, sauf que cette fois-ci, l’astuce n’a pas fonctionnée. Mon HTML était en effet pas interprété du tout, le code HTML s’affichait directement sur la page. Du coup, j’ai installé un plugin pour faire l’insertion de code de manière plus propre que par l’ajout d’un objet de contenu de type HTML.  Pour info, il s’agit de Movie Players. Bien tenté mais ça ne fonctionne toujours pas. Du coup, j’ai ouvert la classe Tx_Fluid_ViewHelpers_Format_HtmlViewHelper et j’ai remarqué qu’elle prenait un paramètre appelé parseFuncTSPath. Ce paramètre indique le chemin de la librairie chargée de s’occuper du rendu en front office. C’est d’ailleurs expliqué sur le Wiki de TYPO3. La librairie utilisée par défaut est lib.parseFunc. Donc, pourquoi ne pas s’en abstenir dans ce cas ?

Ainsi, au lieu de mettre le code habituel comme ceci :

<f:format.html>{flash}</f:format.html>

Essayez plutôt de cette manière (paramètre vide) :

<f:format.html parseFuncTSPath= » »>{flash}</f:format.html>

C’est tout bête mais ça marche.

TYPO3 Fluid : le View Helper de traduction

Publié le Mis à jour le

Les aides de vue ou View Helpers sont des aides à l’affichage. Ces View Helpers sont situés dans typo3/sysext/fluid/Classes/ViewHelpers/.

Nous allons voir aujourd’hui l’aide de vue pour les traductions. Ce View Helper est situé ici : typo3/sysext/fluid/Classes/ViewHelpers/TranslateViewHelper.php

Pourquoi l’utiliser ?

Le view helper (ou aide de vue) de traduction dans Fluid évite de coder en dur les différents messages dans les gabarits HTML.
Lorsque l’on souhaite mettre à jour une traduction, il est plus simple de passer par un seul fichier XML contenant l’intégralité des traductions, plutôt que de retoucher les fichiers HTML. De plus, et c’est là le plus important, un fichier XML est obligatoire si votre site est en plusieurs langues.
Néanmoins, on peut affirmer que même si votre site n’est traduit qu’en une seule langue, on ne dois jamais se passer d’un fichier XML. Il suffit juste de déclarer la langue du site comme langue par défaut.

<languageKey index= »default » type= »array »> […] </languageKey>

Comment utiliser ce view helper ?

Avec tslib_pibase, on n’utilisait $this->pi_getLL(‘the.key’) où « the.key » est l’entrée correspondante dans le fichier locallang.xml.
Pour Fluid, la syntaxe du fichier XML est la même mais on le code différement dans le fichier HTML.

Tout d’abord, petit rappel sur l’emplacement du fichier html. Celui-ci doit se situer dans le répertoire Resources/Private/Templates de votre extension.
Ensuite, on le place dans un dossier portant le nom du contrôleur appelé en front office.

Pour reprendre l’extension MVC blog_example, les contrôleurs identifiés sont : blog et post. On a donc deux dossiers dans Resources/Private/Templates :
– Blog
– Post
(Notez la première lettre en majuscule… c’est une règle).
On a ensuite un fichier HTML pour chaque action, le nom du fichier portant le nom de l’action, toujours avec une lettre majuscule au début.

# Voici l’appel du view helper dans un template (fonctionne également dans un partiel) :
<f:translate key= »the.key » htmlEscape= »false » />

Ce view helper va aller cherche la traduction de la clé « the.key » dans le fichier locallang.xml, situé dans le dossier Resources/Private/Language/.

C’est un appel basique mais d’autres appels sont également possibles :

# Référence à un fichier : <f:translate key= »LLL:EXT:myext/Resources/Private/Language/locallang.xml:the.key » />
L’intérêt ici c’est que vous pouvez spécifier un autre fichier que celui appelé par défaut.

# Ajout d’un texte par défaut si la clé n’est pas trouvée : <f:translate key= »the.key » htmlEscape= »false » default= »Texte par défaut » />

# Autre notation et passage d’arguments :

Si on a le label suivant :
<label index= »the.key »>TYPO3 has a large and growing %s of users %s.</label>

%s et %s seront remplacés respectivement par community et worldwide, ‘default value’ est une valeur par défaut.

Vous pouvez bien évidemment utiliser des fonctions fournies par Fluid pour rendre dynamique les paramètres passés :

<f:translate key= »post.list » arguments= »{numberOfBosts: ‘{posts -> f:count()}’} »>

Ou encore (extension perso) :

<f:translate key= »tx_simplefaq_domain_model_category.selectedcat » arguments= »{0: ‘{singleCategory.title}’} » htmlEscape= »false » default= »Texte par défaut » />

Ci-dessus, on a fait appel à deux View Helpers :
– f:translate
– f:count

L’objet « posts » contient tous les posts retournés par le contrôleur avec les lignes suivantes :
$this->postRepository->findByBlog($blog);
$this->view->assign(‘posts’, $posts);

Au final : « This blog contains 5 posts »

Je vous encourage à inspecter les autres view helpers dans typo3/sysext/fluid/Classes/ViewHelpers/. Des exemples sont commentés dans le code PHP des classes 🙂