1: <?php
2: namespace TIC\CoreBundle\Form\DataTransformer;
3:
4: use Symfony\Component\Form\DataTransformerInterface;
5: use Symfony\Component\Form\Exception\TransformationFailedException;
6:
7: /**
8: * Transforms between a list of values (simple array) and a string (concatenation).
9: *
10: * Example: edit a multi-valued field with a simple textfield (with ", ") or textarea (with "\n") form
11: */
12: class ListToStringTransformer implements DataTransformerInterface
13: {
14: protected $sep = ','; /** separator for split (ex: "," "\n" "|") */
15: protected $glue = null; /** separator for join (ex: ", " "\r\n" "|") */
16: protected $trim = " \n\r\t\v\x00"; /** characters to clean with trim on values (or null to desactivate) */
17: protected $skip = false; /** keep or skip items with empty value (null or "") */
18:
19: /**
20: * Construct the data transformer with parameters (separator, glue, trim & skip options).
21: *
22: * @param string $sep Separator for split (default ",")
23: * @param string $glue Separator for join (default according to $sep, ex: ", " for ",")
24: * @param bool $trim If false, disable the trim on each values
25: * @param bool $skip If true, skip items with empty value (null or "")
26: */
27: public function __construct(string $sep = null, string $glue = null, bool $trim = true, bool $skip = false)
28: {
29: if ($sep !== null) $this->sep = $sep;
30: if ($glue !== null) $this->glue = $glue;
31: else switch ($this->sep) {
32: case "," : $this->glue = ", "; break;
33: case "\n" : $this->glue = "\r\n"; break;
34: default : $this->glue = $this->sep; break;
35: }
36: if ($trim === false) $this->trim = null;
37: if ($skip !== null) $this->skip = $skip;
38: }
39:
40: /**
41: * Transforms an array into string.
42: *
43: * @param array $array List of values
44: * @return string All values into one string
45: * @throws TransformationFailedException If the given value is not an array.
46: */
47: public function transform(mixed $values): ?string
48: {
49: if ($values === null) return null;
50: # if (\is_string($values)) return $values;
51: if (! \is_array($values)) throw new TransformationFailedException("Expected an array.");
52:
53: return \implode($this->glue, \array_map(function($v){
54: if ($v === null) return '';
55: // vérification que chaque élément de la liste soit bien un simple scalaire concaténable
56: if (! \is_scalar($v)) throw new TransformationFailedException("Expected a simple array (list of scalars): ".\print_r($v,true));
57: // remplacement des éventuels séparateurs dans la valeur
58: $v = \str_replace($this->sep, '', $v);
59: // nettoyage des blancs et remplacement des éventuels séparateurs dans la valeur
60: return ($this->trim === null) ? $v : \trim($v, $this->trim);
61: }, $values));
62: }
63:
64: /**
65: * Transforms a string into an array.
66: *
67: * @param string $values All values into one string
68: * @return array Array of values
69: * @throws TransformationFailedException If the given value is not a string.
70: */
71: public function reverseTransform(mixed $values): ?array
72: {
73: if ($values === null) return null;
74: # if (\is_array($values)) return $values;
75: if (! \is_string($values)) throw new TransformationFailedException("Expected a string.");
76:
77: return array_map(function($v){
78: if ($v === '') return null;
79: return ($this->trim === null) ? $v : \trim($v, $this->trim);
80: }, \explode($this->sep, $values));
81: }
82:
83: }
84: