Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ jobs:
box server start serverConfigFile="server-${{ matrix.cfengine }}.json" --noSaveSettings --debug
curl --fail-with-body http://127.0.0.1:60299/tests/index.cfm

- name: Run Adobe Full Null Regression
if: ${{ matrix.cfengine == 'adobe@2025' }}
run: |
curl --fail-with-body http://127.0.0.1:60299/tests/full-null/index.cfm

- name: Run Tests
run: |
mkdir -p test-harness/tests/results
Expand Down
63 changes: 45 additions & 18 deletions interceptors/Mementifier.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,21 @@ component {
arguments.entity.$injectMixin( "$getDeepProperties", variables.$getDeepProperties );

// We do simple date formatters as they are faster than CFML methods
var dateMask = isNull( this.memento.dateMask ) ? variables.settings.dateMask : this.memento.dateMask;
var timeMask = isNull( this.memento.timeMask ) ? variables.settings.timeMask : this.memento.timeMask;
var entityMemento = (
structKeyExists( arguments.entity, "memento" ) && isStruct( arguments.entity.memento )
? arguments.entity.memento
: {}
);
var dateMask = (
structKeyExists( entityMemento, "dateMask" ) && !isNull( entityMemento.dateMask )
? entityMemento.dateMask
: variables.settings.dateMask
);
var timeMask = (
structKeyExists( entityMemento, "timeMask" ) && !isNull( entityMemento.timeMask )
? entityMemento.timeMask
: variables.settings.timeMask
);
arguments.entity.$FORMATTER_ISO8601 = variables.jSimpleDateFormat.init( "yyyy-MM-dd'T'HH:mm:ssXXX" );
arguments.entity.$FORMATTER_CUSTOM = variables.jSimpleDateFormat.init( "#dateMask# #timeMask#" );

Expand Down Expand Up @@ -145,19 +158,30 @@ component {

// Param Default Memento Settings
// We do it here, because ACF caches crap!
var thisMemento = {
"autoCastBooleans" : isNull( this.memento.autoCastBooleans ) ? variables.$mementifierSettings.autoCastBooleans : this.memento.autoCastBooleans,
"dateMask" : isNull( this.memento.dateMask ) ? variables.$mementifierSettings.dateMask : this.memento.dateMask,
"defaults" : isNull( this.memento.defaults ) ? {} : this.memento.defaults,
"defaultIncludes" : isNull( this.memento.defaultIncludes ) ? [] : this.memento.defaultIncludes,
"defaultExcludes" : isNull( this.memento.defaultExcludes ) ? [] : this.memento.defaultExcludes,
"iso8601Format" : isNull( this.memento.iso8601Format ) ? variables.$mementifierSettings.iso8601Format : this.memento.iso8601Format,
"mappers" : isNull( this.memento.mappers ) ? {} : this.memento.mappers,
"neverInclude" : isNull( this.memento.neverInclude ) ? [] : this.memento.neverInclude,
"ormAutoIncludes" : isNull( this.memento.ormAutoIncludes ) ? variables.$mementifierSettings.ormAutoIncludes : this.memento.ormAutoIncludes,
"profiles" : isNull( this.memento.profiles ) ? {} : this.memento.profiles,
"timeMask" : isNull( this.memento.timeMask ) ? variables.$mementifierSettings.timeMask : this.memento.timeMask,
"trustedGetters" : isNull( this.memento.trustedGetters ) ? variables.$mementifierSettings.trustedGetters : this.memento.trustedGetters
var entityMemento = structKeyExists( this, "memento" ) && isStruct( this.memento ) ? this.memento : {};
var thisMemento = {
"autoCastBooleans" : entityMemento.keyExists( "autoCastBooleans" ) && !isNull(
entityMemento.autoCastBooleans
) ? entityMemento.autoCastBooleans : variables.$mementifierSettings.autoCastBooleans,
"dateMask" : entityMemento.keyExists( "dateMask" ) && !isNull( entityMemento.dateMask ) ? entityMemento.dateMask : variables.$mementifierSettings.dateMask,
"defaults" : entityMemento.keyExists( "defaults" ) && !isNull( entityMemento.defaults ) ? entityMemento.defaults : {},
"defaultIncludes" : entityMemento.keyExists( "defaultIncludes" ) && !isNull(
entityMemento.defaultIncludes
) ? entityMemento.defaultIncludes : [],
"defaultExcludes" : entityMemento.keyExists( "defaultExcludes" ) && !isNull(
entityMemento.defaultExcludes
) ? entityMemento.defaultExcludes : [],
"iso8601Format" : entityMemento.keyExists( "iso8601Format" ) && !isNull( entityMemento.iso8601Format ) ? entityMemento.iso8601Format : variables.$mementifierSettings.iso8601Format,
"mappers" : entityMemento.keyExists( "mappers" ) && !isNull( entityMemento.mappers ) ? entityMemento.mappers : {},
"neverInclude" : entityMemento.keyExists( "neverInclude" ) && !isNull( entityMemento.neverInclude ) ? entityMemento.neverInclude : [],
"ormAutoIncludes" : entityMemento.keyExists( "ormAutoIncludes" ) && !isNull(
entityMemento.ormAutoIncludes
) ? entityMemento.ormAutoIncludes : variables.$mementifierSettings.ormAutoIncludes,
"profiles" : entityMemento.keyExists( "profiles" ) && !isNull( entityMemento.profiles ) ? entityMemento.profiles : {},
"timeMask" : entityMemento.keyExists( "timeMask" ) && !isNull( entityMemento.timeMask ) ? entityMemento.timeMask : variables.$mementifierSettings.timeMask,
"trustedGetters" : entityMemento.keyExists( "trustedGetters" ) && !isNull(
entityMemento.trustedGetters
) ? entityMemento.trustedGetters : variables.$mementifierSettings.trustedGetters
};

// Param arguments according to instance > settings chain precedence
Expand Down Expand Up @@ -310,7 +334,6 @@ component {
reFind( "^\d{4}-\d{2}-\d{2}", thisValue ) // ACF date format begins with YYYY-MM-DD
)
) {

var dateInstance = thisValue;

try {
Expand All @@ -319,7 +342,9 @@ component {
// Iso Date?
if ( arguments.iso8601Format ) {
// we need to convert trailing Zulu time designations offset or JS libs like Moment will not know how to parse it
result[ thisAlias ] = this.$FORMATTER_ISO8601.format( dateInstance ).replace( "Z", "+00:00" );
result[ thisAlias ] = this.$FORMATTER_ISO8601
.format( dateInstance )
.replace( "Z", "+00:00" );
} else {
result[ thisAlias ] = customDateFormatter.format( dateInstance );
}
Expand Down Expand Up @@ -444,7 +469,9 @@ component {
* @return The array of default includes for the ORM entity where this function is injected into
*/
array function $buildOrmIncludes(){
var thisName = isNull( variables.entityName ) ? "" : variables.entityName;
var thisName = (
structKeyExists( variables, "entityName" ) && !isNull( variables.entityName ) ? variables.entityName : ""
);
if ( !len( thisName ) ) {
var md = getMetadata( this );
thisName = ( md.keyExists( "entityName" ) ? md.entityName : listLast( md.name, "." ) );
Expand Down
12 changes: 12 additions & 0 deletions test-harness/models/PartialMemento.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
component accessors="true" {

property name="id";

this.memento = { defaultIncludes : [ "id" ] };

function init(){
variables.id = "partial-memento";
return this;
}

}
12 changes: 12 additions & 0 deletions test-harness/tests/full-null/Application.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
component {

moduleRoot = createObject( "java", "java.io.File" )
.init( getDirectoryFromPath( getCurrentTemplatePath() ) & "../../../" )
.getCanonicalPath();

this.name = "mementifier-full-null-regression-#hash( moduleRoot )#";
this.enableNullSupport = true;
this.mappings[ "/mementifier" ] = moduleRoot;
this.mappings[ "/fullnull" ] = getDirectoryFromPath( getCurrentTemplatePath() );

}
12 changes: 12 additions & 0 deletions test-harness/tests/full-null/PartialMemento.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
component accessors="true" {

property name="id";

this.memento = { defaultIncludes : [ "id" ] };

function init(){
variables.id = "partial-memento";
return this;
}

}
9 changes: 9 additions & 0 deletions test-harness/tests/full-null/TestMementifier.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
component extends="mementifier.interceptors.Mementifier" {

function init( required struct settings ){
variables.settings = arguments.settings;
configure();
return this;
}

}
24 changes: 24 additions & 0 deletions test-harness/tests/full-null/index.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<cfsetting showDebugOutput="false">
<cfscript>
settings = {
iso8601Format : false,
dateMask : "yyyy-MM-dd",
timeMask : "HH:mm:ss",
ormAutoIncludes : false,
nullDefaultValue : "",
trustedGetters : false,
convertToTimezone : "",
autoCastBooleans : true
};

model = new fullnull.PartialMemento();
interceptor = new fullnull.TestMementifier( settings );
interceptor.processMemento( model );
memento = model.getMemento();

if ( !memento.keyExists( "id" ) || memento.id != "partial-memento" ) {
throw( type = "RegressionFailure", message = "Partial memento settings failed with full null support." );
}

writeOutput( "PASS" );
</cfscript>
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ component extends="coldbox.system.testing.BaseInterceptorTest" interceptor="meme

function run(){
describe( "Mementifier", function(){
it( "supports partial memento settings with full null support", function(){
var model = getWireBox().getInstance( "PartialMemento" );

expect( model.getMemento() ).toBeStruct().toHaveKey( "id" );
} );

it( "Won't modify includes/excludes arrays", function(){
var includesList = "userId,blogUrl,fname:firstName,lname:lastName";
var excludesList = "userId,blogUrl,fname:firstName,lname:lastName";
Expand Down
Loading