1<?php 2 3 4namespace ComboStrap\Meta\Api; 5 6 7use ComboStrap\DataType; 8use ComboStrap\ExceptionBadArgument; 9use ComboStrap\ExceptionCompile; 10use ComboStrap\ExceptionNotFound; 11use ComboStrap\LogUtility; 12 13/** 14 * @package ComboStrap 15 * A list of value metadata 16 * * Multiple select if the possible values are set 17 * * Text with a {@link MetadataMultiple::getStringSeparator() separator} 18 * Ie: 19 * * keyword1, keyword2 20 * * usage1, usage2, ... 21 * 22 * By default, the data type is text, if number, the implementation should overwrite the {@link MetadataMultiple::getDataType()} 23 */ 24abstract class MetadataMultiple extends Metadata 25{ 26 27 /** 28 * @var array|null 29 */ 30 protected ?array $array = null; 31 32 33 /** 34 * @param null|array $value 35 * @return Metadata 36 * @throws ExceptionCompile 37 */ 38 public function setValue($value): Metadata 39 { 40 if ($value === null) { 41 $this->array = $value; 42 return $this; 43 } 44 if (!is_array($value)) { 45 throw new ExceptionCompile("The value is not an array. Value: " . var_export($value, true)); 46 } 47 $this->array = $value; 48 return $this; 49 } 50 51 static public function getDataType(): string 52 { 53 return DataType::TEXT_TYPE_VALUE; 54 } 55 56 public function getValue(): array 57 { 58 $this->buildCheck(); 59 if ($this->array === null) { 60 throw new ExceptionNotFound("No multiple values was found"); 61 } 62 return $this->array; 63 } 64 65 public function getDefaultValue() 66 { 67 throw new ExceptionNotFound("No default multiples value"); 68 } 69 70 /** 71 * @throws ExceptionNotFound 72 */ 73 public function getValueOrDefaults(): array 74 { 75 try { 76 return $this->getValue(); 77 } catch (ExceptionNotFound $e) { 78 return $this->getDefaultValue(); 79 } 80 } 81 82 83 public function valueIsNotNull(): bool 84 { 85 return $this->array !== null; 86 } 87 88 public function toStoreValue() 89 { 90 $this->buildCheck(); 91 if ($this->array === null) { 92 return null; 93 } 94 return implode($this->getStringSeparator(), $this->array); 95 } 96 97 public function toStoreDefaultValue() 98 { 99 try { 100 $defaultValue = $this->getDefaultValue(); 101 } catch (ExceptionNotFound $e) { 102 return null; 103 } 104 return implode($this->getStringSeparator(), $defaultValue); 105 } 106 107 108 /** 109 * @return string - the separator used when we receive or store/send an element 110 */ 111 function getStringSeparator(): string 112 { 113 return ","; 114 } 115 116 /** 117 * @throws ExceptionBadArgument 118 */ 119 public function setFromStoreValue($value): Metadata 120 { 121 $values = $this->toArrayOrNull($value); 122 if ($values === null) { 123 return $this; 124 } 125 $possibleValues = $this->getPossibleValues(); 126 if ($possibleValues !== null) { 127 foreach ($values as $value) { 128 if (!in_array($value, $possibleValues)) { 129 throw new ExceptionBadArgument("The value ($value) for ($this) is not a possible value (" . implode(",", $possibleValues) . ")", $this->getCanonical()); 130 } 131 } 132 } 133 $this->array = $values; 134 return $this; 135 } 136 137 /** 138 * @throws ExceptionBadArgument 139 */ 140 protected function toArrayOrNull($value): ?array 141 { 142 /** 143 * Empty String is the default for HTML form 144 */ 145 if ($value === null || $value === "") { 146 return null; 147 } 148 149 /** 150 * Array 151 */ 152 if (is_array($value)) { 153 return $value; 154 } 155 156 /** 157 * String 158 */ 159 if (!is_string($value)) { 160 throw new ExceptionBadArgument("The value for $this is not an array, nor a string (value: $value)", get_class($this)); 161 } 162 $stringSeparator = $this->getStringSeparator(); 163 return explode($stringSeparator, $value); 164 165 } 166 167 168 public function setFromStoreValueWithoutException($value): Metadata 169 { 170 try { 171 $this->array = $this->toArrayOrNull($value); 172 } catch (ExceptionCompile $e) { 173 LogUtility::msg($e->getMessage(), $e->getCanonical()); 174 } 175 return $this; 176 177 } 178} 179