Skip to content

Commit 2593258

Browse files
committed
Merge branch 'development' of github.com:coldbox-modules/cbvalidation into development
2 parents f9be3d6 + 84c68ac commit 2593258

18 files changed

+368
-134
lines changed

box.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name":"ColdBox Validation",
33
"author":"Ortus Solutions <[email protected]>",
4-
"version":"2.0.1",
4+
"version":"2.2.0",
55
"location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbvalidation/@build.version@/[email protected]@.zip",
66
"slug":"cbvalidation",
77
"type":"modules",

build/toMaster.boxr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# Check out master
44
!git checkout -f master
5+
!git pull
56
# Merge development into it
67
!git merge --no-ff development
78
# Tag the master repo with the version in box.json

changelog.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
# CHANGELOG
22

3-
## 2.0.1
3+
## 2.1.0
44

5-
* Updated `RequiredUnless` and `RequiredIf` to use struct literal notation instead of the weird parsing we did.
6-
* Added the `Unique` validator thanks to @elpete!
5+
* `feature` : Added `constraintProfiles` to allow you to define which fields to validate according to defined profiles: https://github.com/coldbox-modules/cbvalidation/issues/37
6+
* `feature` : Updated `RequiredUnless` and `RequiredIf` to use struct literal notation instead of the weird parsing we did.
7+
* `feature` : Added the `Unique` validator thanks to @elpete!
8+
* `feature` : All validators now accept a `rules` argument, which is the struct of constraints for the specific field it's validating on
9+
* `improvement` : Added `null` support for the `RequiredIf,RequiredUnless` validator values
710

811
## 2.0.0
912

@@ -12,8 +15,8 @@
1215
* No more manual discovery of validators, automated registration and lookup process, cleaned lots of code on this one!
1316
* New Validator: `Accepted` - The field under validation must be yes, on, 1, or true. This is useful for validating "Terms of Service" acceptance.
1417
* New Validator: `Alpha` - Only allows alphabetic characters
15-
* New Validator: `RequiredUnless` with validation data: `anotherField:value,...` - The field under validation must be present and not empty unless the `anotherfield` field is equal to the passed `value`.
16-
* New Validator: `RequiredIf` with validation data: `anotherField:value,...` - The field under validation must be present and not empty if the `anotherfield` field is equal to the passed `value`.
18+
* New Validator: `RequiredUnless` with validation data as a struct literal `{ anotherField:value, ... }` - The field under validation must be present and not empty unless the `anotherfield` field is equal to the passed `value`.
19+
* New Validator: `RequiredIf` with validation data as a struct literal `{ anotherField:value, ... }` - The field under validation must be present and not empty if the `anotherfield` field is equal to the passed `value`.
1720
* Accelerated validation by removing type checks. ACF chokes on interface checks
1821

1922
### Improvements
@@ -28,7 +31,6 @@
2831
* `Bugs` : Fixed lots of wrong type exceptions
2932
* `Compat` : Remove ACF11 support
3033

31-
`requiredUnless=role,test
3234
---
3335

3436
## 1.5.2

models/Mixins.cfm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* @locale The i18n locale to use for validation messages
1010
* @excludeFields The fields to exclude from the validation
1111
* @includeFields The fields to include in the validation
12+
* @profiles If passed, a list of profile names to use for validation constraints
1213
*
1314
* @return cbvalidation.model.result.IValidationResult
1415
*/
@@ -26,6 +27,7 @@ function validate(){
2627
* @locale The i18n locale to use for validation messages
2728
* @excludeFields The fields to exclude from the validation
2829
* @includeFields The fields to include in the validation
30+
* @profiles If passed, a list of profile names to use for validation constraints
2931
*
3032
* @return The validated object or the structure fields that where validated
3133
* @throws ValidationException

models/ValidationManager.cfc

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ component accessors="true" serialize="false" singleton {
117117
* @locale An optional locale to use for i18n messages
118118
* @excludeFields An optional list of fields to exclude from the validation.
119119
* @IncludeFields An optional list of fields to include in the validation.
120+
* @profiles If passed, a list of profile names to use for validation constraints
120121
*
121122
* @return IValidationResult
122123
*/
@@ -126,7 +127,8 @@ component accessors="true" serialize="false" singleton {
126127
any constraints = "",
127128
string locale = "",
128129
string excludeFields = "",
129-
string includeFields = ""
130+
string includeFields = "",
131+
string profiles = ""
130132
){
131133
var targetName = "";
132134

@@ -152,10 +154,38 @@ component accessors="true" serialize="false" singleton {
152154
locale : arguments.locale,
153155
targetName : targetName,
154156
resourceService : resourceService,
155-
constraints : allConstraints
157+
constraints : allConstraints,
158+
profiles : arguments.profiles
156159
}
157160
);
158161

162+
// Discover profiles, and update the includeFields list from it
163+
if( len( arguments.profiles ) ){
164+
arguments.includeFields = arguments.profiles
165+
.listToArray()
166+
// Check if profiles defined in target and iterated one exists
167+
.filter( function( profileKey ){
168+
return structKeyExists( target, "constraintProfiles" ) && structKeyExists( target.constraintProfiles, profileKey );
169+
} )
170+
// Incorporate fields from each profile
171+
.map( function( profileKey ){
172+
// iterate all declared profile fields and incorporate into the includeFields
173+
return target.constraintProfiles
174+
.find( arguments.profileKey )
175+
.listToArray();
176+
} )
177+
// Reduce all fields into a single hashset to do a distinct collection
178+
.reduce( function( result, item ){
179+
item
180+
.each( function( thisField ){
181+
result.add( thisField );
182+
} );
183+
return result;
184+
}, createObject( "java", "java.util.HashSet" ) )
185+
.toArray();
186+
arguments.includeFields = arrayToList( arguments.includeFields );
187+
}
188+
159189
// iterate over constraints defined
160190
for ( var thisField in allConstraints ) {
161191
var validateField = true;
@@ -193,6 +223,7 @@ component accessors="true" serialize="false" singleton {
193223
* @locale An optional locale to use for i18n messages
194224
* @excludeFields An optional list of fields to exclude from the validation.
195225
* @IncludeFields An optional list of fields to include in the validation.
226+
* @profiles If passed, a list of profile names to use for validation constraints
196227
*
197228
* @throws ValidationException
198229
* @return any,struct: The target object that was validated, or the structure fields that where validated.
@@ -203,7 +234,8 @@ component accessors="true" serialize="false" singleton {
203234
any constraints = "",
204235
string locale = "",
205236
string excludeFields = "",
206-
string includeFields = ""
237+
string includeFields = "",
238+
string profiles = ""
207239
){
208240
var vResults = this.validate( argumentCollection = arguments );
209241

models/result/ValidationResult.cfc

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,49 @@
77
component accessors="true" {
88

99
/**
10-
* A collection of error objects represented in this result object
11-
*/
10+
* A collection of error objects represented in this result object
11+
*/
1212
property name="errors" type="array";
1313

1414
/**
15-
* Extra metadata you can store in the results object
16-
*/
15+
* Extra metadata you can store in the results object
16+
*/
1717
property name="resultMetadata" type="struct";
1818

1919
/**
20-
* The locale this result validation is using
21-
*/
20+
* The locale this result validation is using
21+
*/
2222
property name="locale" type="string";
2323

2424
/**
25-
* The name of the target object
26-
*/
25+
* The name of the target object
26+
*/
2727
property name="targetName" type="string";
2828

2929
/**
30-
* The constraints evaluated in the validation process
31-
*/
30+
* The constraints evaluated in the validation process
31+
*/
3232
property name="constraints" type="struct";
3333

3434
/**
35-
* The resource bundle object
36-
*/
35+
* The resource bundle object
36+
*/
3737
property name="resourceService";
3838

3939
/**
40-
* Constructor
41-
*/
40+
* The profiles used in the validation
41+
*/
42+
property name="profiles" type="string";
43+
44+
/**
45+
* Constructor
46+
*/
4247
ValidationResult function init(
4348
string locale = "",
4449
string targetName = "",
4550
any resourceService = "",
46-
struct constraints = structNew()
51+
struct constraints = structNew(),
52+
string profiles = ""
4753
){
4854
variables.errors = [];
4955
variables.resultMetadata = {};
@@ -53,6 +59,7 @@ component accessors="true" {
5359
variables.targetName = arguments.targetName;
5460
variables.resourceService = arguments.resourceService;
5561
variables.constraints = arguments.constraints;
62+
variables.profiles = arguments.profiles;
5663
return this;
5764
}
5865

models/validators/RequiredIfValidator.cfc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ component accessors="true" extends="RequiredValidator" singleton {
4343
.map( function( key, value ){
4444
// Get comparison values
4545
var comparePropertyValue = invoke( target, "get#key#" );
46+
// Null checks
47+
if( isNull( comparePropertyValue ) ){
48+
return isNull( arguments.value );
49+
}
4650
// Check if the compareValue is the same as the defined one
4751
return ( arguments.value == comparePropertyValue ? true : false );
4852
} )

models/validators/RequiredUnlessValidator.cfc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ component accessors="true" extends="RequiredValidator" singleton {
4343
.map( function( key, value ){
4444
// Get comparison values
4545
var comparePropertyValue = invoke( target, "get#key#" );
46+
// Null checks
47+
if( isNull( comparePropertyValue ) ){
48+
return isNull( arguments.value );
49+
}
4650
// Check if the compareValue is the same as the defined one
4751
return ( arguments.value == comparePropertyValue ? true : false );
4852
} )

readme.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ The module will also register several methods in your handlers/interceptors/layo
4141
* @locale The i18n locale to use for validation messages
4242
* @excludeFields The fields to exclude from the validation
4343
* @includeFields The fields to include in the validation
44+
* @profiles If passed, a list of profile names to use for validation constraints
4445
*
4546
* @return cbvalidation.model.result.IValidationResult
4647
*/
@@ -56,6 +57,7 @@ function validate()
5657
* @locale The i18n locale to use for validation messages
5758
* @excludeFields The fields to exclude from the validation
5859
* @includeFields The fields to include in the validation
60+
* @profiles If passed, a list of profile names to use for validation constraints
5961
*
6062
* @return The validated object or the structure fields that where validated
6163
* @throws ValidationException
@@ -167,6 +169,25 @@ this.constraints = {
167169
}
168170
```
169171

172+
## Constraint Profiles
173+
174+
You can also create profiles or selections of fields that will be targeted for validation if you are defining the constraints in objects. All you do is create a key called: `this.constraintProfiles` which contains a struct of defined fields:
175+
176+
```js
177+
this.constraintProfiles = {
178+
new = "fname,lname,email,password",
179+
update = "fname,lname,email",
180+
passUpdate = "password,confirmpassword"
181+
}
182+
```
183+
184+
Each key is the name of the profile like `new, update passUpdate`. The value of the profile is a list of fields to validate within that selected profile. In order to use it, just pass in one or more profile names into the `validate() or validateOrFail()` methods.
185+
186+
```js
187+
var results = validateModel( target=model, profiles="update" )
188+
var results = validateModel( target=model, profiles="update,passUpdate" )
189+
```
190+
170191
```
171192
********************************************************************************
172193
Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp

test-harness/handlers/Main.cfc

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ component{
5757
}
5858

5959
/**
60-
* validateOrFailWithObject
61-
*/
60+
* validateOrFailWithObject
61+
*/
6262
function validateOrFailWithObject( event, rc, prc ){
6363

6464
var oModel = populateModel( "User" );
@@ -69,6 +69,19 @@ component{
6969
return "Validated";
7070
}
7171

72+
/**
73+
* validateOrFailWithObjectProfiles
74+
*/
75+
function validateOrFailWithProfiles( event, rc, prc ){
76+
77+
var oModel = populateModel( "User" );
78+
79+
// validate
80+
prc.object = validateOrFail( target=oModel, profiles=rc._profiles );
81+
82+
return "Validated";
83+
}
84+
7285

7386
// Run on first init
7487
any function onAppInit( event, rc, prc ){

0 commit comments

Comments
 (0)