Source of file ZenValidatorConstraint.php
Size: 40,767 Bytes - Last Modified: 2021-12-23T10:20:27+00:00
/var/www/docs.ssmods.com/process/src/code/ZenValidatorConstraint.php
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366 | <?php use SilverStripe\Forms\FormField; use SilverStripe\Core\Injector\Injectable; use SilverStripe\Assets\File; use SilverStripe\View\Requirements; use SilverStripe\i18n\i18n; use SilverStripe\Forms\CheckboxSetField; use SilverStripe\Control\Controller; use SilverStripe\Control\Director; /** * @package ZenValidator * @license BSD License http://www.silverstripe.org/bsd-license * @author <shea@silverstripe.com.au> **/ abstract class ZenValidatorConstraint { use Injectable; /** * @var FormField */ protected $field; /** * @var string */ protected $customMessage; /** * @var boolean */ protected $parsleyApplied; /** * **/ public function __construct() { // } /** * Set the field this constraint is applied to * @param FormField $field * @return this **/ public function setField(FormField $field) { $this->field = $field; return $this; } /** * @return FormField */ public function getField() { return $this->field; } /** * Set a custom message for this constraint * @param string $message * @return this **/ public function setMessage($message) { $this->customMessage = $message; return $this; } /** * Get's the message that was set on the constrctor or falls back to default * @return string **/ public function getMessage() { return $this->customMessage ? $this->customMessage : $this->getDefaultMessage(); } /** * Load extra validator * @param string $name **/ public function loadExtra($name) { $useCurrent = ZenValidator::config()->use_current; $parsleyFolder = 'parsley'; if ($useCurrent) { $parsleyFolder = 'parsley_current'; } Requirements::javascript("sheadawson/silverstripe-zenvalidator:javascript/$parsleyFolder/extra/validator/$name.js", ['defer' => true]); $lang = i18n::get_lang_from_locale(i18n::get_locale()); Requirements::javascript("sheadawson/silverstripe-zenvalidator:javascript/$parsleyFolder/i18n/$lang.extra.js", ['defer' => true]); } /** * Return the default message for this constraint * @return string **/ abstract public function getDefaultMessage(); /** * Sets the html attributes required for frontend validation * Subclasses should call parent::applyParsley * @return void **/ public function applyParsley() { if (!$this->field) { throw new Exception("A constrained Field does not exist on the FieldSet, check you have the right field name for your ZenValidatorConstraint."); } $this->parsleyApplied = true; if ($this->customMessage) { $this->field->setAttribute(sprintf('data-parsley-%s-message', $this->getConstraintName()), $this->customMessage); } // CheckboxSetField might not have a unique name, so set parsley-multiple attribute if (get_class($this->field) === CheckboxSetField::class) { $this->field->setAttribute('data-parsley-multiple', $this->field->getName()); } } /** * Removes the html attributes required for frontend validation * Subclasses should call parent::removeParsley * @return void **/ public function removeParsley() { $this->parsleyApplied = false; if ($this->field && $this->customMessage) { $this->field->setAttribute(sprintf('data-parsley-%s-message', $this->getConstraintName()), ''); } if (get_class($this->field) === CheckboxSetField::class) { $this->field->setAttribute('data-parsley-multiple', ''); } } /** * Performs php validation on the value * @param $value * @return bool **/ abstract public function validate($value); /** * Gets the name of this constraint from it's classname which should correspond * to the string that parsley uses to identify a constraint type * @return string **/ public function getConstraintName() { return str_replace('Constraint_', '', get_called_class()); } } /** * Constraint_required * Basic required field form validation **/ class Constraint_required extends ZenValidatorConstraint { public function applyParsley() { parent::applyParsley(); $this->field->setAttribute('data-parsley-required', 'true'); $this->field->addExtraClass('required'); } public function removeParsley() { parent::removeParsley(); $this->field->setAttribute('data-parsley-required', 'false'); $this->field->removeExtraClass('required'); } public function validate($value) { return $value != ''; } public function getDefaultMessage() { return _t('ZenValidator.REQUIRED', 'This field is required'); } } /** * Constraint_length * Constrain a field value to be a of a min length, max length or between a range * * @example Constraint_length::create('min', 5); // minimum length of 5 characters * @example Constraint_length::create('max', 5); // maximum length of 5 characters * @example Constraint_length::create('range', 5, 10); // length between 5 and 10 characters **/ class Constraint_length extends ZenValidatorConstraint { const MIN = 'min'; const MAX = 'max'; const RANGE = 'range'; /** * @var string **/ protected $type; /** * @var int **/ protected $val1, $val2; /** * @param string $type (min,max,range) * @param int $val1 * @param int $val2 **/ public function __construct($type, $val1, $val2 = null) { $this->type = $type; $this->val1 = (int) $val1; $this->val2 = (int) $val2; parent::__construct(); } public function applyParsley() { parent::applyParsley(); switch ($this->type) { case 'min': $this->field->setAttribute('data-parsley-minlength', $this->val1); break; case 'max': $this->field->setAttribute('data-parsley-maxlength', $this->val1); break; case 'range': $this->field->setAttribute('data-parsley-length', sprintf("[%s,%s]", $this->val1, $this->val2)); break; } } public function getConstraintName() { return $this->type; } public function removeParsley() { parent::removeParsley(); switch ($this->type) { case 'min': $this->field->setAttribute('data-parsley-minlength', ''); break; case 'max': $this->field->setAttribute('data-parsley-maxlength', ''); break; case 'range': $this->field->setAttribute('data-parsley-length', ''); break; } } public function validate($value) { if (!$value) { return true; } if (function_exists('mb_strlen')) { $len = mb_strlen(trim($value)); } else { $len = strlen(trim($value)); } switch ($this->type) { case 'min': return $len >= $this->val1; case 'max': return $len <= $this->val1; case 'range': return $len >= $this->val1 && $len <= $this->val2; } } public function getDefaultMessage() { switch ($this->type) { case 'min': return sprintf(_t('ZenValidator.MINLENGTH', 'This value is too short. It should have %s characters or more'), $this->val1); case 'max': return sprintf(_t('ZenValidator.MAXLENGTH', 'This value is too long. It should have %s characters or less'), $this->val1); case 'range': return sprintf(_t('ZenValidator.RANGELENGTH', 'This value length is invalid. It should be between %s and %s characters long'), $this->val1, $this->val2); } } } /** * Constraint_check * Constrain CheckBoxSetField to have a minimum or maximum number of elements checked * * @example Constraint_length::create('min', 5); // minimum of 5 elements checked * @example Constraint_length::create('max', 5); // maximum of 5 elements checked * @example Constraint_length::create('range', 5, 10); // between 5 and 10 elements checked **/ class Constraint_check extends ZenValidatorConstraint { const MIN = 'min'; const MAX = 'max'; const RANGE = 'range'; /** * @var string **/ protected $type; /** * @var int **/ protected $val1, $val2; /** * @param string $type (min,max,check) * @param int $val1 * @param int $val2 **/ public function __construct($type, $val1, $val2 = null) { $this->type = $type; $this->val1 = (int) $val1; $this->val2 = (int) $val2; parent::__construct(); } public function applyParsley() { parent::applyParsley(); if (!$this->field instanceof CheckboxSetField) { throw new Exception("Constraint_check expects a CheckboxSetField, not a " . get_class($this->field)); } switch ($this->type) { case 'min': $this->field->setAttribute('data-parsley-mincheck', $this->val1); break; case 'max': $this->field->setAttribute('data-parsley-maxcheck', $this->val1); break; case 'range': $this->field->setAttribute('data-parsley-check', sprintf("[%s,%s]", $this->val1, $this->val2)); break; } } public function getConstraintName() { return $this->type; } public function removeParsley() { parent::removeParsley(); switch ($this->type) { case 'min': $this->field->setAttribute('data-parsley-mincheck', ''); break; case 'max': $this->field->setAttribute('data-parsley-maxcheck', ''); break; case 'range': $this->field->setAttribute('data-parsley-check', ''); break; } } public function validate($value) { $array = array_filter(explode(',', $value)); if (empty($array)) { return; //you should use required instead } switch ($this->type) { case 'min': return count($array) >= $this->val1; case 'max': return count($array) <= $this->val1; case 'range': return count($array) >= $this->val1 && count($array) <= $this->val2; } } public function getDefaultMessage() { switch ($this->type) { case 'min': return sprintf(_t('ZenValidator.MINCHECK', 'You must select at least %s choices'), $this->val1); case 'max': return sprintf(_t('ZenValidator.MAXCHECK', 'You must select %s choices or fewer'), $this->val1); case 'range': return sprintf(_t('ZenValidator.RANGECHECK', 'You must select between %s and %s choices'), $this->val1, $this->val2); } } } /** * Constraint_value * Constrain a field value to be a of a min value, max value or between a range * * @example Constraint_value::create('min', 5); // minimum value of 5 * @example Constraint_value::create('max', 5); // maximum value of 5 * @example Constraint_value::create('range', 5, 10); // value between 5 and 10 characters **/ class Constraint_value extends ZenValidatorConstraint { const MIN = 'min'; const MAX = 'max'; const RANGE = 'range'; /** * @var string **/ protected $type; /** * @var int **/ protected $val1, $val2; /** * @param srting $type (min,max,range) * @param int $val1 * @param int $val2 **/ public function __construct($type, $val1, $val2 = null) { $this->type = $type; $this->val1 = (int) $val1; $this->val2 = (int) $val2; parent::__construct(); } public function applyParsley() { parent::applyParsley(); switch ($this->type) { case 'min': $this->field->setAttribute('data-parsley-min', $this->val1); break; case 'max': $this->field->setAttribute('data-parsley-max', $this->val1); break; case 'range': $this->field->setAttribute('data-parsley-range', sprintf("[%s,%s]", $this->val1, $this->val2)); break; } } public function getConstraintName() { return $this->type; } public function removeParsley() { parent::removeParsley(); switch ($this->type) { case 'min': $this->field->setAttribute('data-parsley-min', ''); break; case 'max': $this->field->setAttribute('data-parsley-max', ''); break; case 'range': $this->field->setAttribute('data-parsley-range', ''); break; } } public function validate($value) { if (!is_numeric($value)) { return true; } switch ($this->type) { case 'min': return (int) $value >= $this->val1; case 'max': return (int) $value <= $this->val1; case 'range': return (int) $value >= $this->val1 && (int) $value <= $this->val2; } } public function getDefaultMessage() { switch ($this->type) { case 'min': return sprintf(_t('ZenValidator.MIN', 'This value should be greater than or equal to %s'), $this->val1); case 'max': return sprintf(_t('ZenValidator.MAX', 'This value should be less than or equal to %s'), $this->val1); case 'range': return sprintf(_t('ZenValidator.RANGE', 'This value should be between %s and %s'), $this->val1, $this->val2); } } } /** * Constraint_regex * Constrain a field to match a regular expression * * @example Constraint_regex::create("/^#(?:[0-9a-fA-F]{3}){1,2}$/"); // value must be a valid hex color **/ class Constraint_regex extends ZenValidatorConstraint { /** * @var string **/ protected $regex; /** * @param string $regex **/ public function __construct($regex) { $this->regex = $regex; parent::__construct(); } public function getConstraintName() { return 'pattern'; } public function applyParsley() { parent::applyParsley(); $this->field->setAttribute('data-parsley-pattern', trim($this->regex, '/')); } public function removeParsley() { parent::removeParsley(); $this->field->setAttribute('data-parsley-pattern', ''); } public function validate($value) { if (!$value) { return true; } return preg_match($this->regex, $value); } public function getDefaultMessage() { return _t('ZenValidator.REGEXP', 'This value seems to be invalid'); } } /** * Constraint_remote * Validate a field remotely via ajax * * See readme for example **/ class Constraint_remote extends ZenValidatorConstraint { /** * @var string **/ protected $url; /** * @var array **/ protected $params; /** * @var array **/ protected $options; /** * @var string **/ protected $validator; /** * @var string **/ protected $method = 'GET'; /** * @param string $url - the url to call via ajax * @param array $params - request vars * @param string $options - array of options like { "type": "POST", "dataType": "jsonp", "data": { "token": "value" } } * @param boolean|string $validator - custom validator or "reverse" * By default, all 2xx ajax returs are considered valid, all others failure. * You can show frontend server-side specific error messages by returning a 404 error with the error message in the body of the response **/ public function __construct($url, $params = array(), $options = true, $validator = null) { $this->url = $url; $this->params = $params; $this->options = $options; if ($validator !== null) { $this->validator = $validator; } // For current version of Parsley, we have defined a custom async validator for default use cases if ($this->validator === null && ZenValidator::config()->use_current) { $this->validator = 'zenRemote'; } if (is_array($options) && isset($this->options['type'])) { $this->method = $this->options['type']; } parent::__construct(); } public function applyParsley() { parent::applyParsley(); $url = count($this->params) ? $this->url . '?' . http_build_query($this->params) : $this->url; $this->field->setAttribute('data-parsley-remote', $url); if (!empty($this->options)) { $this->field->setAttribute('data-parsley-remote-options', json_encode($this->options)); } if ($this->validator) { $this->field->setAttribute('data-parsley-remote-validator', $this->validator); } } public function removeParsley() { parent::removeParsley(); $this->field->setAttribute('data-parsley-remote', ''); if ($this->field->getAttribute('data-parsley-remote-options')) { $this->field->setAttribute('data-parsley-remote-options', ''); } if ($this->field->getAttribute('data-parsley-remote-validator')) { $this->field->setAttribute('data-parsley-remote-validator', ''); } } public function validate($value) { if (!$value) { return true; } $this->params[$this->field->getName()] = $value; $query = http_build_query($this->params); $url = $this->method == 'GET' ? $this->url . '?' . $query : $this->url; // If the url is a relative one, use Director::test() to get the response if (Director::is_relative_url($url)) { $url = Director::makeRelative($url); $postVars = $this->method == 'POST' ? $this->params : null; $response = Director::test($url, $postVars, Controller::curr()->getRequest()->getSession(), $this->method); $result = ($response->getStatusCode() == 200) ? true : false; // Otherwise CURL to remote url } else { $ch = curl_init(); if ($this->method == 'POST') { curl_setopt($ch, CURLOPT_POSTFIELDS, $query); } curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_USERAGENT, 'ZENVALIDATOR'); curl_setopt($ch, CURLOPT_HEADER, true); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $result = ($status == 200) ? true : false; } return $this->validator == 'reverse' ? !$result : $result; // $isJson = ((is_string($result) && (is_object(json_decode($result)) || is_array(json_decode($result))))); // // if ($isJson) { // $result = Convert::json2obj($result); // if (isset($result->success)) { // return true; // } else { // if (isset($result->message)) { // $this->setMessage($result->message); // } elseif (isset($result->error)) { // $this->setMessage($result->error); // } // } // } return false; } public function getDefaultMessage() { return _t('ZenValidator.REMOTE', 'This value seems to be invalid'); } } /** * Constraint_type * Constrain a field value to be a of a min value, max value or between a range * * @example Constraint_type::create('email'); // require valid email * @example Constraint_type::create('url'); // require valid url * @example Constraint_type::create('number'); // require valid number * @example Constraint_type::create('integer'); // require valid integer * @example Constraint_type::create('digits'); // require only digits * @example Constraint_type::create('alphanum'); // require valid alphanumeric string **/ class Constraint_type extends ZenValidatorConstraint { const EMAIL = 'email'; const URL = 'url'; const NUMBER = 'number'; const INTEGER = 'integer'; const DIGITS = 'digits'; const ALPHANUM = 'alphanum'; /** * @var string **/ protected $type; /** * @param string $type - allowed datatype **/ public function __construct($type) { $this->type = $type; parent::__construct(); } public function applyParsley() { parent::applyParsley(); $this->field->setAttribute('data-parsley-type', $this->type); } public function removeParsley() { parent::removeParsley(); $this->field->setAttribute('data-parsley-type', ''); } public function validate($value) { if (!$value) { return true; } switch ($this->type) { case 'url': return filter_var($value, FILTER_VALIDATE_URL); case 'email': return filter_var($value, FILTER_VALIDATE_EMAIL); case 'number': return is_numeric($value); case 'integer': return is_int($value); case 'digits': return preg_match('/^[0-9]*$/', $value); case 'alphanum': return ctype_alnum($value); default: throw new Exception($this->type . " is not a valid type"); } } public function getDefaultMessage() { switch ($this->type) { case 'url': return _t('ZenValidator.URL', 'This value should be a valid URL'); case 'email': return _t('ZenValidator.EMAIL', 'This value should be a valid email'); case 'number': return _t('ZenValidator.NUMBER', 'This value should be a number'); case 'integer': return _t('ZenValidator.INTEGER', 'This value should be a number'); case 'digits': return _t('ZenValidator.DIGITS', 'This value should be a number'); case 'alphanum': return _t('ZenValidator.ALPHANUMERIC', 'This value should be alphanumeric'); } } } /** * Constraint_equalto * Constrain a field value to be the same as another field * * @example Constraint_equalto::create('OtherField'); **/ class Constraint_equalto extends ZenValidatorConstraint { /** * @var string **/ protected $targetField; /** * @param string $field the Name of the field to match **/ public function __construct($field) { $this->targetField = $field; parent::__construct(); } /** * @return FormField */ public function getTargetField() { return $this->field->getForm()->Fields()->dataFieldByName($this->targetField); } public function applyParsley() { parent::applyParsley(); $this->field->setAttribute('data-parsley-equalto', '#' . $this->getTargetField()->getAttribute('id')); } public function removeParsley() { parent::removeParsley(); $this->field->setAttribute('data-parsley-equalto', ''); } public function validate($value) { return $this->getTargetField()->dataValue() == $value; } public function getDefaultMessage() { return sprintf(_t('ZenValidator.EQUALTO', 'This value should be the same as the field %s'), $this->getTargetField()->Title()); } } /** * Constraint_notequalto * Constrain a field value to be the different from another field * * @example Constraint_notequalto::create('OtherField'); **/ class Constraint_notequalto extends ZenValidatorConstraint { /** * @var string **/ protected $targetField; /** * @param string $field the Name of the field to check **/ public function __construct($field) { $this->targetField = $field; parent::__construct(); } /** * @return FormField */ public function getTargetField() { return $this->field->getForm()->Fields()->dataFieldByName($this->targetField); } public function applyParsley() { parent::applyParsley(); $this->loadExtra('notequalto'); $this->field->setAttribute('data-parsley-notequalto', '#' . $this->getTargetField()->getAttribute('id')); } public function removeParsley() { parent::removeParsley(); $this->field->setAttribute('data-parsley-notequalto', ''); } public function validate($value) { return $this->getTargetField()->dataValue() != $value; } public function getDefaultMessage() { return sprintf(_t('ZenValidator.NOTEQUALTO', 'This value should be the different from the field %s'), $this->getTargetField()->Title()); } } /** * Constraint_comparison * Compare the value from one field to another field * * @example Constraint_comparison::create('gt','OtherField'); * @example Constraint_comparison::create('gte','OtherField'); * @example Constraint_comparison::create('lt','OtherField'); * @example Constraint_comparison::create('lte','OtherField'); **/ class Constraint_comparison extends ZenValidatorConstraint { const GREATER = 'gt'; const GREATER_OR_EQUAL = 'gte'; const LESS = 'lt'; const LESS_OR_EQUAL = 'lte'; /** * @var string **/ protected $targetField; /** * @var type **/ protected $type; /** * @param string $type Type of validation * @param string $field the Name of the field to match **/ public function __construct($type, $field) { $this->type = $type; $this->targetField = $field; parent::__construct(); } /** * @return FormField **/ public function getTargetField() { return $this->field->getForm()->Fields()->dataFieldByName($this->targetField); } public function applyParsley() { parent::applyParsley(); $this->loadExtra('comparison'); $this->field->setAttribute('data-parsley-' . $this->type, '#' . $this->getTargetField()->getAttribute('id')); } public function removeParsley() { parent::removeParsley(); $this->field->setAttribute('data-parsley-' . $this->type, ''); } public function validate($value) { switch ($this->type) { //Validates that the value is greater than another field's one case self::GREATER: return $value > $this->getTargetField()->dataValue(); //Validates that the value is greater than or equal to another field's one case self::GREATER_OR_EQUAL: return $value >= $this->getTargetField()->dataValue(); //Validates that the value is less than another field's one case self::LESS: return $value < $this->getTargetField()->dataValue(); //Validates that the value is less than or equal to another field's one case self::LESS_OR_EQUAL: return $value <= $this->getTargetField()->dataValue(); default: throw new Exception('Invalid type : ' . $this->type); } } public function getDefaultMessage() { switch ($this->type) { case self::GREATER: return sprintf(_t('ZenValidator.GREATER', 'This value should be greater than the field %s'), $this->getTargetField()->Title()); case self::GREATER_OR_EQUAL: return sprintf(_t('ZenValidator.GREATEROREQUAL', 'This value should be greater or equal than the field %s'), $this->getTargetField()->Title()); case self::LESS: return sprintf(_t('ZenValidator.LESS', 'This value should be less than the field %s'), $this->getTargetField()->Title()); case self::LESS_OR_EQUAL: return sprintf(_t('ZenValidator.LESSOREQUAL', 'This value should be less than or equal to the field %s'), $this->getTargetField()->Title()); } } } /** * Constraint_words * Validates the number of words in the field * * @example Constraint_words::create('minwords','200'); * @example Constraint_words::create('maxwords','200'); * @example Constraint_words::create('words','200',600); **/ class Constraint_words extends ZenValidatorConstraint { const MINWORDS = 'minwords'; const MAXWORDS = 'maxwords'; const WORDS = 'words'; /** * @var int **/ protected $val1; /** * @var int **/ protected $val2; /** * @var type **/ protected $type; /** * @param string $type type of validation * @param int $val1 number of words * @param int $val2 maximum number of words **/ public function __construct($type, $val1, $val2 = null) { $this->type = $type; $this->val1 = $val1; $this->val2 = $val2; if ($type == self::WORDS && $val2 === null) { throw new Exception('You must specify a range of words'); } parent::__construct(); } public function applyParsley() { parent::applyParsley(); $this->loadExtra('words'); $value = $this->val1; if ($this->val2) { $value = '[' . $value . ',' . $this->val2 . ']'; } $this->field->setAttribute('data-parsley-' . $this->type, $value); } public function removeParsley() { parent::removeParsley(); $this->field->setAttribute('data-parsley-' . $this->type, ''); } public function validate($value) { $count = str_word_count($value); switch ($this->type) { //Validates that the value have at least a certain amount of words case self::MINWORDS: return $count >= $this->val1; //Validates that the value have a maximum of a certain amount of words case self::MAXWORDS: return $count <= $this->val1; //Validates that the value is within a certain range of words case self::WORDS: return $count >= $this->val1 && $count <= $this->val2; default: throw new Exception('Invalid type : ' . $this->type); } } public function getDefaultMessage() { switch ($this->type) { case self::MINWORDS: return sprintf(_t('ZenValidator.MINWORDS', 'This value should have at least %s words'), $this->val1); case self::MAXWORDS: return sprintf(_t('ZenValidator.MAXWORDS', 'This value should have a maximum of %s words'), $this->val1); case self::WORDS: return sprintf(_t('ZenValidator.WORDS', 'This value should be between %s and %s words'), $this->val1, $this->val2); } } } /** * Constraint_date * Validates the the field is a date * * @example Constraint_date::create(); **/ class Constraint_date extends ZenValidatorConstraint { /** **/ public function __construct() { parent::__construct(); } public function applyParsley() { parent::applyParsley(); $this->loadExtra('dateiso'); $this->field->setAttribute('data-parsley-dateiso', 'true'); } public function removeParsley() { parent::removeParsley(); $this->field->setAttribute('data-parsley-dateiso', ''); } public function validate($value) { return preg_match('/^(\d{4})\D?(0[1-9]|1[0-2])\D?([12]\d|0[1-9]|3[01])$/', $value); } public function getDefaultMessage() { return _t('ZenValidator.DATEISO', 'This value should be a date'); } } /** * Constraint_Dimension * Constrain an image field to have the specified dimension(s) * * @example Constraint_dimension::create('width', 100); **/ class Constraint_dimension extends ZenValidatorConstraint { /** * @var string */ protected $type; /** * @var int */ protected $val1; /** * @var int */ protected $val2; /** * Validation type constants. */ const WIDTH = 'width'; const HEIGHT = 'height'; const WIDTH_HEIGHT = 'width_height'; const RATIO = 'ratio'; const MIN_WIDTH = 'min_width'; const MIN_HEIGHT = 'min_height'; const MIN_WIDTH_HEIGHT = 'min_width_height'; const MAX_WIDTH = 'max_width'; const MAX_HEIGHT = 'max_height'; const MAX_WIDTH_HEIGHT = 'max_width_height'; /** * Constructor * @param string $type Type of validation * @param int $val1 First value * @param int $val2 Second value */ public function __construct($type, $val1, $val2 = null) { $this->type = $type; $this->val1 = $val1; $this->val2 = $val2; parent::__construct(); } /** * Validate function called for validator. * @param Mixed $value the value of the field being validated. * @return boolean */ public function validate($value) { // The value which comes in is a files array so we can look through this // to and then get the files to test aspects of them. if (isset($value['Files'])) { foreach ($value['Files'] as $fileID) { $file = File::get()->byId($fileID); // Now have the file double-check it is an image and if so then // get some information about the image using PHPs getimagesize() if ($file->ClassName == 'Image') { $info = getimagesize(BASE_PATH . "/" . $file->Filename); if ($info && is_array($info)) { $width = $info[0]; $height = $info[1]; switch ($this->type) { case self::WIDTH: return $width == $this->val1; break; case self::HEIGHT: return $height == $this->val1; break; case self::WIDTH_HEIGHT: return (($width == $this->val1) && ($height == $this->val2)); break; case self::RATIO: $baseWidth = floor($width / $this->val1); $baseHeight = floor($height / $this->val2); return $baseWidth == $baseHeight; break; case self::MIN_WIDTH: return $width >= $this->val1; break; case self::MIN_HEIGHT: return $height >= $this->val1; break; case self::MIN_WIDTH_HEIGHT: return (($width >= $this->val1) && ($height >= $this->val2)); break; case self::MAX_WIDTH: return $width <= $this->val1; break; case self::MAX_HEIGHT: return $height <= $this->val1; break; case self::MAX_WIDTH_HEIGHT: return (($width <= $this->val1) && ($height <= $this->val2)); break; default: throw new Exception('Invalid type : ' . $this->type); } } } } } else { // Return true so if no file selected then not shown validation message // when the field is optional. If required dev should add to required fields as well. return true; } } /** * Gets the default message for the validator * @return string the validation message */ public function getDefaultMessage() { switch ($this->type) { case self::WIDTH: return sprintf( _t( 'ZenValidator.DIMWIDTH', 'Image width must be %s pixels' ), $this->val1 ); break; case self::HEIGHT: return sprintf( _t( 'ZenValidator.DIMHEIGHT', 'Image height must be %s pixels' ), $this->val1 ); break; case self::WIDTH_HEIGHT: return sprintf( _t( 'ZenValidator.DIMWIDTHHEIGHT', 'Image width must be %s pixels and Image height must be %s pixels' ), $this->val1, $this->val2 ); break; case self::RATIO: return sprintf( _t( 'ZenValidator.DIMRATIO', 'Image aspect ratio (shape) must be %s:%s' ), $this->val1, $this->val2 ); break; case self::MIN_WIDTH: return sprintf( _t( 'ZenValidator.DIMMINWIDTH', 'Image width must be greater than or equal to %s pixels' ), $this->val1 ); break; case self::MIN_HEIGHT: return sprintf( _t( 'ZenValidator.DIMMINHEIGHT', 'Image height must be greater than or equal to %s pixels' ), $this->val1 ); break; case self::MIN_WIDTH_HEIGHT: return sprintf( _t( 'ZenValidator.DIMMINWIDTHHEIGHT', 'Image width must be greater than or equal to %s pixels and Image height must be greater than or equal to %s pixels' ), $this->val1, $this->val2 ); break; case self::MAX_WIDTH: return sprintf( _t( 'ZenValidator.DIMMAXWIDTH', 'Image width must be less than or equal to %s pixels' ), $this->val1 ); break; case self::MAX_HEIGHT: return sprintf( _t( 'ZenValidator.DIMMAXHEIGHT', 'Image height must be less than or equal to %s pixels' ), $this->val1 ); break; case self::MAX_WIDTH_HEIGHT: return sprintf( _t( 'ZenValidator.DIMMAXWIDTHHEIGHT', 'Image width must be less than or equal to %s pixels and Image height must be less than or equal to %s pixels' ), $this->val1, $this->val2 ); break; } } } |