1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5use dokuwiki\plugin\struct\types\AbstractBaseType; 6 7/** 8 * Validator to validate a single value 9 */ 10class ValueValidator 11{ 12 /** @var \helper_plugin_struct_db */ 13 protected $hlp; 14 15 /** @var array list of validation errors */ 16 protected $errors = []; 17 18 /** 19 * ValueValidator constructor. 20 */ 21 public function __construct() 22 { 23 $this->hlp = plugin_load('helper', 'struct_db'); 24 } 25 26 /** 27 * Validate a single value 28 * 29 * @param Column $col the column of that value 30 * @param mixed &$rawvalue the value, will be fixed according to the type 31 * @return bool 32 */ 33 public function validateValue(Column $col, &$rawvalue) 34 { 35 if ($rawvalue === null) $rawvalue = ''; // no data was passed 36 37 // fix multi value types 38 $type = $col->getType(); 39 $trans = $type->getTranslatedLabel(); 40 if ($type->isMulti() && !is_array($rawvalue)) { 41 $rawvalue = $type->splitValues($rawvalue); 42 } 43 // strip empty fields from multi vals 44 // but keep at least one so we can properly delete multivalues on update 45 // some fields like media or date can post an array with multiple empty strings 46 // because they use multiple inputs instead of comma separation in one input 47 if (is_array($rawvalue)) { 48 $rawvalue = array_filter($rawvalue, [$this, 'filter']); 49 $rawvalue = array_values($rawvalue); // reset the array keys 50 if ($rawvalue === []) { 51 $rawvalue = ['']; 52 } 53 } 54 55 // validate data 56 return $this->validateField($type, $trans, $rawvalue); 57 } 58 59 /** 60 * The errors that occured during validation 61 * 62 * @return string[] already translated error messages 63 */ 64 public function getErrors() 65 { 66 return $this->errors; 67 } 68 69 /** 70 * Validate the given data for a single field 71 * 72 * Catches the Validation exceptions and transforms them into proper error messages. 73 * 74 * Blank values are not validated and always pass 75 * 76 * @param AbstractBaseType $type 77 * @param string $label 78 * @param array|string|int &$data may be modified by the validation function 79 * @return bool true if the data validates, otherwise false 80 */ 81 protected function validateField(AbstractBaseType $type, $label, &$data) 82 { 83 $prefix = sprintf($this->hlp->getLang('validation_prefix'), $label); 84 85 $ok = true; 86 if (is_array($data)) { 87 foreach ($data as &$value) { 88 if (!blank($value)) { 89 try { 90 $value = $type->validate($value); 91 } catch (ValidationException $e) { 92 $this->errors[] = $prefix . $e->getMessage(); 93 $ok = false; 94 } 95 } 96 } 97 return $ok; 98 } 99 100 if (!blank($data)) { 101 try { 102 $data = $type->validate($data); 103 } catch (ValidationException $e) { 104 $this->errors[] = $prefix . $e->getMessage(); 105 $ok = false; 106 } 107 } 108 return $ok; 109 } 110 111 /** 112 * Simple filter to remove blank values 113 * 114 * @param string $val 115 * @return bool 116 */ 117 public function filter($val) 118 { 119 return !blank($val); 120 } 121} 122