Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
lmajano committed Nov 15, 2022
2 parents 93ce81e + 391495f commit 615d912
Show file tree
Hide file tree
Showing 21 changed files with 566 additions and 66 deletions.
2 changes: 1 addition & 1 deletion box.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name":"ColdBox Validation",
"author":"Ortus Solutions <[email protected]>",
"version":"4.0.0",
"version":"4.1.0",
"location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbvalidation/@build.version@/[email protected]@.zip",
"slug":"cbvalidation",
"type":"modules",
Expand Down
21 changes: 17 additions & 4 deletions build/Build.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,7 @@ component {
)
.toConsole();

// Prepare exports directory
variables.exportsDir = variables.artifactsDir & "/#projectName#/#arguments.version#";
directoryCreate( variables.exportsDir, true, true );
ensureExportDir( argumentCollection = arguments );

// Project Build Dir
variables.projectBuildDir = variables.buildDir & "/#projectName#";
Expand Down Expand Up @@ -200,11 +198,12 @@ component {
version = "1.0.0",
outputDir = ".tmp/apidocs"
){
ensureExportDir( argumentCollection = arguments );

// Create project mapping
fileSystemUtil.createMapping( arguments.projectName, variables.cwd );
// Generate Docs
print.greenLine( "Generating API Docs, please wait..." ).toConsole();
directoryCreate( arguments.outputDir, true, true );

command( "docbox generate" )
.params(
Expand Down Expand Up @@ -315,4 +314,18 @@ component {
return ( createObject( "java", "java.lang.System" ).getProperty( "cfml.cli.exitCode" ) ?: 0 );
}

/**
* Ensure the export directory exists at artifacts/NAME/VERSION/
*/
private function ensureExportDir(
required projectName,
version = "1.0.0"
){
if ( structKeyExists( variables, "exportsDir" ) && directoryExists( variables.exportsDir ) ){
return;
}
// Prepare exports directory
variables.exportsDir = variables.artifactsDir & "/#projectName#/#arguments.version#";
directoryCreate( variables.exportsDir, true, true );
}
}
15 changes: 14 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

----

## [4.1.0] => 2022-NOV-14

### Added

* New ColdBox 7 delegate: `Validatable@cbValidation` which can be used to make objects validatable
* New validators: `notSameAs, notSameAsNoCase`

### Changed

* All date comparison validators now validate as `false` when the comparison target dates values are NOT dates instead of throwing an exception.

----

## [4.0.0] => 2022-OCT-10

### Added
Expand Down Expand Up @@ -64,7 +77,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

----

## [3.1.0] => 2021-MAY-17
## [3.1.1] => 2021-MAY-17

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion helpers/Mixins.cfm
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ boolean function validateHasValue( any targetValue ){
* @targetValue the value to check for nullness/emptyness
*/
boolean function validateIsNullOrEmpty( any targetValue ){
return getValidationManager().getValidator( "Required", {} ).hasValue( argumentCollection = arguments );
return !getValidationManager().getValidator( "Required", {} ).hasValue( argumentCollection = arguments );
}
/**
Expand Down
131 changes: 131 additions & 0 deletions models/delegates/Validatable.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* Copyright since 2016 by Ortus Solutions, Corp
* www.ortussolutions.com
* ---
* This delegate helps models validate themselves
*/
component accessors="true" {

// DI
property name="validationManager" inject="ValidationManager@cbvalidation";

// Properties
property name="validationResults";

/**
* Validate the $parent and stores a validation result in the delegate
*
* @fields One or more fields to validate on, by default it validates all fields in the constraints. This can be a simple list or an array.
* @constraints An optional shared constraints name or an actual structure of constraints to validate on.
* @locale An optional locale to use for i18n messages
* @excludeFields An optional list of fields to exclude from the validation.
* @IncludeFields An optional list of fields to include in the validation.
* @profiles If passed, a list of profile names to use for validation constraints
*/
boolean function isValid(
string fields = "*",
any constraints = "",
string locale = "",
string excludeFields = "",
string includeFields = "",
string profiles = ""
){
// validate and save results in private scope
variables.validationResults = validate( argumentCollection = arguments );

// return it
return ( !variables.validationResults.hasErrors() );
}

/**
* Get the validation results object. This will be an empty validation object if isValid() has not being called yet.
*
* @return cbvalidation.models.result.IValidationResult
*/
any function getValidationResults(){
if ( !isNull( variables.validationResults ) && isObject( variables.validationResults ) ) {
return variables.validationResults;
}
return new cbvalidation.models.result.ValidationResult();
}

/**
* Validate the parent delegate
*
* @fields The fields to validate on the target. By default, it validates on all fields
* @constraints A structure of constraint rules or the name of the shared constraint rules to use for validation
* @locale The i18n locale to use for validation messages
* @excludeFields The fields to exclude from the validation
* @includeFields The fields to include in the validation
* @profiles If passed, a list of profile names to use for validation constraints
*
* @return cbvalidation.model.result.IValidationResult
*/
function validate(){
arguments.target = $parent;
return variables.validationManager.validate( argumentCollection = arguments );
}

/**
* Validate an object or structure according to the constraints rules and throw an exception if the validation fails.
* The validation errors will be contained in the `extendedInfo` of the exception in JSON format
*
* @fields The fields to validate on the target. By default, it validates on all fields
* @constraints A structure of constraint rules or the name of the shared constraint rules to use for validation
* @locale The i18n locale to use for validation messages
* @excludeFields The fields to exclude from the validation
* @includeFields The fields to include in the validation
* @profiles If passed, a list of profile names to use for validation constraints
*
* @return The validated object or the structure fields that where validated
*
* @throws ValidationException
*/
function validateOrFail(){
arguments.target = $parent;
return variables.validationManager.validateOrFail( argumentCollection = arguments );
}

/**
* Verify if the target value has a value
* Checks for nullness or for length if it's a simple value, array, query, struct or object.
*/
boolean function validateHasValue( any targetValue ){
return variables.validationManager
.getValidator( "Required", {} )
.hasValue( argumentCollection = arguments );
}

/**
* Check if a value is null or is a simple value and it's empty
*
* @targetValue the value to check for nullness/emptyness
*/
boolean function validateIsNullOrEmpty( any targetValue ){
return !variables.validationManager
.getValidator( "Required", {} )
.hasValue( argumentCollection = arguments );
}

/**
* This method mimics the Java assert() function, where it evaluates the target to a boolean value and it must be true
* to pass and return a true to you, or throw an `AssertException`
*
* @target The tareget to evaluate for being true
* @message The message to send in the exception
*
* @return True, if the target is a non-null value. If false, then it will throw the `AssertError` exception
*
* @throws AssertException if the target is a false or null value
*/
boolean function assert( target, message = "" ){
if ( !isNull( arguments.target ) && arguments.target ) {
return true;
}
throw(
type : "AssertException",
message: len( arguments.message ) ? arguments.message : "Assertion failed from #callStackGet()[ 2 ].toString()#"
);
}

}
18 changes: 14 additions & 4 deletions models/validators/AfterOrEqualValidator.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,22 @@ component extends="BaseValidator" accessors="true" singleton {
if ( isNull( arguments.targetValue ) || isNullOrEmpty( arguments.targetValue ) ) {
return true;
}
// If not a date, throw it

// If not a date, invalide it
if ( !isDate( arguments.targetValue ) ) {
throw(
message = "The date you sent is an invalid date [#arguments.targetValue#]",
type = "InvalidValidationData"
validationResult.addError(
validationResult.newError(
argumentCollection = {
message : "The '#arguments.targetValue#' is not a valid date, so we cannot compare them.",
field : arguments.field,
validationType : getName(),
rejectedValue : ( arguments.targetValue ),
validationData : arguments.validationData,
errorMetadata : { "afterOrEqual" : arguments.targetValue }
}
)
);
return false;
}

// The compare value is set or it can be another field
Expand Down
18 changes: 14 additions & 4 deletions models/validators/AfterValidator.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,22 @@ component extends="BaseValidator" accessors="true" singleton {
if ( isNull( arguments.targetValue ) || isNullOrEmpty( arguments.targetValue ) ) {
return true;
}
// If target is not a date, throw it

// If target is not a date, invalidate it
if ( !isDate( arguments.targetValue ) ) {
throw(
message = "The date you sent is an invalid date [#arguments.targetValue#]",
type = "InvalidValidationData"
validationResult.addError(
validationResult.newError(
argumentCollection = {
message : "The '#arguments.targetValue#' is not a valid date, so we cannot compare them.",
field : arguments.field,
validationType : getName(),
rejectedValue : ( arguments.targetValue ),
validationData : arguments.validationData,
errorMetadata : { "afterOrEqual" : arguments.targetValue }
}
)
);
return false;
}

// The compare value is set or it can be another field
Expand Down
15 changes: 12 additions & 3 deletions models/validators/BeforeOrEqualValidator.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,19 @@ component extends="BaseValidator" accessors="true" singleton {
}
// If not a date, throw it
if ( !isDate( arguments.targetValue ) ) {
throw(
message = "The date you sent is an invalid date [#arguments.targetValue#]",
type = "InvalidValidationData"
validationResult.addError(
validationResult.newError(
argumentCollection = {
message : "The '#arguments.targetValue#' is not a valid date, so we cannot compare them.",
field : arguments.field,
validationType : getName(),
rejectedValue : ( arguments.targetValue ),
validationData : arguments.validationData,
errorMetadata : { "afterOrEqual" : arguments.targetValue }
}
)
);
return false;
}

// The compare value is set or it can be another field
Expand Down
15 changes: 12 additions & 3 deletions models/validators/BeforeValidator.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,19 @@ component extends="BaseValidator" accessors="true" singleton {
}
// If not a date, throw it
if ( !isDate( arguments.targetValue ) ) {
throw(
message = "The date you sent is an invalid date [#arguments.targetValue#]",
type = "InvalidValidationData"
validationResult.addError(
validationResult.newError(
argumentCollection = {
message : "The '#arguments.targetValue#' is not a valid date, so we cannot compare them.",
field : arguments.field,
validationType : getName(),
rejectedValue : ( arguments.targetValue ),
validationData : arguments.validationData,
errorMetadata : { "afterOrEqual" : arguments.targetValue }
}
)
);
return false;
}

// The compare value is set or it can be another field
Expand Down
16 changes: 13 additions & 3 deletions models/validators/DateEqualsValidator.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,22 @@ component extends="BaseValidator" accessors="true" singleton {
if ( isNull( arguments.targetValue ) || isNullOrEmpty( arguments.targetValue ) ) {
return true;
}

// If not a date, throw it
if ( !isDate( arguments.targetValue ) ) {
throw(
message = "The date you sent is an invalid date [#arguments.targetValue#]",
type = "InvalidValidationData"
validationResult.addError(
validationResult.newError(
argumentCollection = {
message : "The '#arguments.targetValue#' is not a valid date, so we cannot compare them.",
field : arguments.field,
validationType : getName(),
rejectedValue : ( arguments.targetValue ),
validationData : arguments.validationData,
errorMetadata : { "afterOrEqual" : arguments.targetValue }
}
)
);
return false;
}

// The compare value is set or it can be another field
Expand Down
Loading

0 comments on commit 615d912

Please sign in to comment.