Custom Poll module - part 5 - Finalisation

Posté le: dim 31/03/2019 - 09:27 Par: rcowebdev

On met un peu au propre tout ca

  • Ajouter des contraintes d’intégrité sur les tables crées

  • Modifier les permissions douteuses attribuées à la sauvegarde d’un vote

  • Ajouter une interface pour le poll manager

  • Corriger le breadcrumb du BO qui se comporte “bizarrement”

Alors pour ajouter les contraintes sur les tables, on ouvre notre fichier d’installation

 

poll.install

 

et on va jouer avec les commandes

drush pm-uninstall -y poll

drush pm-enable -y poll

Hopopopop, on s’arrête tout de suite ! Dans le schema d’installation, je m’attendais à rajouter juste mes clés étrangères

    'foreign keys' => [
      'poll_answer' => [
        'table' => 'poll_answer',
        'columns' => [
          'id' => 'answer_id', 
        ]
      ],
    ], 
...

Mais la doc Drupal précise pour la la clé 'foreign keys'

  // For documentation purposes only; foreign keys are not created in the
  // database.

Bha, ca ne m’arrange pas du tout ca et pourquoi ne pas les créer en BDD lors de l’installation ? mh.

Les contraintes sont les suivantes :

ALTER TABLE poll_question_answer ADD CONSTRAINT fk_question_answer_answer FOREIGN KEY (answer_id) REFERENCES poll_answer(id);

ALTER TABLE poll_question_answer ADD CONSTRAINT fk_question_answer_question FOREIGN KEY (question_id) REFERENCES poll_question(id);

ALTER TABLE poll_result ADD CONSTRAINT fk_result_answer FOREIGN KEY (answer_id) REFERENCES poll_answer(id);
ALTER TABLE poll_result ADD CONSTRAINT fk_result_question FOREIGN KEY (question_id) REFERENCES poll_question(id);

Je trouve ca vraiment bizarre, je vais regarder dans les modules du core pour voir comment ils font…

Few minutes later, ils ne le font pas. J’ai regardé la description de quelques tables, rien, puis je sors

select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where CONSTRAINT_TYPE = 'FOREIGN KEY';

Aucun résultat. Pas trop étonnant que ce soit si facile de casser une BDD Drupal, je suis vraiment déçu, j’espère que ce sera mieux gérer dans Drupal 9 parce que là ca craint !

 

On passe à la modification des permissions douteuses attribuées à la sauvegarde d’un vote, oui parce qu’à force de copier/coller des configurations qui se ressemblent, fatalement, il peut y avoir un raté.

 

Puisque Drupal 8 (et je crois que c’est depuis la première version) propose un overlay BO/FO - je n’ai jamais trop compris pourquoi, cool pour les contributeurs je suppose mais alors pour les développeurs (…) - du coup quand je testais le module Poll j’avais les droits administrateur et ca fonctionnait mais en navigation privée j’ai déchanté...

 

Le fichier qui nous intéresse est

 

poll.routing.yml

 

Et le noeud poll.result.save

poll.result.save:
 path: '/poll_result/save/{question_id}/{answer_id}'
 defaults:
  _controller: '\Drupal\poll\Controller\ResultController::save'
  _title: 'Poll result save'
 requirements:
  _permission: 'administer poll'

A remplacer par

poll.result.save:
 path: '/poll_result/save/{question_id}/{answer_id}'
 defaults:
  _controller: '\Drupal\poll\Controller\ResultController::save'
  _title: 'Poll result save'
 requirements:
  _access: 'TRUE'

Ajouter une interface pour le poll manager, ca va être rapide. Il faut créer un fichier PollManagerInterface.php qui a cette tête là

 

src/PollManagerInterface.php

<?php

namespace Drupal\Poll;

interface PollManagerInterface {
  /** 
   * Get poll.
   *
   * @param int $id
   *
   * @return array
   */
  public function getPoll($id);

   /**
   * @param int $questionId
   * @param int $answerId
   *
   * @return array
   */
  public function isAvailable($questionId, $answerId);

  /**
   * @param int     $questionId
   * @param varchar $clientIp
   *
   * @return array
   */
  public function hasPolled($questionId, $clientIp);

  /**
   * @return array
   */
  public function getQuestions();

  /**
   * @param int     $questionId
   * @param int     $answerId
   * @param varchar $clientIp
   *
   * @return void
   */
  public function saveResult($questionId, $answerId, $clientIp);
}

Et on implémente cette interface dans la classe

 

src/PollManager.php

/**
 * Poll manager
 */
class PollManager implements PollManagerInterface {

...

On s’attaque à la correction du Breadcrumb pour le BO, on commence par créer un nouveau dossier

 

src/Breadcrumb

 

et on y place

 

src/Breadcrumb/PollBreadcrumbBuilder.php

<?php

namespace Drupal\poll\Breadcrumb;
 
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Link ;
 
class PollBreadcrumbBuilder implements BreadcrumbBuilderInterface {

	/**
	* {@inheritdoc}
	*/
	public function applies(RouteMatchInterface $attributes) {
		return strrpos($attributes->getRouteName(), 'poll') === 0;
	}
 
	/**
	* {@inheritdoc}
	*/
	public function build(RouteMatchInterface $route_match) {

		$breadcrumb = new Breadcrumb();
		$breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
		$breadcrumb->addLink(Link::createFromRoute('Poll', 'poll.question.overview'));

		switch ( $route_match->getRouteName() ) {
			case 'poll.answer.edit':
			case 'poll.answer.delete':
				$breadcrumb->addLink(Link::createFromRoute('Poll Answers', 'poll.answer.overview'));
			break;
			case 'poll.result.view':
				$breadcrumb->addLink(Link::createFromRoute('Poll Results', 'poll.result.overview'));
			break;
		}

		$breadcrumb->addCacheContexts(['route']);

		return $breadcrumb;
	}
}

La méthode applies retourne un booléen, en gros, selon le contexte (route), est ce que j’applique ou pas cette surcharge de Breadcrumb ? si non, le programme continuera sa vie sans se soucier de notre BreadcrumbBuilder, si oui, on passe par la méthode build pour construire notre Breadcrumb à la mano.

 

On déclare notre service à Drupal via

 

poll.services.yml

services:
  ...
  poll.breadcrumb:
   class: Drupal\poll\Breadcrumb\PollBreadcrumbBuilder
   tags:
     - { name: breadcrumb_builder, priority: 100 }

Pour pérenniser tout ca, il faut y ajouter des tests afin d’éviter les mauvaises surprises mais ce sera l’objet d’un prochain article voir dossier parce qu’il y a pas mal de chose à dire et à faire. On passe à la Conclusion de ce premier - vrai - échange avec Drupal 8

Mots clés
Drupal 8
Créer un module Drupal 8
Dossier