Ez-publish ( 10 / 75 articles - Voir la liste )

Astuce [eZ5] Authentifier un utilisateur programmatiquement

Pour authentifier programmatiquement un utilisateur en front-office, vous pouvez utiliser cette méthode :

<?php

use eZ\Publish\Core\MVC\Symfony\Security\User as SecurityUser;
use eZ\Publish\API\Repository\Values\User\User;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

    /**
     * Connecte l'utilisateur en argument.
     *
     * @param User $user
     *   Utilisateur eZ Publish récupéré depuis le repository
     *
     * @throws \Exception Si une erreur survient lors de la récupération du service de gestion de jeton.
     */
    public function login(User $user)
    {
        // Authentification pour Symfony
        $roles =['ROLE_USER'];
        $security_user = new SecurityUser($user, $roles);
        $security_user->setAPIUser($user);

        $token = new UsernamePasswordToken($security_user, null, 'ezpublish_front', $roles);
        $this->container->get('security.token_storage')->setToken($token);

        // Authentification pour le repo eZ Publish
        $this->repository->setCurrentUser($user);
    }

Marque-page [eZ5] Les répertoires dans le cœur d'eZ Publish 5

Le cœur d'eZ Publish 5 se trouve dans le répertoire vendor/ezsystems/ezpublish-kernel/ de l'application.

Voici quelques répertoires utiles qu'il contient :

  • eZ/Publish/API/Repository/ : contient les interfaces des services avec les signatures de toutes leurs méthodes.
  • eZ/Publish/Core/ : contient l'implémentation des interfaces du répertoire précédent
    • Repository/ : contient l'implémentation de ces mêmes services.
    • Base/Exceptions/ : contient toutes les exceptions fournies par eZ, et surtout leurs constructeurs.
    • Persistence/Legacy/Content/Search/Gateway/CriterionHandler/ : contient les critères de recherche fournis par eZ.
    • Persistence/Legacy/Content/Search/Gateway/SortClauseHandler/ : contient les méthodes de tri fournies par eZ.

Remarque :

Les 4 derniers répertoires, sont sous eZ/Publish/Core/.

Astuce [eZ5] Rechercher des contenus par mot clé

L'extension eZTags pour eZ Publish fournit un système de mots clés pour regrouper des contenus par thématique. Avec elle arrive un nouveau type de champ, pour taguer vos contenus.

Dans eZ Publish 4.x (ou en mode legacy), le template de ce champ affiche un lien vers une page qui liste les contenus avec ce mot clé. La version pour eZ Publish 5 est disponible ici. Malheureusement, elle ne fournit aucune méthode pour trouver des contenus à partir d'un mot clé.

Voici trois méthodes pour récupérer ces contenus.

<?php

// [...]

use \Netgen\TagsBundle\API\Repository\Values\Tags\Tag;

/**
 * Retrouve les contenus avec le mot clé en argument.
 *
 * @param string $keyword Mot clé recherché
 * @param int $offset Offset pour les résultats de la recherche
 * @param int $limit Nombre maximal de résultats de recherche
 *
 * @return \eZ\Publish\API\Repository\Values\Content\Content[]
 *
 * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException Si l'utilisateur courant n'a pas le droit de voir les tags
 * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException Si aucun tag avec cet ID n'existe
 */
public function getRelatedContentByKeyword($keyword, $offset = 0, $limit = 50) {

    $rootTagID = 2;

    // Recherche du tag correspond au mot clé
    $tag = $this->getTagByKeyword($rootTagID, $keyword);

    $relatedContentList = array();

    if (!empty($tag)) {

        // Recherche des contenus avec le mot clé souhaité
        $tagService         = $this->container->get('ezpublish.api.service.tags');
        $relatedContentList = $tagService->getRelatedContent($tag, $offset, $limit);
    }

    return $relatedContentList;
}

/**
 * Retrouve un Tag à partir de son mot clé.
 * Le premier trouvé parmi les descendants de celui dont l'ID est en argument est retourné.
 *
 * @param string $rootTagID ID du tag parmi les descendants duquel rechercher
 * @param string $keyword Mot clé recherché
 *
 * @return \Netgen\TagsBundle\API\Repository\Values\Tags\Tag
 *
 * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException Si l'utilisateur courant n'a pas le droit de voir le tag courant
 * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException Si aucun tag avec cet ID n'existe
 */
public function getTagByKeyword($rootTagID, $keyword) {

    $tag = null;

    // Récupération du tag racine
    $tagService = $this->container->get('ezpublish.api.service.tags');
    $rootTag    = $tagService->loadTag($rootTagID);

    if (!empty($rootTag)) {

        // Récupération des tags descendants
        $descendantTagList = $this->getTagDescendantList($rootTag);

        if (!empty($descendantTagList)) {

            // Parcours des tags descendants
            for ($i = 0, $length = count($descendantTagList); $i < $length && $tag == null; $i++) {

                if ($descendantTagList[$i]->keyword == $keyword) { 
                    $tag = $descendantTagList[$i];
                }
            }
        }
    }

    return $tag;
}

/**
 * Retourne tous les tags descendant de celui en argument.
 *
 * @param \Netgen\TagsBundle\API\Repository\Values\Tags\Tag $rootTag Tag racine
 *
 * @return \Netgen\TagsBundle\API\Repository\Values\Tags\Tag[]
 *
 * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException Si l'utilisateur courant n'a pas le droit de voir le tag courant
 */
public function getTagDescendantList( Tag $rootTag ) {

    // Récupération des tag descendants
    $descendantTagList = array();

    $tagService       = $this->container->get( 'ezpublish.api.service.tags' );
    $childrenTagList  = $tagService->loadTagChildren( $rootTag );

    // Parcours des tags enfants
    foreach ( $childrenTagList as $childTag ) {

        $descendantTagList[] = $childTag;

        // Récupération des descendants
        $descendantTagList = array_merge( $descendantTagList, $this->getTagDescendantList( $childTag ) );
    }

    return $descendantTagList;
}

Remarques :

  • Ces méthodes peuvent être utilisées dans un contrôleur, où l'attribut $container (ContainerInterface) est disponible.
  • Tous vos tags doivent avoir une racine commune (= une seule arborescence). Cette racine servira de base pour les recherches.
  • Dans la première méthode, la variables $rootTagID (identifiant du tag racine) est en dur et devrait être récupérée depuis un fichier de configuration.
  • Dans cet exemple, la recherche ne fonctionne pas pour les synonymes. La deuxième méthode peut être améliorée pour les gérer.

Astuce [eZ5] Ajouter des filtres et des fonctions à Twig

Twig fournit de nombreuses fonctions et une liste de filtres pour simplifier le développement des templates.

Quelques exemples :

{# Des fonctions natives : #}
Contenu d'une variable : {{ dump(my_var) }}
Nombre aléatoire : {{ random(5) }}

{# Des filtres natifs : #}
Taille d'un tableau : {{ my_array|length }}
Mise en minuscule : {{ my_string|upper }}
Échappement de caractère : {{my_string|escape}}

L'intérêt de Twig c'est qu'il est très facilement extensible, et vous vous pouvez créer vos propres fonctions et vos propres filtres. Par exemple :

{# Une nouvelle fonction : #}
Affiche l'Url actuelle : {{ current_uri() }}

{# Un nouveau filtre : #}
{{ "Ma phrase est trop longue parce que la fin n'est pas intéressante."|truncate(28) }}

Prérequis

  • Vous avez déjà créé le Bundle Acme/MyBundle, et l'avez activé dans le fichier ezpublish/EzPublishKernel.php.

Remarque :

Si ce n'est le nom du fichier de kernel, tout cet exemple est valable pour une application Symfony 2 non eZ.

Création de l'extension Twig

L'ajout de filtres et fonctions se fait via un fichier PHP, qu'on appelle une extension Twig.

Créez le répertoire Twig/ dans votre bundle, et le fichier MyExtension.php à l'intérieur :

<?php
namespace AT\APIToolsBundle\Twig;

use \Symfony\Component\DependencyInjection\ContainerInterface;

class MyExtension extends \Twig_Extension {

    /**
     * @var \Symfony\Component\DependencyInjection\ContainerInterface;
     */
    protected $container;

    /**
     * Contructeur de l'extension Twig MyExtension.
     *
     * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
     */
    public function __construct(ContainerInterface $container) {

        $this->container = $container;
    }

    /**
     * Retourne le nom de l'extension.
     *
     * @return string
     */
    public function getName() {

        return 'MyExtension';
    }

    /**
     * Retourne la liste des Filtres de template à ajouter à Twig.
     *
     * @return array
     */
    public function getFilters() {

        return [
            'truncate' => new \Twig_Filter_Method($this, 'truncate'),
        ];
    }

    /**
     * Retourne la liste des Fonctions de template à ajouter à Twig.
     *
     * @return array
     */
    public function getFunctions() {

        return [
            'current_uri' => new \Twig_Function_Method($this, 'getCurrentURI'),
        ];
    }

    /**
     * Retourne l'URI courante.
     *
     * @return string $_SERVER['REQUEST_URI']
     */
    public function getCurrentURI() {

        return $_SERVER['REQUEST_URI'];
    }

    /**
     * Tronque le texte en argument.
     * Si la longueur du texte est supérieure à $maxLength, $suffix est ajouté à la chaîne.
     *
     * @param string $text Chaîne à tronquer
     * @param int $maxLength Longueur maximale autorisée pour la chaîne
     * @param string $suffix Le sufixe à ajouter si besoin
     * @return string
     */
    public function truncate($text, $maxLength, $suffix = '...') {

        $truncatedText = $text;

        mb_internal_encoding('UTF-8');

        $length      = mb_strlen($text );
        $sufixlength = mb_strlen($suffix);

        // Si le texte est trop long
        if ($length > $maxLength && $length >= $sufixlength) {

            $truncatedText = mb_substr($text, 0, $maxLength - $sufixlength) . $suffix;
        }

        return $truncatedText;
    }
}

Explications :

  • La classe MyExtension étend la classe Twig_Extension fournie par Symfony.
  • La méthode getName() retourne le nom de votre choix pour votre extension.
  • Les méthodes getFilters() et getFunctions() retournent la liste des filtres et des fonctions à ajouter à Twig.
  • Le nom du filtre ou de la méthode est défini par la clé dans le tableau (ici truncate et current_uri).
  • Pour instancier un nouveau filtre, on utilise new \Twig_Filter_Method($this, 'méthode_à_appeler').
  • Et de la même manière, pour une nouvelle fonction new \Twig_Function_Method($this, 'méthode_à_appeler').
  • Les deux dernières méthodes sont celles appelées dans les constructeurs. Elles contiennent le code métier qui effectue le traitement.

Informer Symfony

L'extension Twig est terminée mais Symfony ne sait pas encore qu'elle existe. Il vous faut la déclarer en tant que service, dans le fichier Resources/config/services.yml de votre bundle :

parameters:
    acme_my.twig_extension.class: Acme\MyBundle\Twig\MyExtension

services:
    acme_my.twig_extension:
        class: %acme_my.twig_extension.class%
        arguments: [@service_container]
        tags:
            - { name: twig.extension }

Explications :

  • Chaque paramètre et chaque service du fichier a un identifiant unique (ex : acme_my.twig_extension).
  • On définit la classe MyExtension comme paramètre. Si on déplace ou renomme la classe par la suite, seul le paramètre sera à changer.
  • On déclare l'extension Twig en tant que service, en spécifiant la classe à utiliser et l'argument à passer au constructeur.
  • On tague le service avec twig.extension pour que Symfony sache de quel type de service il s'agit.

Astuce [eZ5] Créer une page de login

Objectif

Le but de cet article est de proposer un exemple de page de connexion. Il s'articule autour de deux fichiers principaux : un template Twig et un contrôleur PHP.

Il est réalisé entièrement en mode Symfony, sans utiliser le stack Legacy.

Si l'utilisateur saisit de mauvais identifiants, un message d'erreur est affiché. Une fois connecté, il est redirigé vers la page qu'il consultait avant de se connecter.

Prérequis

  • Vous avez déjà créé le Bundle Acme/MyBundle, et l'avez activé dans le fichier ezpublish/EzPublishKernel.php.
  • Le pagelayout utilisé par défaut est AcmeMyBundle::pagelayout.html.twig. Il possède un bloc nommé col_main.
  • Dans le pagelayout, la variable redirect_uri doit être définie et contenir l'url courante (ex: /Ma-rubrique/Mon-article).

Création du template

Dans le répertoire de templates de votre bundle (Resources/views/), créez les répertoires user/connection/, qui contiendront tous les templates pour la connexion des utilisateurs (connexion, inscription, ...)

Créez ensuite le fichier login.html.twig dans le répertoire user/connection/.

Voici à quoi il peut ressembler :

{# Surcharge du bloc 'col_main' du template pagelayout.html.twig, pour la page de connexion #}
{% extends noLayout ? viewbaseLayout : "AcmeMyBundle::pagelayout.html.twig" %}

{#
    Affiche un article en mode Full

    Paramètres :
    - noLayout      : False
    - fail_login    : Si la connexion a échouée
    - redirect_uri  : URI vers laquelle rediriger après la connexion
 #}

{% block col_main %}

<div class="main-content user user-login panel">

    {# Titre #}
    <header class="heading">
        <h1>Connexion</h1>
    </header>

    {# Contenu #}
    <div class="content-body">

        {# Message d'erreur #}
        {% if fail_login %}
            <div class="alert alert-danger">
                <button data-dismiss="alert" class="close" type="button">×</button>
                <p><strong>Erreur !</strong></p>
                <p>Identifiant ou mot de passe invalide.</p>
            </div>
        {% endif %}

        {# Formulaire #}
        <form class="form-horizontal" method="post"
              action="{{ path( 'acme_my_user_login', { 'redirectURI': redirect_uri } ) }}">

            <div class="form-group {% if fail_login %}has-error{% endif %}">
                <label class="col-lg-3 control-label" for="login">Identifiant</label>
                <div class="col-lg-4">
                    <input type="text" placeholder="Identifiant" 
                           id="login" name="Login" class="form-control input-small">
                </div>
                <div class="validation col-lg-5">
                    <img src="{{ asset( "bundles/acmemy/images/error.png" ) }}" alt="Erreur" />
                </div>
            </div>

            <div class="form-group {% if fail_login %}has-error{% endif %}">
                <label class="col-lg-3 control-label" for="password">Mot de passe</label>
                <div class="col-lg-4">
                    <input type="password" placeholder="Mot de passe" 
                           id="password" name="Password" class="form-control input-small">
                </div>
                <div class="validation col-lg-5">
                    <img src="{{ asset( "bundles/acmemy/images/error.png" ) }}" alt="Erreur" />
                </div>
            </div>

            <div class="form-group">
                <div class="col-lg-10 text-right">
                    <button class="btn btn-primary" type="submit">Connexion</button>
                </div>
            </div>
        </form>
    </div>
</div>
{% endblock %}

Explications :

  • Ligne 2, on commence par étendre le pagelayout par défaut pour modifier le bloc principal.
  • Juste en dessous, en commentaire, on liste les paramètres disponibles/nécessaires dans le template.
  • Ensuite, on commence la surcharge du bloc principal de la page : col_main.
  • On affiche un message d'erreur si les identifiants sont mauvais ({% if fail_login %}).
  • On affiche un formulaire avec un champ identifiant et un champ mot de passe.
  • Le formulaire pointe vers la route acme_my_user_login, sur laquelle Symfony va brancher le futur contrôleur. L'URL courante lui sera transmise en argument.

Remarques :

  • L'image d'erreur doit être présente dans le répertoire Resources/public/images/ du bundle.
  • Ce template utilise le framework CSS Bootstrap 3.
  • Les textes devraient être entre les tags {% trans %} et {% endtrans %}, pour pouvoir être traduits facilement par la suite si besoin.

Création du contrôleur

C'est le contrôleur qui va gérer les actions de connexion et déconnexion des utilisateurs. Il aura donc deux actions : login et logout.

Créez le fichier UserConnectionController.php dans le répertoire Controller/ de votre Bundle :

<?php
namespace Acme\MyBundle\Controller;

use \eZ\Bundle\EzPublishCoreBundle\Controller;
use \eZ\Publish\API\Repository\Exceptions\NotFoundException;
use \eZ\Publish\API\Repository\Values\User\User;
use \Symfony\Component\HttpFoundation\Cookie;
use \Symfony\Component\HttpFoundation\RedirectResponse;

/**
 * Controleur pour gérer les vues de connexion des utilisateurs.
 */
class UserConnectionController extends Controller {

    /**
     * Gestion de l'affichage de la page de login.
     *  - Affiche la page de login par défaut
     *  - Affiche d'éventuelles erreur de connexion
     *  - Connecte et redirige l'utilisateur
     *
     * @param string URI vers laquelle rediriger après la déconnexion
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function loginAction( $redirectURI ) {

        $failLogin = false;

        // Suppression d'un éventuel doublon dans l'URI
        if ( ( $offset = strpos( $redirectURI, '/user/login' ) ) === 0 ) {
            $redirectURI = substr( $redirectURI, $offset );
        }

        $request = $this->getRequest()->request;

        // Si le formulaire de connexion a été soumis
        if ( $request->has( 'Login' ) && $request->has( 'Password' ) ) {

            $login       = $request->get( 'Login' );
            $password    = $request->get( 'Password' );

            if ( trim( $login ) != '' && trim( $password ) != '' ) {
                $userService = $this->getRepository()->getUserService();

                try {
                    $user = $userService->loadUserByCredentials( $login, $password );
                    return $this->connectUser( $user, $redirectURI );

                } catch (NotFoundException $e) {
                    $failLogin = true;
                }
            } else {
                $failLogin = true;
            }
        }

        return $this->render(
            'AcmeMyBundle:user\connection:login.html.twig',
            array(
                'noLayout'      => false,
                'fail_login'    => $failLogin,
                'redirect_uri'  => $redirectURI
            )
        );
    }

    /**
     * Déconnecte l'utilisateur courant.
     *
     * @param string URI vers laquelle rediriger après la déconnexion
     *
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException Si l'utilisateur anonyme n'existe pas
     */
    public function logoutAction( $redirectURI ) {

        // Suppression d'un éventuel doublon dans l'URI
        if ( ( $offset = strpos( $redirectURI, '/user/logout' ) ) === 0 ) {
            $redirectURI = substr( $redirectURI, $offset );
        }

        // Récupération de l'utilisateur anonyme
        $userService  = $this->getRepository()->getUserService();
        $anonymousUser = $userService->loadAnonymousUser();

        return $this->connectUser( $anonymousUser, $redirectURI );
    }

    /**
     * Connecte l'utilisateur en argument et retourne une redirection 302.
     * Si l'utilisateur en argument est anonyme, alors c'est une déconnexion.
     *
     * @param \eZ\Publish\API\Repository\Values\User\User $user L'utilisateur à connecter
     * @param string $redirectURI URI vers laquelle rediriger l'utilisateur après connexion
     *
     * @return RedirectResponse
     */
    protected function connectUser( User $user, $redirectURI = '/' ) {

        $repository = $this->getRepository();
        $repository->setCurrentUser( $user );
        $session    = $this->getRequest()->getSession();

        try {
             $response = new RedirectResponse( $redirectURI );

        } catch (NotFoundException $e) {
             $response = new RedirectResponse( '/' );
        }

        $userService    = $repository->getUserService();
        $anonymousUser  = $userService->loadAnonymousUser();

        // Si l'utilisateur en argument est anonyme
        if ( $user->id === $anonymousUser->id ) {
            // Déconnexion de l'utilisateur courant
            $response->headers->setCookie( new Cookie( 'is_logged_in', 'false' ) );
            $session->remove( 'eZUserLoggedInID' );

        } else {
            // Connexion de l'utilisateur
            $response->headers->setCookie( new Cookie( 'is_logged_in', 'true' ) );
            $session->set( 'eZUserLoggedInID', $user->id );
        }

        return $response;
    }
}

Explications :

  • Le contrôleur est une classe PHP qui étend la classe Controller du Bundle eZ\Bundle\EzPublishCoreBundle fourni par eZ Publish.
  • Ses deux premières méthodes sont des actions et leurs noms finissent d'ailleurs par Action. Elles retournent un objet Response.
  • La troisième est une méthode utilitaire pour connecter un utilisateur.
  • Par défaut, loginAction() inclue le template de login dans sa réponse, grâce aux lignes :
return $this->render(
    'AcmeMyBundle:modules/user:login.html.twig',
    array(
        'noLayout'      => false,
        'fail_login'    => $failLogin,
        'redirect_uri'  => $redirectURI
    )
);
  • Si le formulaire est soumis et valide, on appelle la méthode connectUser() qui connecte l'utilisateur et on fournit une réponse de type redirection.

Configuration de la route

Pour que Symfony sache quoi faire lorsqu'on appelle la page http://mon-site/user/login, il faut modifier le fichier Resources/config/routing.yml dans votre bundle.

Ajoutez-y les deux routes suivantes, pour se connecter et se déconnecter :

acme_my_user_login:
    pattern:  /user/login{redirectURI}
    defaults: { _controller: AcmeMyBundle:UserConnection:login }
    requirements:
        redirectURI: ".*"

acme_my_user_logout:
    pattern:  /user/logout{redirectURI}
    defaults: { _controller: AcmeMyBundle:UserConnection:logout }
    requirements:
        redirectURI: ".*"

Explications :

  • Une route doit être nommée par un identifiant unique de votre choix (ex : acme_my_user_login). C'est lui qui est appelé dans la fonction path() côté template.
  • Elle associe un pattern d'URL, à l'action d'un contrôleur.
  • Pour la première route, si on appelle la page /user/login<quelque chose>, la méthode loginAction() du contrôleur UserConnectionController du bundle AcmeMyBundle sera exécutée. La méthode recevra quelque chose en argument.
  • Les éléments dans requirements permettent entre autres de spécifier la forme que doit avoir le paramètre. Ici, n'importe qu'elle chaîne est autorisée.

Astuce [eZ5] Créer un bundle

Qu'est-ce qu'un Bundle ?

Bundle est le nom Symfony pour un module, une brique, une extension (terme eZ Publish 4.X). Il peut contenir tout ou une partie du design, une API technique, une fonctionnalité particulière, ...

Il peut être dépendant d’autres Bundles, mais est réutilisable. Il est identifié par un nom de domaine (namespace) et un nom de Bundle (finissant par Bundle), le tout concaténé.

Création du Bundle

La création du Bundle peut se faire via ligne de commande, à partir du répertoire racine de l’application eZ Publish :

php ezpublish/console generate:bundle --namespace="MonNamespace/MonBundle"

Explications :

  • Le paramètre namespace est le nom du namespace et le nom du Bundle concaténés.
  • Le nom de domaine peut être le nom du projet, celui de l’entreprise, ... Il peut contenir des /.
  • Le nom du Bundle doit finir par Bundle.

Nom du Bundle

L’assistant de création du Bundle propose alors le nom final du Bundle : MonNamespaceMonBundle.

Appuyez sur Entrée pour conserver ce nom standard.

Remarque :

Si vous créez le Bundle principal de votre application, et que vous souhaitez avoir un namespace et un nom de Bundle identique, c'est à cette étape que vous pouvez simplifier le nom final pour éviter d'avoir MonNamespaceMonNamespaceBundle.

Emplacement du Bundle

Vous pouvez ensuite choisir le chemin où se trouvera le Bundle.

Par défaut il sera créé dans le répertoire src/ à la racine de l’application eZ Publish, ce qu'il est préférable de conserver : appuyez sur Entrée.

Format de la configuration

Choisissez yml comme format de configuration, et validez avec Entrée.

Génération et autres configurations

Pour une première fois, choisissez de générer la structure complète du Bundle.

Appuyez sur Entrée pour confirmer toute la génération.

Même chose pour les questions suivantes.

Fichiers générés

L’assistant de création de Bundle a généré l’arborescence suivante :

Arborescence bundle généré

Comme tout bundle Symfony, il se compose de 3 répertoires principaux :

  • Controller/ : vous y créerez vos contrôleurs (équivalents de vos modules dans eZ4).
  • Resources/ : s'y trouvent tous les fichiers non PHP (templates Twig, fichiers de config, js, CSS, ...).
  • Tests/ : répertoire contenant vos tests unitaires.

Erreur [eZ5] FatalErrorException: Error: Class 'XSLTProcessor' not found

Si vous rencontrez l'erreur suivante après l'installation d'eZ Publish 5 :

FatalErrorException: Error: Class 'XSLTProcessor' not found in 
[...]\vendor\ezsystems\ezpublish-kernel\eZ\Publish\Core\FieldType\XmlText\Converter\Html5.php line 77

C'est que l'extension xsl n'est pas activée pour PHP.

Erreur [eZ5] The extension "ext/fileinfo" must be loaded in order for this class to work

Lorsque vous migrez vers eZ Publish Community Project 2013.06, vous pouvez rencontrer cette erreur :

The extension "ext/fileinfo" must be loaded in order for this class to work.

Fileinfo est une extension pour PHP. Elle est généralement déjà packagée sous Linux, mais pas sous Windows avec WampServer.

Activez l'extension php_fileinfo et redémarrez apache.

Marque-page [eZ] Créer un datatype

Dans eZ Publish 4, un datatype est un type de champ pour une classe de contenu.

EZ Publish en fournit un certain nombre : image, ligne de texte, texte riche, case à cocher, nombre, ... Vous pouvez également créer votre propre datatype, pour facilité la contribution et l'affichage d'un champ.

On peut par exemple imaginer un champ couleur, avec côté back-office une pipette ou une palette de couleur pour choisir facilement sa couleur.

Voici un tutoriel complet pour créer son propre datatype, rédigé par Jérôme Vieilledent et Nicolas Pastorino pour PHP Solutions.

Astuce [eZ5] Développez en mode dev

Avec eZ Publish 5, pour activer la console de développement de Symfony vous devez modifier la configuration Apache, à priori dans votre virtual host.

Remplacez index.php par index_dev.php :

DirectoryIndex index.php
...
RewriteRule .* /index.php

Remarque :

EZ Publish et Symfony doivent également être configurés en mode développement.