Vues

Introduction

Les vues sont responsables de la création des sorties. Elles gèrent tout depuis :

  • la disposition des pages

  • des morceaux de sortie d’affichage (comme un pied de page ou une barre d’outils)

  • des liens individuels et des entrées de formulaire.

  • des images, js, et css nécessaires pour votre page web

Utiliser les vues

À leur niveau le plus élémentaire, les vues par défaut ne sont que des fichiers PHP avec des extraits de html :

<h1>Hello, World!</h1>

En supposant que cette vue se trouve dans /views/default/hello.php, nous pourrions l’afficher comme ceci :

echo elgg_view('hello');

Pour votre commodité, Elgg est livré avec beaucoup de vues par défaut. Afin de garder les choses gérables, elles sont organisées en sous-répertoires. Elgg gère très bien cette organisation. Par exemple, notre vue simple peut être située dans /views/default/hello/world.php, auquel cas elle sera appelée comme ceci :

echo elgg_view('hello/world');

Le nom de la vue reflète simplement l’emplacement de la vue dans le répertoire des vues.

Les vues comme modèles (templates)

Vous pouvez transmettre des données arbitraires à une vue via le tableau $vars. Notre vue hello/wordl pourrait être modifié pour accepter une variable comme ceci :

<h1>Hello, <?= $vars['name']; ?>!</h1>

Dans ce cas, nous pouvons passer un paramètre de nom arbitraire à la vue comme ceci :

echo elgg_view('hello/world', ['name' => 'World']);

qui produirait la sortie suivante :

<h1>Hello, World!</h1>

Avertissement

Les vues ne font aucune sorte d’assainissement automatique de la sortie par défaut. Vous êtes responsable de faire l’assainissement correct vous-même pour prévenir les attaques XSS et similaires.

Les vues en tant qu’actifs pouvant être mis en cache

Comme mentionné précédemment, les vues peuvent contenir du JS, des CSS, ou même des images.

Les actifs doivent correspondre à certaines exigences :

  • Elles ne doivent pas utiliser de paramètre de $vars

  • Elles ne doivent pas modifier leur sortie en fonction de l’état global comme

    • qui est connecté

    • l’heure de la journée

  • Elles doivent avoir une extension de fichier valide

    • Mauvais : my/cool/template

    • Bon : my/cool/template.html

Par exemple, supposons que vous vouliez charger certains CSS sur une page. Vous pouvez définir une vue messtyles.css, qui ressemblerait à ceci :

/* /views/default/mystyles.css */
.mystyles-foo {
  background: red;
}

Note

Omettez l’extension « .php » du nom de fichier et Elgg reconnaîtra automatiquement la vue comme pouvant être mise en cache.

Pour obtenir une URL de ce fichier, vous utiliseriez elgg_get_simplecache_url :

// Returns "https://mysite.com/.../289124335/default/mystyles.css
elgg_get_simplecache_url('mystyles.css');

Elgg ajoute automatiquement les numéros magiques que vous voyez là pour le cache-busting et définit les entêtes Expires à long terme sur le fichier renvoyé.

Avertissement

Elgg pourrait décider de modifier l’emplacement ou la structure de l’URL retournée dans une version ultérieure pour une raison quelconque, et les numéros d’invalidation du cache (cache-busting) changent à chaque fois que vous videz les caches d’Elgg, de sorte que l’URL exacte n’est pas stable par design.

Avec cela à l’esprit, voici quelques anti-modèles à éviter :

  • Ne vous fiez pas à la structure/emplacement exacts de cette URL

  • N’essayez pas de générer les URL vous-même

  • Ne stockez pas les URL renvoyées dans une base de données

Dans la fonction init de votre plugin, enregistrez le fichier css :

elgg_register_css('mystyles', elgg_get_simplecache_url('mystyles.css'));

Sur la page où vous souhaitez charger le css, appelez :

elgg_load_css('mystyles');

Vues et actifs tierce-partie (assets)

La meilleure manière de servir des actifs tiers est par le biais des vues. Toutefois, au lieu de copier/coller manuellement les actifs au bon endroit dans /views/*, vous pouvez mapper les actifs dans le système de vues via la clef "views" dans le fichier de configuration elgg-plugin.php de votre plugin.

La valeur des vues doit être un tableau à 2 dimensions. Le premier niveau mappe un type de vue à une liste de mappage de vues. Le deuxième niveau associe les noms des vues à des chemins de fichiers, absolus ou relatifs au répertoire racine de Elgg.

Si vous ajoutez vos actifs au suivi de version, pointez-les comme ceci :

<?php // mod/example/elgg-plugin.php
return [
    // view mappings
    'views' => [
        // viewtype
        'default' => [
            // view => /path/from/filesystem/root
            'js/jquery-ui.js' => __DIR__ . '/bower_components/jquery-ui/jquery-ui.min.js',
        ],
    ],
];

Pour pointer vers les actifs installés avec fxp/composer-asset-plugin, utilisez les chemins install-root-relative sans le slash initial :

<?php // mod/example/elgg-plugin.php
return [
    'views' => [
        'default' => [
            // view => path/from/install/root
            'js/jquery-ui.js' => 'vendor/bower-asset/jquery-ui/jquery-ui.min.js',
        ],
    ],
];

Le noyau de Elgg utilise cette fonctionnalité largement, bien que la valeur soit retournée directement à partir de /engine/views.php.

Note

Vous n’avez pas besoin d’utiliser Bower, Composer Asset Plugin, ou tout autre script pour gérer les actifs de votre plugin, mais nous vous recommandons fortement d’utiliser un gestionnaire de package, car cela rend la mise à niveau tellement plus facile.

En spécifiant des répertoires supplémentaires pour les vues

Dans elgg-plugin.php vous pouvez également spécifier des répertoires à scanner pour les vues. Il suffit de fournir un préfixe de nom de vue se terminant par / et un chemin de répertoire (comme ci-dessus).

<?php // mod/file/elgg-plugin.php
return [
    'views' => [
        'default' => [
            'file/icon/' => __DIR__ . '/graphics/icons',
        ],
    ],
];

Avec ce qui précède, les fichiers trouvés dans le dossier icons seront interprétés comme des vues. Par exemple, l’affichage file/icon/general.gif sera créé et mappé à mod/file/graphics/icons/general.gif.

Note

Il s’agit d’un scan entièrement récursif. Tous les fichiers trouvés seront introduits dans le système de vues.

Plusieurs chemins peuvent partager le même préfixe, il suffit de donner un tableau de chemins :

<?php // mod/file/elgg-plugin.php
return [
    'views' => [
        'default' => [
            'file/icon/' => [
                __DIR__ . '/graphics/icons',
                __DIR__ . '/more_icons', // processed 2nd (may override)
            ],
        ],
    ],
];

Types de vues (viewtypes)

Vous pouvez vous demandez : « Pourquoi /views/default/hello/world.php au lieu de simplement /views/hello/world.php ? ».

Le sous-répertoire dans /views détermine le viewtype des vues qu’il contient. Un type de vue correspond généralement au format de sortie des vues.

Le type de vue par défaut est supposé être HTML et d’autres actifs statiques nécessaires pour rendre une page Web réactive dans un navigateur de bureau ou mobile, mais il peut également être :

  • RSS

  • ATOM

  • JSON

  • HTML optimisé pour mobile

  • HTML optimisé pour TV

  • N’importe quel nombre d’autres formats de données

Vous pouvez forcer Elgg à utiliser un type de vue particulier pour afficher la page en définissant la variable d’entrée view comme ceci : https://monsite.com/?view=rss.

Vous pourriez également écrire un plugin pour définir ceci automatiquement à l’aide de la fonction elgg_set_viewtype(). Par exemple, votre plugin peut détecter que la page a été consultée avec la chaîne de navigateur d’un iPhone, et définir le type de vue sur iphone en appelant :

elgg_set_viewtype('iphone');

Le plugin fournirait probablement également un ensemble de vues optimisées pour ces appareils.

Modification des vues via des plugins

Sans modifier le noyau d’Elgg, Elgg offre plusieurs manières de personnaliser quasiement toutes les sorties :

Surcharger les vues (override)

Les vues dans les répertoires des plugins remplacent toujours les vues du répertoire du noyau ; toutefois, quand les plugins remplacent les vues d’autres plugins, les vues des derniers plugins remplacent celles de précédents.

Par exemple, si nous voulions personnaliser la vue hello/world pour utiliser un h2 au lieu d’un h1, nous pourrions créer un fichier à mod/exemple/views/default/hello/world.php comme ceci :

<h2>Hello, <?= $vars['name']; ?></h2>

Note

Quand vous considérez la maintenance à long terme, la surcharge des vues du noyau et des plugins groupés a un coût : les mises à niveau peuvent apporter des changements dans les vues, et si vous les avez remplacés, vous n’obtiendrez pas ces changements ou devrez les réintégrer dans vos vues.

Vous pouvez plutôt souhaiter modifier l’entrée ou :ref:{la sortie <guides/views#altering-view-output>` de la vue via des hooks plugin.

Note

Elgg met en cache les chemins des vues. Cela signifie que vous devez désactiver le cache système quand vous développez avec des vues. Lorsque vous installez les modifications apportées dans un environnement de production, vous devez vider les caches.

Étendre les vues

Il peut y avoir d’autres situations dans lesquelles vous ne voulez pas remplacer l’ensemble de la vue, et plutôt y ajouter un peu plus de contenu au début ou à la fin. Dans Elgg, c’est ce qu’on appelle étendre une vue.

Par exemple, au lieu de remplacer la vue hello/world, nous pourrions l’étendre comme ceci :

elgg_extend_view('hello/world', 'hello/greeting');

Si le contenu de /views/default/hello/greeting.php est :

<h2>How are you today?</h2>

Ensuite, chaque fois que nous appelons elgg_view('hello/world');, nous obtiendrons :

<h1>Hello, World!</h1>
<h2>How are you today?</h2>

Vous pouvez ajouter des choses avant la vue en transmettant au 3ème paramètre une valeur inférieure à 500 :

// appends 'hello/greeting' to every occurrence of 'hello/world'
elgg_extend_view('hello/world', 'hello/greeting');

// prepends 'hello/greeting' to every occurrence of 'hello/world'
elgg_extend_view('hello/world', 'hello/greeting', 450);

Toutes les extensions de vues doivent être enregistrées dans le gestionnaire d’événements init,system de votre plugin dans start.php.

Modification de l’entrée d’une vue

Il peut être utile de modifier le tableau $vars d’une vue avant que la vue ne soit rendue.

Depuis 1.11, avant le rendu de chaque vue le tableau $vars est filtré par le hook plugin ["view_vars", $view_name]. Ces arguments sont passés à chaque fonction de gestionnaire enregistrée :

  • $hook - la chaîne "view_vars"

  • $view_name - le nom de la vue (le premier argument est passé à elgg_view())

  • $returnvalue - le tableau modifié $vars

  • $params - un tableau contenant :

    • vars - le tableau original $vars, inchangé

    • view - le nom de la vue

    • viewtype - Le type de vue en train d’être affiché

Exemple de modification des entrées d’une vue

Ici, nous allons modifier la limite de pagination par défaut pour la vue des commentaires :

elgg_register_plugin_hook_handler('view_vars', 'page/elements/comments', 'myplugin_alter_comments_limit');

function myplugin_alter_comments_limit($hook, $type, $vars, $params) {
    // only 10 comments per page
    $vars['limit'] = elgg_extract('limit', $vars, 10);
    return $vars;
}

Modification de la sortie d’une vue

Parfois, il est préférable de modifier la sortie d’une vue au lieu de la remplacer.

La sortie de chaque vue passe par le hook plugin ["view", $view_name] avant d’être renvoyé par elgg_view(). Chaque fonction de gestionnaire enregistrée dispose de ces arguments :

  • $hook - la chaîne "view"

  • $view_name - le nom de la vue (le premier argument est passé à elgg_view())

  • $result - la sortie modifiée de la vue

  • $params - un tableau contenant :

    • viewtype - Le type de vue en train d’être affiché

Pour modifier le résultat de la vue, le gestionnaire n’a qu’à modifier $returnvalue et à renvoyer une nouvelle chaîne.

Exemple de modification d’affichage d’une vue

Ici, nous allons éliminer le fil d’Ariane lorsqu’il ne contient aucun lien.

elgg_register_plugin_hook_handler('view', 'navigation/breadcrumbs', 'myplugin_alter_breadcrumb');

function myplugin_alter_breadcrumb($hook, $type, $returnvalue, $params) {
    // we only want to alter when viewtype is "default"
    if ($params['viewtype'] !== 'default') {
        return $returnvalue;
    }

    // output nothing if the content doesn't have a single link
    if (false === strpos($returnvalue, '<a ')) {
        return '';
    }

    // returning nothing means "don't alter the returnvalue"
}

Remplacement complet du résultat de la vue

Vous pouvez pré-définir la sortie de la vue en définissant $vars['__view_output']. La valeur sera retournée sous forme de chaîne. Les extensions de vue ne seront pas utilisées et le hook view ne sera pas déclenché.

elgg_register_plugin_hook_handler('view_vars', 'navigation/breadcrumbs', 'myplugin_no_page_breadcrumbs');

function myplugin_no_page_breadcrumbs($hook, $type, $vars, $params) {
    if (elgg_in_context('pages')) {
        return ['__view_output' => ""];
    }
}

Afficher des entités

Si vous ne savez pas ce qu’est une entité, commencez par lire cette page.

Le code suivant affiche automatiquement l’entité dans $entity :

echo elgg_view_entity($entity);

Comme vous le savez après la lecture de l’introduction au modèle de données, toutes les entités ont un type (object, site, user ou group), et éventuellement un sous-type (qui pourrait être n’importe quoi - blog, forumpost, banane).

''elgg_view_entity va automatiquement rechercher une vue appelée type/subtype ; s’il n’y a pas de sous-type, elle recherchera type/type. À défaut, elle essaiera type/default avant de renoncer.

Les flux RSS d’Elgg fonctionnent généralement en affichant la vue object/default dans le type de vue “rss”.

Par exemple, la vue pour afficher un article de blog peut être object/blog. La vue pour afficher un utilisateur est user/default.

Vues des entités partielles et complètes

elgg_view_entity dispose en fait d’un certain nombre de paramètres, bien que seul le tout premier soit nécessaire. Les trois premiers sont :

  • $entity - L’entité à afficher

  • ''$viewtype - Le type de vue à afficher (par défaut c’est celui actuellement utilisé, mais il peut être forcé - par exemple pour afficher un extrait RSS dans une page HTML)

  • $full_view - Affichage d’une version complète de l’entité. (Par défaut false.)

Ce dernier paramètre est transmis à la vue sous le nom de $vars['full_view']. C’est à vous de déterminer comment vous souhaitez l’utiliser ; le comportement habituel consiste à afficher uniquement des commentaires et des informations de ce type si cela est défini sur true.

Lister des entités

Ceci est ensuite utilisé dans les fonctions de liste fournies. Pour afficher automatiquement une liste d’articles de blog (voir le tutoriel complet), vous pouvez appeler :

echo elgg_list_entities([
    'type' => 'object',
    'subtype' => 'blog',
]);

Cette fonction vérifie s’il y a des entités ; s’il y en a, elle affiche d’abord la vue navigation/pagination afin d’afficher un moyen de passer d’une page à l’autre. Elle appelle ensuite à plusieurs reprises elgg_view_entity sur chaque entité avant de renvoyer le résultat.

Notez que elgg_list_entities permet à l’URL de définir ses options limit et offset, aussi définissez-les explicitement si vous avez besoin de valeurs particulières (par exemple si vous ne les utilisez pas pour la pagination).

Elgg sait qu’il peut automatiquement fournir un flux RSS sur les pages qui utilisent elgg_list_entities. Il initialise le hook de plugin ["head","page"] (qui est utilisé par l’entête) afin de fournir la découverte automatique RSS, c’est pourquoi vous pouvez voir l’icône RSS orange sur ces pages dans certains navigateurs.

Si votre liste d’entités affiche les propriétaires des entités, vous pouvez améliorer un peu les performances en préchargeant toutes les entités propriétaires :

echo elgg_list_entities([
    'type' => 'object',
    'subtype' => 'blog',

    // enable owner preloading
    'preload_owners' => true,
]);

Voyez aussi ces informations de contexte sur la base de données d’Elgg.

Si vous souhaitez afficher un message lorsque la liste ne contient aucun élément, vous pouvez passer un message no_results. Si vous voulez encore plus de contrôle sur le message no_results, vous pouvez également passer une Closure (une fonction anonyme).

echo elgg_list_entities([
    'type' => 'object',
    'subtype' => 'blog',

    'no_results' => elgg_echo('notfound'),
]);

Rendu d’une liste avec une autre vue

Depuis 1.11, vous pouvez définir une autre vue pour rendre des éléments de liste à l’aide du paramètre item_view.

Dans certains cas, les vues d’entité par défaut peuvent ne pas convenir à vos besoins. L’utilisation de item_view vous permet de personnaliser l’apparence, tout en préservant la pagination, le balisage HTML de la liste, etc.

Prenons les deux exemples suivants :

echo elgg_list_entities_from_relationship([
    'type' => 'group',
    'relationship' => 'member',
    'relationship_guid' => elgg_get_logged_in_user_guid(),
    'inverse_relationship' => false,
    'full_view' => false,
]);
echo elgg_list_entities_from_relationship([
    'type' => 'group',
    'relationship' => 'invited',
    'relationship_guid' => (int) $user_guid,
    'inverse_relationship' => true,
    'item_view' => 'group/format/invitationrequest',
]);

Dans le premier exemple, nous affichons une liste de groupes dont un utilisateur est membre à l’aide de l’affichage de groupe par défaut. Dans le deuxième exemple, nous voulons afficher une liste de groupes auxquels l’utilisateur a été invité.

Étant donné que les invitations ne sont pas des entités, elles n’ont pas leurs propres vues et ne peuvent pas être répertoriées à l’aide de elgg_list_ *. Nous fournissons une vue d’élément alternative, qui utilisera l’entité de groupe pour afficher une invitation qui contient un nom de groupe et des boutons pour accéder ou rejeter l’invitation.

Rendu d’une liste en tant que tableau

Depuis 2.3, vous pouvez afficher des listes sous forme de tableaux. Définissez $options[`list_type'] = 'table' et fournissez un tableau d’objets TableColumn comme $options['columns']. Le service elgg()->table_columns fournit plusieurs méthodes pour créer des objets de colonnes basés sur des vues (comme page/components/column/* ), des propriétés, ou des méthodes existantes.

Dans cet exemple, nous répertorions les derniers objets mon_plugin dans un tableau de 3 colonnes : icône de l’entité, nom d’affichage, et date dans un format convivial.

echo elgg_list_entities([
    'type' => 'object',
    'subtype' => 'my_plugin',

    'list_type' => 'table',
    'columns' => [
        elgg()->table_columns->icon(),
        elgg()->table_columns->getDisplayName(),
        elgg()->table_columns->time_created(null, [
            'format' => 'friendly',
        ]),
    ],
]);

Pour plus d’informations sur la façon dont les colonnes sont spécifiées et rendues, consultez la classe Elgg\Views\TableColumn\ColumnFactory. Vous pouvez ajouter ou remplacer des méthodes de elgg()->table_columns de diverses façons, en fonction des vues, des propriétés/méthodes sur les éléments ou des fonctions données.