Liste d'utilisateurs séparés par des virgules

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J'ai un formulaire dans lequel j'aimerais bien avoir un champ texte tout simple dans lequel l'utilisateur peut entrer une liste d'utilisateurs séparés par des virgules (et où on s'en fout des espaces). Ce sera les destinataires d'un message privé. P.ex. "Alice, Bob, Cedric, David"

Comment est-ce que je peux faire ça ?

Je pourrais utiliser un simple TextFieldType, mais alors ensuite comment faire pour la validation (vérifier que tous les utilisateurs saisis existent) ? Pour faire la validation, je pourrais ajouter une méthode avec une assertion IsTrue dans ma classe. Mais je n'ai pas accès à Doctrine dans cette classe et ce n'est probablement pas très réglo d'en passer une instance depuis le contrôleur (une entité avec une référence à doctrine ? assez moche non ? Le repository ? pas beaucoup mieux, si ?) ET faire une validation à la mano dans le contrôleur après la validation Symfony, c'est aussi assez bof…

D'un autre côté, FOSUserBundle est fourni avec un UserType qu'on peut utiliser pour entrer un simple utilisateur. Je pourrais faire un tableau de cet UserType en utilisant un CollectionType. C'est sûrement une meilleure voie. Mais du coup ça va m'afficher autant de zones de texte qu'il n'y a d'utilisateur et je ne vois vraiment pas comment je pourrais aller contre ça. Il y a peut-être moyen de bidouiller un template quelque part, mais par quel moyen faire un preg_split de la chaîne saisie pour la transformer en tableau de chaînes et ensuite en tableau d'instances après ?

Voilà où mes réflexions ont abouti pour le moment, malheureusement ce n'est pas grand chose. J'imagine que je vais devoir me résoudre à ne pas implémenter cette fonction.

Merci pour vos réponses.

+0 -0

Salut !

Dans ce que tu nous racontes, j'entrevois deux pistes :

  • utiliser un système JavaScript dans le genre de select2 (avantage : tu ne peux avoir dans cette liste que des utilisateurs existants) ;
  • créer un type personnalisé avec un DataTransformer adapté pour récupérer une collection d'utilisateurs depuis une "liste CSV", quitte à te baser ou intégrer le DataTransformer de FOSUserBunle (du coup, ça reste un bête champ texte, ou au moins en hérite).
+0 -0

Ah, grâce au mot-clé DataTransformer qui me manquait, j'ai trouvé ça: http://symfony.com/doc/current/cookbook/form/data_transformers.html Merci !

J'ai réussi à faire que ça fonctionne… presque; j'ai un dernier petit problème.

IL se trouve qu'il y a aussi des contraintes de validation dans la classe User, et que j'ai certains utilisateurs invalides vis-à-vis de ces contraintes qui existent dans la base de données. Quand je choisis un destinataire de MP qui existe mais qui est invalide vis-à-vis de ces contraintes propres à l'utilisateur, Symfony me remonte toutes ces erreurs et je me retrouve, par exemple, avec un pavé de messages d'erreur genre « cet e-mail est invalide », « Vous devez choisir un des choix proposés », etc. pour des champs qui ne sont pas, et qui n'ont pas à être dans le formulaire d'envoi de MP.

Alors question, comment faire pour que quand j'envoie un MP, seule l'existance des utilisateurs saisis soit vérifiée, et non pas toutes ses contraintes internes ?

Voici le code que je pense utile, et qui est aussi la solution à ma question initiale :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?php
// La construction du formulaire
$builder
->add('dests', SimpleUserListType::class, array('label'=>'Recipients'))
->add('title', TextType::class, array('label'=>'Title'))
->add('text', TextareaType::class, array('label'=>'Message'))
->add('submit', SubmitType::class, array('label'=>('Post')));

//Mon type personnalisé permettant de saisir une liste d'utilisateurs séparés par des virgules, construit grâce au tutoriel mis en lien ci-dessus
class SimpleUserListType extends AbstractType { 
    private $repo;

    public function __construct($doctrine)      { 
$this->repo = $doctrine->getRepository('AppBundle:User');
    } 

    public function buildForm(FormBuilderInterface $builder, array $options)      { 
        $builder->addModelTransformer(new SimpleUserListDataTransformer($this->repo)); 
    } 

    public function configureOptions(OptionsResolver $resolver)      { 
        $resolver->setDefaults(array( 
            'invalid_message' => 'InvalidUserList', 
        )); 
    } 

    public function getParent()      { 
        return TextType::class; 
    }
}


//Mon DataTransformer, construit grâce au tutoriel mis en lien ci-dessus
class SimpleUserListDataTransformer implements DataTransformerInterface { 
    private $repo; 

    public function __construct($repo)      { 
$this->repo = $repo;
    } 

    public function transform($userList)      { 
if ($userList===null) return '';
$a = array();
foreach($userList as $u) $a[]=$u->getUsername();
return implode(', ', $a);
    } 

    public function reverseTransform($str)      { 
$str = trim($str);
if (!$str || $str==='') return null;
$a = preg_split('/[^-a-zA-Z_0-9]+/', $str, -1, PREG_SPLIT_NO_EMPTY);
$users = $this->repo->findByUsername($a);
if (count($users) != count($a))            throw new TransformationFailedException("One or more of the specified users don't exist"); 
return $users;
    }
}

J'ai essayé @Assert\Valid(traverse=false) sur le champ dests de la data_class, mais ça ne change rien…

Merci.

+0 -0

C'est un peu trop pointu pour moi, mais je me demande si tu ne pourrais pas jouer avec les groupes de validation…

C'est effectivement avec les groupes de validation que j'ai contourné le problème, je ne sais pas si c'est la solution ultime. Mais si le groupe Default n'est pas utilisé, alors les sous-entités ne sont pas vérifiées.

Sujet résolu donc.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte