Planète

Par liber_t
Adhérent
Ines WALLON

Présentation de GrumPHP

Quand on travaille à plusieurs sur un projet, il peut être intéressant de mettre en place des outils de qualité de code afin d’harmoniser le code source que vous souhaitez mettre en place sur votre projet (linter, CodeSniffer et tests) mais pour cela, il faudra alors s'assurer que tous les collaborateurs les utilisent afin d'en tirer réellement partie et c'est là que GrumPHP rentre en jeux.

Par WeBla
Adhérent
Cédric Albrecht

Drupal 8 Statistics, la vue manquante

Une vue Drupal 8 prête à importer pour obtenir une page de l'ensemble des statistiques collectées par le module Statistics.

Par WeBla
Adhérent
Cédric Albrecht

Drupal 8 Statistics, la vue manquante

Une vue Drupal 8 prête à importer pour obtenir une page de l'ensemble des statistiques collectées par le module Statistics.

Par lequipe.tech
L'Équipe.tech

Configuration minimum pour lancer phpunit avec Drupal

Configuration minimum pour lancer phpunit avec Drupal Drupal 8 PhpUnitFabien CLÉMENT
dim 11/08/2019 - 09:44

A l'heure de la virtualisation et de la containerisation, on n'a pas forcément tout un environnement lamp/wamp/mamp d'installé sur son local.

Sous Drupal 8.x, Si l'on souhaite lancer des test phpunit, nous n'avons besoin que de 3 applications :

  • PHP
  • SQLITE
  • Composer

Suivant votre OS, vous pouvez installer les 2 premiers :

  • Windows : avec leurs binaires
  • Linux : via les dépots
  • OSX : via homebrew

Pour composer, suivre les instructions sur https://getcomposer.org/download/.

Catégorie
Tags
Par lequipe.tech
L'Équipe.tech

Configuration minimum pour lancer phpunit avec Drupal

A l'heure de la virtualisation et de la containerisation, on n'a pas forcément tout un environnement lamp/wamp/mamp d'installé sur son local.

Sous Drupal 8.x, Si l'on souhaite lancer des test phpunit, nous n'avons besoin que de 3 applications :

PHP
SQLITE
Composer

Suivant votre OS, vous pouvez installer les 2 premiers :

Windows : avec leurs binaires
Linux : via les dépots
OSX : via homebrew

Pour composer, suivre les instructions sur https://getcomposer.org/download/.

Habituellement, nous aurions également besoin d'un serveur apache ou nginx pour pouvoir accéder à notre application, mais depuis la version 8.4.x, Drupal embarque ce qu'il faut pour lancer un serveur depuis php.

Lancer la commande :

php -S localhost:8888 .ht.router.php

Il ne reste plus qu'à configurer phpunit en copiant le fichier phpunit.xml.dist en phpunit.xml :

cp core/phpunit.xml.dist core/phpunit.xml

Créer le répertoire sites/default/simpletest et ajuster la configuration suivant vos besoins. Exemple :

   

   

   

   

   

   

Faire un composer install pour installer les dépendances de Drupal et obtenir phpunit.

Il ne reste plus qu'à lancer phpunit en ligne de commande ou depuis phpstorm.

Pour configurer phpstorm, aller dans le menu PHPStorm > Preferences, chercher PHP.

Ajouter votre binaire PHP puis chercher phpunit et dans Test Frameworks, configurer phpunit.

 

Par lequipe.tech
L'Équipe.tech

Configuration minimum pour lancer phpunit avec Drupal

A l'heure de la virtualisation et de la containerisation, on n'a pas forcément tout un environnement lamp/wamp/mamp d'installé sur son local.

Sous Drupal 8.x, Si l'on souhaite lancer des test phpunit, nous n'avons besoin que de 3 applications :

PHP
SQLITE
Composer

Suivant votre OS, vous pouvez installer les 2 premiers :

Windows : avec leurs binaires
Linux : via les dépots
OSX : via homebrew

Pour composer, suivre les instructions sur https://getcomposer.org/download/.

Habituellement, nous aurions également besoin d'un serveur apache ou nginx pour pouvoir accéder à notre application, mais depuis la version 8.4.x, Drupal embarque ce qu'il faut pour lancer un serveur depuis php.

Lancer la commande :

php -S localhost:8888 .ht.router.php

Il ne reste plus qu'à configurer phpunit en copiant le fichier phpunit.xml.dist en phpunit.xml :

cp core/phpunit.xml.dist core/phpunit.xml

Créer le répertoire sites/default/simpletest et ajuster la configuration suivant vos besoins. Exemple :

   

   

   

   

   

   

Faire un composer install pour installer les dépendances de Drupal et obtenir phpunit.

Il ne reste plus qu'à lancer phpunit en ligne de commande ou depuis phpstorm.

Pour configurer phpstorm, aller dans le menu PHPStorm > Preferences, chercher PHP.

Ajouter votre binaire PHP puis chercher phpunit et dans Test Frameworks, configurer phpunit.

 

Par kgaut
Kevin Gautreau

Drupal 8 - Rediriger sur le listing des noeuds après la création d'un contenu

Sur une commande expresse de Vincent, voici comment modifier les formulaires de création / modification de nœud pour être redirigé sur la page de listing des nœuds plutôt que sur le nœud en lui même lors de la création ou de la modification d'un contenu.

1 - Altération du type d'entité

  1. # mon_module.module
  2. function mon_module_entity_type_alter(array &$entity_types) {
  3. $entity_types['node']->setFormClass('default', Drupal\mon_module\Entity\Form\CustomNodeForm::class);
  4. $entity_types['node']->setFormClass('edit', Drupal\mon_module\Entity\Form\CustomNodeForm::class);
  5. }

2 - Classe du formulaire

  1. # web/modules/mon_module/src/Entity/Form/CustomNodeForm.php
  2.  
  3. namespace Drupal\mon_module\Entity\Form;
  4.  
  5. use Drupal\Core\Form\FormStateInterface;
  6. use Drupal\node\NodeForm;
  7.  
  8. class CustomNodeForm extends NodeForm {
  9.  
  10. public function save(array $form, FormStateInterface $form_state) {
  11. parent::save($form, $form_state);
  12. $form_state->setRedirect('view.content.page_1');
  13. }
  14.  
  15. }

 

Par lequipe.tech
L'Équipe.tech

Docker et OSX

Docker et OSX Docker + OSXFabien CLÉMENT
mar 16/07/2019 - 11:26

Chez l'Équipe.tech, nous avons toujours travaillé sous OSX avec des Macbook Pro. Pendant de nombreuses années nous en étions très content. Plus simple pour le web que sous Microsoft Windows qui n'est pas adapté pour du développement PHP, plus propre et clé en main que Linux, et finition impeccable.

La majorité de notre expérience sur cet environnement s'est fait avant l'avènement de Docker, et surtout avant que les machines d'Apple ne soient compatibles avec Docker, quand ils n'utilisaient pas encore de processeurs Intel.

Catégorie
Tags
Par lequipe.tech
L'Équipe.tech

Docker et OSX

Chez l'Équipe.tech, nous avons toujours travaillé sous OSX avec des Macbook Pro. Pendant de nombreuses années nous en étions très content. Plus simple pour le web que sous Microsoft Windows qui n'est pas adapté pour du développement PHP, plus propre et clé en main que Linux, et finition impeccable.

La majorité de notre expérience sur cet environnement s'est fait avant l'avènement de Docker, et surtout avant que les machines d'Apple ne soient compatibles avec Docker, quand ils n'utilisaient pas encore de processeurs Intel.

Lorsque nos machines (et leur processeurs) nous l'ont permis, nous nous sommes alors mis à Docker et ses promesses. Exit les Vagrant, Virtualbox, LXC et compagnie. Et là c'est la douche froide.

Il fallait auparavant utiliser boot2docker (souvenir douloureux), ça avait le mérite de fonctionner, mais on s'arrêtait là. Manque de stabilité, perfs désastreuses.

Puis est arrivé Docker Desktop (for mac). Côté perfs, ce n'est toujours pas ça mais on a gagné en stabilité.

Pourquoi mon application PHP (Symfony, Drupal etc) avec Docker sous OSX est si lente ?

Le gros problème sous OSX avec docker, c'est la façon dont est gérée l'écriture disque et la synchronisation entre les données du container et le système hôte (osx).

Partant de ce constat, Eugen Meyer a créé Docker Sync.

Docker sync

Cet outil promet d'améliorer drastiquement les performances de votre application sous Docker. Une fois que tout est en place, c'est vrai que cela fonctionne comme convenu. C'est bien plus rapide. Mais il y a un mais !

Pour gagner en rapidité, il faut laisser docker sync... synchroniser. Et là c'est le drame. Le processeur en prend pour son grade. C'est violent, ça chauffe, pour peu que beaucoup de fichiers soient modifiés (c'est quand même le but), il faut attendre un certain temps que ça se mette à jour. Et comme il est gourmand, c'est a son tour de dégrader les performances d'osx cette fois.

Docker sync doit forcément être lancé avant vos containers et pour peu que d'autres personnes de l'équipe ne soit pas sous osx, il nous faut une configuration différente pour gérer docker sync sur notre projet. On est loin de la promesse de plateforme d'environnement uniformisée...

Enfin, dans le cas où on passe d'un projet à l'autre, il faut veiller a bien configurer le docker sync pour ne pas se marcher dessus entre les différents projets et surtout si vous avez besoin de reconstruire entièrement le projet, il faut alors vider docker sync et recommencer l'indexation (prenez un café, allez faire un tour, ou montrez-vous patient).

La solution : Les volumes

Docker sync a donc rapidement été abandonné. Une solution à base de VM virtualbox sous linux pour gérer notre docker à été testée. Les perfs étaient bien meilleures mais devoir lancer une machine virtuelle pour lancer un docker, c'est loin d'être optimal et ça risque vite de déraper en inception... Sans parler qu'avec Virtualbox, on a tendance à se prendre un beau BSOD sans prévenir...

Le top du top : jouer avec les volumes.

Au risque de se répéter, le problème c'est la synchronisation des fichiers entre le container et osx. Il est vrai que c'est bien plus simple de faire un gros volume et de synchroniser tous les fichiers, sauf que c'est là où docker et osx ne sont pas contents.

On utilise donc deux choses :

On segmente notre projet en différents volumes. On écarte ce qui est du code custom que l'on a besoin de modifier : notre code; de ce qui ne nous appartient pas et ne doit de toute façon pas être modifié : les vendors par exemple.
On utilise les options de montage de docker : cached, delegated, ro, rw.

Concernant le premier point, si vous faites du Symfony (ou du Drupal ou tout autre solution opensource), une partie du code de votre projet est issue de la communauté. Celui-ci bouge rarement, et s'il bouge, vous pouvez vous permettre d'avoir un temps de latence un peu plus important pour que votre container se mette a jour (on ne parle que d'une poignée de secondes). Toute ce code peut donc être monté dans un volume avec l'option cached voir mieux : delegated.

Pour votre code custom qui ne doit plus représenter grand chose par rapport au volume total du projet, vous pouvez alors le monter avec l'option cached.

Rien qu'avec cette configuration, vous allez remarquer une belle amélioration. Il est important de se rappeler que si des fichiers sont beaucoup modifiés mais ne sont pas du fait de votre développement, ils ne doivent pas être synchronisés directement sur votre hôte osx.

Les fichiers de cache / les fichiers "volatiles"

Que l'on soit sous Drupal ou Symfony, des fichiers de cache sont générés, ou des fichiers "données" son uploadés. Ces fichiers ne sont pas liés au développement de votre application et, sauf exception pour les fichiers uploadés suivant les cas, peuvent être perdus à tout moment sans impacter votre application. Inutile donc de s'embêter à les synchroniser, autant les laisser dans un volume de container interne à Docker.

Pas de synchronisation, utiliser le mécanisme interne de volumes de Docker

Même sous OSX, les volumes de Docker qui ne sont pas montés sur l'hôte n'ont pas ce problème de performances. Donc le mieux est de ne monter QUE ce qui vous est réellement nécessaire pour vos développements. Dans la partie précédente, nous avons parlé des fichiers générés. Ces fichiers n'ont aucune besoin d'être montés et sont générés en masse, donc autant les placer dans un volume non monté.

Le top du top serait de ne conserver que vos fichiers custom dans des volumes montés. Si vous n'avez pas besoin du code communautaire, inutile de vous embêter à le monter. Vous verrez la différence de performances.

L'exemple

Voici un fichier docker-compose.yml d'exemple commenté pour illustrer cet article dans le cas d'une configuration Drupal (issu de notre stack docker drupal) :

version: "3"

services:
php:
container_name: ${COMPOSE_PROJECT_NAME}_php
volumes:
# La partie web contient l'ensemble du code drupal de notre application. Il n'est pas utile
# de le synchroniser à la seconde car il n'y aura des modifications qu'à la mise à jour mais
# ces fichiers représentent un gros volume.
- ../../web:/var/www/html/web:rw,delegated
# Les paquets vendors n'ont pas besoin d'être synchronisé à la seconde car peu modifiés
# mais ils représentent un gros volume.
- ../../vendor:/var/www/html/vendor:rw,delegated
# On y stocke la configuration sous forme de fichiers. Beaucoup de fichiers générés que l'on
# souhaite versionner mais pas de nécessité de synchronisation immédiate.
- ../../config:/var/www/html/config:rw,delegated
# On monte ces fichiers par commodité pour pouvoir les modifier simplement et que leur modification
# soit prise en compte sans devoir copier un fichier ou relancer un container.
- ../conf/settings.php:/var/www/html/web/sites/default/settings.php:rw,delegated
- ../conf/settings.local.php:/var/www/html/web/sites/default/settings.local.php:rw,delegated
- ../conf/development.services.yml:/var/www/html/web/sites/development.services.yml:rw,delegated
- ../../composer.json:/var/www/html/composer.json:rw,delegated
- ../../composer.lock:/var/www/html/composer.lock:rw,delegated
- ./php/docker-php-upload.ini:/usr/local/etc/php/conf.d/docker-php-upload.ini
# Seuls ces trois répertoires représentent notre code custom et demandent plus de réactivité.
- ../../web/profiles/custom:/var/www/html/web/profiles/custom:rw,cached
- ../../web/modules/custom:/var/www/html/web/modules/custom:rw,cached
- ../../web/themes/custom:/var/www/html/web/themes/custom:rw,cached
# On ne synchronise pas les fichiers de cache et fichiers uploadés.
- drupal-files:/var/www/html/web/sites/default/files
depends_on:
- mysql

apache:
container_name: ${COMPOSE_PROJECT_NAME}_apache
volumes:
# Apache n'est pas censé écrire dans ce répertoire, on peut donc le passer en lecture seule.
- ../../:/var/www/html:ro,delegated
# On partage les fichiers avec le volume de fichier.
- drupal-files:/var/www/html/web/sites/default/files
depends_on:
- php

mysql:
container_name: ${COMPOSE_PROJECT_NAME}_mysql
build:
context: ./mysql
# # On ne monte surtout pas les volumes MYSQL pour des raisons de performances évidentes.
# volumes:
# - ./data/mysql:/var/lib/mysql:rw
# - ./entrypoint:/docker-entrypoint-initdb.d

volumes:
# Ce volume n'étant pas monté avec osx, il ne dégrade pas ses performances.
drupal-files:

 

Par lequipe.tech
L'Équipe.tech

Docker et OSX

Chez l'Équipe.tech, nous avons toujours travaillé sous OSX avec des Macbook Pro. Pendant de nombreuses années nous en étions très content. Plus simple pour le web que sous Microsoft Windows qui n'est pas adapté pour du développement PHP, plus propre et clé en main que Linux, et finition impeccable.

La majorité de notre expérience sur cet environnement s'est fait avant l'avènement de Docker, et surtout avant que les machines d'Apple ne soient compatibles avec Docker, quand ils n'utilisaient pas encore de processeurs Intel.

Lorsque nos machines (et leur processeurs) nous l'ont permis, nous nous sommes alors mis à Docker et ses promesses. Exit les Vagrant, Virtualbox, LXC et compagnie. Et là c'est la douche froide.

Il fallait auparavant utiliser boot2docker (souvenir douloureux), ça avait le mérite de fonctionner, mais on s'arrêtait là. Manque de stabilité, perfs désastreuses.

Puis est arrivé Docker Desktop (for mac). Côté perfs, ce n'est toujours pas ça mais on a gagné en stabilité.

Pourquoi mon application PHP (Symfony, Drupal etc) avec Docker sous OSX est si lente ?

Le gros problème sous OSX avec docker, c'est la façon dont est gérée l'écriture disque et la synchronisation entre les données du container et le système hôte (osx).

Partant de ce constat, Eugen Meyer a créé Docker Sync.

Docker sync

Cet outil promet d'améliorer drastiquement les performances de votre application sous Docker. Une fois que tout est en place, c'est vrai que cela fonctionne comme convenu. C'est bien plus rapide. Mais il y a un mais !

Pour gagner en rapidité, il faut laisser docker sync... synchroniser. Et là c'est le drame. Le processeur en prend pour son grade. C'est violent, ça chauffe, pour peu que beaucoup de fichiers soient modifiés (c'est quand même le but), il faut attendre un certain temps que ça se mette à jour. Et comme il est gourmand, c'est a son tour de dégrader les performances d'osx cette fois.

Docker sync doit forcément être lancé avant vos containers et pour peu que d'autres personnes de l'équipe ne soit pas sous osx, il nous faut une configuration différente pour gérer docker sync sur notre projet. On est loin de la promesse de plateforme d'environnement uniformisée...

Enfin, dans le cas où on passe d'un projet à l'autre, il faut veiller a bien configurer le docker sync pour ne pas se marcher dessus entre les différents projets et surtout si vous avez besoin de reconstruire entièrement le projet, il faut alors vider docker sync et recommencer l'indexation (prenez un café, allez faire un tour, ou montrez-vous patient).

La solution : Les volumes

Docker sync a donc rapidement été abandonné. Une solution à base de VM virtualbox sous linux pour gérer notre docker à été testée. Les perfs étaient bien meilleures mais devoir lancer une machine virtuelle pour lancer un docker, c'est loin d'être optimal et ça risque vite de déraper en inception... Sans parler qu'avec Virtualbox, on a tendance à se prendre un beau BSOD sans prévenir...

Le top du top : jouer avec les volumes.

Au risque de se répéter, le problème c'est la synchronisation des fichiers entre le container et osx. Il est vrai que c'est bien plus simple de faire un gros volume et de synchroniser tous les fichiers, sauf que c'est là où docker et osx ne sont pas contents.

On utilise donc deux choses :

On segmente notre projet en différents volumes. On écarte ce qui est du code custom que l'on a besoin de modifier : notre code; de ce qui ne nous appartient pas et ne doit de toute façon pas être modifié : les vendors par exemple.
On utilise les options de montage de docker : cached, delegated, ro, rw.

Concernant le premier point, si vous faites du Symfony (ou du Drupal ou tout autre solution opensource), une partie du code de votre projet est issue de la communauté. Celui-ci bouge rarement, et s'il bouge, vous pouvez vous permettre d'avoir un temps de latence un peu plus important pour que votre container se mette a jour (on ne parle que d'une poignée de secondes). Toute ce code peut donc être monté dans un volume avec l'option cached voir mieux : delegated.

Pour votre code custom qui ne doit plus représenter grand chose par rapport au volume total du projet, vous pouvez alors le monter avec l'option cached.

Rien qu'avec cette configuration, vous allez remarquer une belle amélioration. Il est important de se rappeler que si des fichiers sont beaucoup modifiés mais ne sont pas du fait de votre développement, ils ne doivent pas être synchronisés directement sur votre hôte osx.

Les fichiers de cache / les fichiers "volatiles"

Que l'on soit sous Drupal ou Symfony, des fichiers de cache sont générés, ou des fichiers "données" son uploadés. Ces fichiers ne sont pas liés au développement de votre application et, sauf exception pour les fichiers uploadés suivant les cas, peuvent être perdus à tout moment sans impacter votre application. Inutile donc de s'embêter à les synchroniser, autant les laisser dans un volume de container interne à Docker.

Pas de synchronisation, utiliser le mécanisme interne de volumes de Docker

Même sous OSX, les volumes de Docker qui ne sont pas montés sur l'hôte n'ont pas ce problème de performances. Donc le mieux est de ne monter QUE ce qui vous est réellement nécessaire pour vos développements. Dans la partie précédente, nous avons parlé des fichiers générés. Ces fichiers n'ont aucune besoin d'être montés et sont générés en masse, donc autant les placer dans un volume non monté.

Le top du top serait de ne conserver que vos fichiers custom dans des volumes montés. Si vous n'avez pas besoin du code communautaire, inutile de vous embêter à le monter. Vous verrez la différence de performances.

L'exemple

Voici un fichier docker-compose.yml d'exemple commenté pour illustrer cet article dans le cas d'une configuration Drupal (issu de notre stack docker drupal) :

version: "3"

services:
php:
container_name: ${COMPOSE_PROJECT_NAME}_php
volumes:
# La partie web contient l'ensemble du code drupal de notre application. Il n'est pas utile
# de le synchroniser à la seconde car il n'y aura des modifications qu'à la mise à jour mais
# ces fichiers représentent un gros volume.
- ../../web:/var/www/html/web:rw,delegated
# Les paquets vendors n'ont pas besoin d'être synchronisé à la seconde car peu modifiés
# mais ils représentent un gros volume.
- ../../vendor:/var/www/html/vendor:rw,delegated
# On y stocke la configuration sous forme de fichiers. Beaucoup de fichiers générés que l'on
# souhaite versionner mais pas de nécessité de synchronisation immédiate.
- ../../config:/var/www/html/config:rw,delegated
# On monte ces fichiers par commodité pour pouvoir les modifier simplement et que leur modification
# soit prise en compte sans devoir copier un fichier ou relancer un container.
- ../conf/settings.php:/var/www/html/web/sites/default/settings.php:rw,delegated
- ../conf/settings.local.php:/var/www/html/web/sites/default/settings.local.php:rw,delegated
- ../conf/development.services.yml:/var/www/html/web/sites/development.services.yml:rw,delegated
- ../../composer.json:/var/www/html/composer.json:rw,delegated
- ../../composer.lock:/var/www/html/composer.lock:rw,delegated
- ./php/docker-php-upload.ini:/usr/local/etc/php/conf.d/docker-php-upload.ini
# Seuls ces trois répertoires représentent notre code custom et demandent plus de réactivité.
- ../../web/profiles/custom:/var/www/html/web/profiles/custom:rw,cached
- ../../web/modules/custom:/var/www/html/web/modules/custom:rw,cached
- ../../web/themes/custom:/var/www/html/web/themes/custom:rw,cached
# On ne synchronise pas les fichiers de cache et fichiers uploadés.
- drupal-files:/var/www/html/web/sites/default/files
depends_on:
- mysql

apache:
container_name: ${COMPOSE_PROJECT_NAME}_apache
volumes:
# Apache n'est pas censé écrire dans ce répertoire, on peut donc le passer en lecture seule.
- ../../:/var/www/html:ro,delegated
# On partage les fichiers avec le volume de fichier.
- drupal-files:/var/www/html/web/sites/default/files
depends_on:
- php

mysql:
container_name: ${COMPOSE_PROJECT_NAME}_mysql
build:
context: ./mysql
# # On ne monte surtout pas les volumes MYSQL pour des raisons de performances évidentes.
# volumes:
# - ./data/mysql:/var/lib/mysql:rw
# - ./entrypoint:/docker-entrypoint-initdb.d

volumes:
# Ce volume n'étant pas monté avec osx, il ne dégrade pas ses performances.
drupal-files:

 

Par kgaut
Kevin Gautreau

Drupal 8 - ajouter du css ou du javascript à un module

Voici comment attacher une librairie javascript ou un fichier css à un module custom dans drupal 8.

Dans les extraits de code ci-dessous, le nom machine du module sera « shoutbox ».

Déclaration de la librairie

  1. #shoutbox.libraries.yml
  2.  
  3. # nom de la librairie
  4. shoutbox :
  5.   js:
  6. # chemin vers le fichier relatif au module
  7.   js/shoutbox.js: {}
  8.   css:
  9.   theme :
  10. # chemin vers le fichier relatif au module
  11.   css/administration.css : {}

Voici comment attacher cette librairies dans un bloc, un preprocess de template ou un controller

  1. // suivant l'endroit ooù l'on attache la librairie, cela peut être $build, $variables...
  2. // la partie avant le slash définie le nom du module qui défini la librairie
  3. // la partie après le slash est le nom de la librairie choisie dans le fichier shoutbox.libraries.yml
  4.  
  5. $variables['#attached']['library'][] = 'shoutbox/shoutbox';

 

Par kgaut
Kevin Gautreau

Drupal 8 - Surcharger la classe de contrôle d'accès d'un type d'entité

Sous drupal 8, les types d'entités, comme les noeuds, viennent avec leur classe pour gérer le contrôle d'accès (création / modification / visualisation / suppression).

Il est possible de surcharger ces classes pour personnaliser plus finement ce contrôle.

Nous allons ici surcharger le contrôle d'accès pour un type d'entité « shoutbox », mais c'est le même principe pour les nodes.

  1. # mon_module.module
  2. function mon_module_entity_type_alter(array &$entity_types) {
  3. $entity_types['shoutbox']->setHandlerClass('access', \Drupal\mon_module\Entity\AccessControlHandler\CustomShoutboxAccessControlHandler::class);
  4. // Note : si on avait voulu surcharger le controle d'accès aux noeuds :
  5. // $entity_types['node']->setHandlerClass('access', \Drupal\mon_module\Entity\AccessControlHandler\CustomNodeAccessControlHandler::class);
  6. }

La classe en elle même, qui étant la classe de contrôle d'accès de base (définie dans l'annotation de notre type d'entité)

  1. # mon_module/src/Entity/AccessControlHandler/CustomShoutboxAccessControlHandler.php
  2.  
  3. namespace Drupal\mon_module\Entity\AccessControlHandler;
  4.  
  5. use Drupal\Core\Access\AccessResult;
  6. use Drupal\Core\Entity\EntityInterface;
  7. use Drupal\Core\Session\AccountInterface;
  8. use Drupal\shoutbox\Entity\AccessControlHandler\ShoutboxAccessControlHandler;
  9. use Drupal\shoutbox\Entity\Shoutbox;
  10. use Drupal\user\Entity\User;
  11.  
  12. class CustomShoutboxAccessControlHandler extends ShoutboxAccessControlHandler {
  13.  
  14. protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
  15. /** @var Shoutbox $entity */
  16. if($operation === 'view' && $this->testPerso()) {
  17. if (!$entity->isPublished()) {
  18. return AccessResult::allowedIfHasPermission($account, 'administer shoutbox');
  19. }
  20. if ($this->autreTest()) {
  21. return AccessResult::allowed();
  22. }
  23. return AccessResult::forbidden('Shoutbox privée');
  24. }
  25. return parent::checkAccess($entity, $operation, $account);
  26. }
  27.  
  28. }

Ici je ne fais un contrôle d'accès que sur l'opération « view » pour la visualisation, je délègue tout le reste à la classe mère.

Par kgaut
Kevin Gautreau

Intégrer Slack à son site drupal 8

Nous allons voir comment envoyer des messages sur un slack depuis un site.

Évidement, vous devez pour cela être administrateur du slack ou bien avoir des jetons d'intégration.

Installation du module d'API

Commençons par télécharger et activer le module slack qui fera le pont entre notre site et l'API de slack

  1. composer require drupal/slack
  2. drush en slack

Configuration

Rendez-vous sur la page de configuration du module : /admin/config/services/slack/config

Il nous faudra ici une « Webhook URL », qui s'obtient sur votre slack, dans la section Apps : https://MONSLACK.slack.com/apps, dans le recherche tapez « webhook » et dans l'auto-complétion selectionnez « Incoming WebHooks » :

Slack Incoming WebHooks

Sur l'écran suivant cliquez sur le bouton « Add Configuration »

Slack - add configuration

Sélectionnez ensuite le canal où les messages devront être postés :

Slack - Selection chan

Récupérez ensuite l'adresse « webhook URL » en renseignez-la sur votre site, sur l'écran de configuration de Slack, vous pouvez renseigner le nom et l'avatar qui apparaîtra pour chaque message :

slack - config

On teste si tout fonctionne bien via l'onglet « send test message »

Slack Test

On vérifie dans le slack :

slack test

\o/

Voila le module est configuré, on peut maintenant utiliser rules pour déclencher des actions. Mais on peut aussi le faire depuis le code.

Un exemple tout simple (qui aurait pu être fait via rules) : envoyer un message slack à chaque commentaire sur le site, j'ai utilisé pour cela le hook_comment_insert avec le service slack.slack_service :

  1. function kgaut_comment_insert(\Drupal\comment\Entity\Comment $comment) {
  2. /** @var \Drupal\slack\Slack $slack */
  3. $slack = \Drupal::service('slack.slack_service');
  4.  
  5. $node = $comment->getCommentedEntity();
  6. $author = $comment->getAuthorName();
  7. $email = $comment->getAuthorEmail();
  8. $body = strip_tags($comment->get('comment_body')->value);
  9. $description = t('*@username* (@email) vient de poster un commentaire sur *@post_title* : _@message_. @comment_url', [
  10. '@username' => $author,
  11. '@message' => $body,
  12. '@email' => $email,
  13. '@post_title' => $node->label(),
  14. '@comment_url' => $comment->toUrl('canonical', ['absolute' => TRUE])->toString(),
  15. ]);
  16. $slack->sendMessage($description);
  17. }

Et hop !

samarsh !

 

Par kgaut
Kevin Gautreau

Drupal 8 - Utiliser les redirections de Redirect sur une page dépubliée

Dans le cas d'une page dé-publiée, si en tant qu'anonyme on tombe sur une erreur 403. On peut vouloir rediriger cette page temporairement vers une autre via le module redirect, mais nativement ça n'est pas pris en compte.

Voici un petit EventSubscriber qui répond sur les erreurs 403, qui teste si une redirection existe pour le nœud courant, et dans ce cas redirige l'utilisateur.

Note : Un administrateur ayant la permission pour voir le contenu dé-publié ne sera pas redirigé, car aucune erreur 403 ne sera lancée et donc l'event subscriber ne sera pas appelé.

Note 2 : C'est un bout de code qui semble fonctionnel, fonctionne avec le multilingue mais qui est certainement perfectible. N'hésitez-pas à me faire vos remarques.

1 - Déclaration de l'event subscriber :

  1. #mon_module.services.yml
  2.  
  3.   mon_module.redirector:
  4.   class: Drupal\mon_module\EventSubscriber\Redirector
  5.   tags:
  6.   - { name: event_subscriber }

2 - Définition de l'event subscriber 

  1. # web/modules/custom/mon_module/src/EventSubscriber/Redirector.php
  2.  
  3. namespace Drupal\mon_module\EventSubscriber;
  4.  
  5. use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
  6. use Drupal\redirect\RedirectRepository;
  7. use Drupal\node\Entity\Node;
  8. use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
  9. use Symfony\Component\HttpFoundation\RedirectResponse;
  10.  
  11. class Redirector extends HttpExceptionSubscriberBase {
  12.  
  13. /**
  14.   * {@inheritdoc}
  15.   */
  16. protected function getHandledFormats() {
  17. return ['html'];
  18. }
  19.  
  20. public function on403(GetResponseForExceptionEvent $event) {
  21. if ($event->getRequest()->attributes->get('node') !== NULL) {
  22. $nid = \Drupal::routeMatch()->getRawParameter('node');
  23. $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
  24. /** @var RedirectRepository $redirectRepository */
  25. $redirectRepository = \Drupal::service('redirect.repository');
  26. $node = Node::load($nid);
  27. if ($node !== NULL && $node->hasTranslation($langcode) && $translation = $node->getTranslation($langcode)) {
  28. if (!$translation->isPublished()) {
  29. $alias = \Drupal::service('path.alias_manager')->getAliasByPath('/node/' . $nid);
  30. $redirection = $redirectRepository->findMatchingRedirect($alias, [], $langcode);
  31. if($redirection) {
  32. $event->setResponse(new RedirectResponse($redirection->getRedirectUrl()->toString(), $redirection->getStatusCode()));
  33. }
  34. }
  35. }
  36. }
  37. }
  38.  
  39. }

 

Par kgaut
Kevin Gautreau

Drupal 8 - Surcharger la classe de formulaire d'un terme de taxonomie

Hier, nous avons vu comment surcharger le formulaire de création / modification d'un nœud, voici aujourd'hui comment faire la même chose mais pour un terme de taxonomie.

Cela se passe encore en deux étapes.

1 - Altération du type d'entité

  1. # mon_module.module
  2. function mon_module_entity_type_alter(array &$entity_types) {
  3. $entity_types['taxonomy_term']->setFormClass('default', Drupal\mon_module\Entity\Form\CustomTermForm::class);
  4. }

2 - Classe du formulaire

  1. # web/modules/mon_module/src/Entity/Form/CustomTermForm.php
  2.  
  3. namespace Drupal\mon_module\Entity\Form;
  4.  
  5. use Drupal\Core\Form\FormStateInterface;
  6. use Drupal\taxonomy\TermForm;
  7.  
  8. class CustomTermForm extends TermForm {
  9. public function form(array $form, FormStateInterface $form_state) {
  10. $form = parent::form($form, $form_state);
  11. /** @var \Drupal\taxonomy\Entity\Term $term */
  12. $term = $this->entity;
  13. if($term->getVocabularyId() === 'mon_vocabulaire') {
  14. // À vous de jouer
  15. }
  16. return $form;
  17. }
  18.  
  19. }

 

Par kgaut
Kevin Gautreau

Drupal 8 - Surcharger la classe de formulaire d'un nœud

Pour modifier le formulaire de création d'un nœud sous drupal 8, on peut utiliser le bon vieux HOOK_form_alter(), mais on peut aussi faire quelque chose de plus « propre » en altérant le type d'entité pour redéfinir son formulaire.

Cela se passe en deux étapes.

1 - Altération du type d'entité

  1. # mon_module.module
  2. function mon_module_entity_type_alter(array &$entity_types) {
  3. $entity_types['node']->setFormClass('default', \Drupal\mon_module\Entity\Form\NodeCustomForm::class);
  4. $entity_types['node']->setFormClass('edit', \Drupal\mon_module\Entity\Form\NodeCustomForm::class);
  5. }

2 - Classe du formulaire

  1. # web/modules/mon_module/src/Entity/Form/NodeCustomForm.php
  2.  
  3. namespace Drupal\mon_module\Entity\Form;
  4.  
  5. use Drupal\Core\Form\FormStateInterface;
  6. use Drupal\node\NodeForm;
  7.  
  8. class NodeCustomForm extends NodeForm {
  9.  
  10. public function form(array $form, FormStateInterface $form_state) {
  11. $form = parent::form($form, $form_state);
  12. // Faite votre magie ici
  13. /** @var \Drupal\node\Entity\Node $node */
  14. $node = $this->entity;
  15. return $form;
  16. }
  17.  
  18. }

Cette classe étant la classe normale, nous avons donc juste à appliquer nos modifications à l'intérieur.

Le problème de cette solution : on ne peut pas avoir deux modules qui surchargent la classe, à moins d'étendre la première dans la seconde.

Par GoZ
Adhérent
Fabien CLEMENT

Ajouter un formulaire à une entité existante

Ajouter un formulaire à une entité existante

Problématique

Dans notre Drupal, nous avons une entité composée de plusieurs champs mais ne souhaitons pas qu'ils soient tous renseignés via le même formulaire ? 2 solutions s'offrent à nous :

GoZ
lun 24/06/2019 - 13:44

Pages