1 /**
2  * Skadi.d Web Framework
3  * Validation Component
4 
5  * Authors: Faianca
6  * Copyright: Copyright (c) 2015 Faianca
7  * License: MIT License, see LICENSE
8  */
9 module skadi.components.validation.validators.stringlength;
10 
11 import skadi.components.validation.validatorInterface;
12 import skadi.components.validation.validation;
13 import skadi.components.validation.validator;
14 import skadi.components.validation.message;
15 
16 import std.conv;
17 import std..string;
18 import std.stdio;
19 
20 /**
21  * Validates that a string has the specified maximum and minimum constraints
22  * The test is passed if for a string's length L, min<=L<=max, i.e. L must
23  * be at least min, and at most max.
24  *
25  * Check Unittests for examples at the bottom of the file.
26  */
27 struct StringOptions
28 {
29 	int min;
30 	int max;
31 	string label;
32 	bool allowEmpty = false;
33 	string messageMinimum;
34 	string messageMaximum;
35 }
36 
37 class StringLength : Validator
38 {
39 
40 	protected StringOptions _options;
41 
42 	/**
43 	 * constructor
44 	 */
45 	this(StringOptions options)
46 	{
47 		this._options = options;
48 	}
49 
50 	bool validate(string field = null)
51 	{
52 		bool valid = false;
53 		string value = field;
54 
55 		if (!this._options.min && !this._options.max) {
56 			throw new Exception("A minimum or maximum must be set");
57 		}
58 
59 		if (this._options.allowEmpty && value.length == 0) {
60 			return true;
61 		}
62 
63 		if (this._options.min) {
64 			if (field.length >= this._options.min) {
65 				valid = true;
66 			} else {
67 				return false;
68 			}
69 		}
70 
71 		if (this._options.max) {
72 			valid = (field.length <= this._options.max);
73 		}
74 
75 		return valid;
76 	}
77 
78 	/**
79 	 * Executes the validation
80 	 */
81 	override bool validate(Validation validation, string field = null)
82 	{
83 		bool valid = false;
84 		string value = validation.getValue(field);
85 
86 		string label = (this._options.label.length == 0)
87 						? validation.getLabel(field)
88 						: this._options.label;
89 
90 		if (!this._options.min && !this._options.max) {
91 			throw new Exception("A minimum or maximum must be set");
92 		}
93 
94 		if (this._options.allowEmpty && value.length == 0) {
95 			return true;
96 		}
97 
98 		if (this._options.min) {
99 			if (field.length >= this._options.min) {
100 				valid = true;
101 			} else {
102 				string message = this._options.messageMinimum;
103 
104 				if (message.length == 0) {
105 					message = validation.getDefaultMessage("TooShort");
106 				}
107 
108 				validation.appendMessage(new Message(format(message, label, this._options.min), field, "TooShort"));
109 				return false;
110 			}
111 		}
112 
113 		if (this._options.max) {
114 			valid = (field.length <= this._options.max);
115 
116 			if (!valid) {
117 				string message = this._options.messageMaximum;
118 
119 				if (message.length == 0) {
120 					message = validation.getDefaultMessage("TooLong");
121 				}
122 				validation.appendMessage(new Message(format(message, label, this._options.max), field, "TooLong"));
123 				return false;
124 			}
125 		}
126 
127 		return valid;
128 	}
129 }
130 
131 unittest
132 {
133 	// WITH VALIDATOR
134 
135 	auto validation = new Validation();
136 
137 	auto options = StringOptions();
138 		 options.max = 10;
139 
140 	StringLength test = new StringLength(options);
141 	assert(test.validate(validation, "test") == true);
142 	assert(test.validate(validation, "testtesttesttestetetetetetete") == false);
143 	assert(validation.isValid() == false);
144 
145 	///// SIMPLE
146 
147 	test = new StringLength(StringOptions(2,50));
148 	assert(test.validate("test") == true);
149 	assert(test.validate("t") == false);
150 
151 	options = StringOptions();
152 		 options.max = 10;
153 
154 	test = new StringLength(options);
155 	assert(test.validate("test") == true);
156 	assert(test.validate("testtesttesttestetetetetetete") == false);
157 
158 	options = StringOptions();
159 		 options.allowEmpty = true;
160 		 options.max = 10;
161 		 options.min = 2;
162 
163 	test = new StringLength(options);
164 	assert(test.validate("") == true);
165 	assert(test.validate("test") == true);
166 	assert(test.validate("testtesttesttestetetetetetete") == false);
167 	assert(test.validate("t") == false);
168 }