Skip to content

Commit 0887fe4

Browse files
committed
fix(BoxLang): BoxLang Prime compatibility
1 parent 0efbecb commit 0887fe4

19 files changed

+246
-88
lines changed

.github/workflows/cron.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
experimental: true
3636
- cfengine: "boxlang@1"
3737
coldbox: "coldbox@^8"
38-
experimental: true
38+
experimental: false
3939
- cfengine: "boxlang@1"
4040
coldbox: "coldbox@be"
4141
experimental: true

.github/workflows/pr.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ jobs:
2121
matrix:
2222
cfengine: ["lucee@5", "lucee@6", "adobe@2021", "adobe@2023", "adobe@2025", "boxlang-cfml@1"]
2323
coldbox: ["coldbox@^7", "coldbox@^8"]
24+
include:
25+
- cfengine: "boxlang@1"
26+
coldbox: "coldbox@^8"
2427
services:
2528
mysql:
2629
image: mysql:5.7

.github/workflows/release.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ jobs:
1616
matrix:
1717
cfengine: ["lucee@5", "lucee@6", "adobe@2021", "adobe@2023", "adobe@2025", "boxlang-cfml@1"]
1818
coldbox: ["coldbox@^7", "coldbox@^8"]
19+
include:
20+
- cfengine: "boxlang@1"
21+
coldbox: "coldbox@^8"
1922
services:
2023
mysql:
2124
image: mysql:5.7

box.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
},
3030
"type":"modules",
3131
"dependencies":{
32-
"qb":"^13.0.12",
32+
"qb":"^13.0.16",
3333
"str":"^4.0.0",
3434
"mementifier":"^3.0.0"
3535
},

models/BaseEntity.cfc

Lines changed: 140 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ component accessors="true" {
295295
setUpMementifier();
296296
fireEvent( "instanceReady", { entity : this } );
297297
}
298+
for ( var key in retrieveAttributeNames( withVirtualColumns = false ) ) {
299+
structDelete( variables, key );
300+
}
298301
}
299302

300303
/**
@@ -2311,8 +2314,12 @@ component accessors="true" {
23112314
.addSelect( retrieveQualifiedColumns() )
23122315
.with( variables._with );
23132316

2314-
if ( variables._meta.originalMetadata.keyExists( "grammar" ) ) {
2315-
newBuilder.setGrammar( variables._wirebox.getInstance( variables._meta.originalMetadata.grammar ) );
2317+
if ( hasMetadataAttribute( "grammar", variables._meta.originalMetadata ) ) {
2318+
newBuilder.setGrammar(
2319+
variables._wirebox.getInstance(
2320+
getMetadataAttribute( key = "grammar", metadata = variables._meta.originalMetadata )
2321+
)
2322+
);
23162323
}
23172324

23182325
newBuilder.applyInheritanceJoins();
@@ -2723,51 +2730,81 @@ component accessors="true" {
27232730

27242731
if ( !isStruct( variables._meta ) || structIsEmpty( variables._meta ) ) {
27252732
variables._meta = duplicate(
2726-
variables._cache.getOrSet( "quick-metadata:#variables._mapping#", function() {
2733+
variables._cache.getOrSet( "quick-metadata:#variables._mapping#_#createUUID()#", function() {
27272734
var util = variables._wirebox.getUtility();
27282735
var meta = {};
27292736
meta[ "originalMetadata" ] = util.getInheritedMetadata( this );
27302737
meta[ "localMetadata" ] = getMetadata( this );
2731-
if (
2732-
!meta[ "localMetadata" ].keyExists( "accessors" ) ||
2733-
meta[ "localMetadata" ].accessors == false
2734-
) {
2738+
var hasAccessorsEnabled = getMetadataAttribute(
2739+
"accessors",
2740+
false,
2741+
meta.localMetadata
2742+
);
2743+
if ( !hasAccessorsEnabled ) {
27352744
throw(
27362745
type = "QuickAccessorsMissing",
27372746
message = 'This instance is missing `accessors="true"` in the component metadata. This is required for Quick to work properly. Please add it to your component metadata and reinit your application.'
27382747
);
27392748
}
2740-
meta[ "fullName" ] = meta.originalMetadata.fullname;
2741-
param meta.originalMetadata.mapping = listLast( meta.originalMetadata.fullname, "." );
2742-
meta[ "mapping" ] = meta.originalMetadata.mapping;
2743-
param meta.originalMetadata.entityName = listLast( meta.originalMetadata.name, "." );
2744-
meta[ "entityName" ] = meta.originalMetadata.entityName;
2745-
param meta.originalMetadata.table = variables._str.plural( variables._str.snake( meta.entityName ) );
2746-
meta[ "table" ] = meta.originalMetadata.table;
2747-
param meta.originalMetadata.readonly = false;
2748-
meta[ "readonly" ] = meta.originalMetadata.readonly;
2749-
param meta.originalMetadata.joincolumn = "";
2750-
param meta.originalMetadata.discriminatorValue = "";
2751-
param meta.originalMetadata.singleTableInheritance = false;
2752-
param meta.originalMetadata.extends = "";
2753-
param meta.originalMetadata.functions = [];
2754-
meta[ "hasParentEntity" ] = !!len( meta.originalMetadata.joincolumn );
2749+
meta[ "fullName" ] = getMetadataAttribute( key = "fullname", metadata = meta.originalMetadata );
2750+
meta[ "mapping" ] = getMetadataAttribute(
2751+
"mapping",
2752+
listLast( meta.fullName, "." ),
2753+
meta.originalMetadata
2754+
);
2755+
meta[ "entityName" ] = getMetadataAttribute(
2756+
"entityName",
2757+
listLast( getMetadataAttribute( key = "name", metadata = meta.originalMetadata ), "." ),
2758+
meta.originalMetadata
2759+
);
2760+
meta[ "table" ] = getMetadataAttribute(
2761+
"table",
2762+
variables._str.plural( variables._str.snake( meta.entityName ) ),
2763+
meta.originalMetadata
2764+
);
2765+
meta[ "readonly" ] = getMetadataAttribute(
2766+
"readonly",
2767+
false,
2768+
meta.originalMetadata
2769+
);
2770+
meta[ "joinColumn" ] = getMetadataAttribute(
2771+
"joinColumn",
2772+
"",
2773+
meta.originalMetadata
2774+
);
2775+
meta[ "discriminatorValue" ] = getMetadataAttribute(
2776+
"discriminatorValue",
2777+
"",
2778+
meta.originalMetadata
2779+
);
2780+
meta[ "singleTableInheritance" ] = getMetadataAttribute(
2781+
"singleTableInheritance",
2782+
false,
2783+
meta.originalMetadata
2784+
);
2785+
meta[ "extends" ] = getMetadataAttribute( "extends", "", meta.originalMetadata );
2786+
meta[ "functions" ] = getMetadataAttribute(
2787+
"functions",
2788+
[],
2789+
meta.originalMetadata
2790+
);
2791+
meta[ "hasParentEntity" ] = !!len( meta.joinColumn );
27552792
if ( meta.hasParentEntity ) {
27562793
var reference = variables._wirebox.getInstance(
2757-
name = meta.localMetadata.extends.fullName,
2794+
name = getMetadataAttribute( key = "fullName", metadata = meta.localMetadata.extends ),
27582795
initArguments = { "meta" : {}, "shallow" : true }
27592796
);
27602797

27612798
meta[ "parentDefinition" ] = {
27622799
"meta" : reference.get_Meta(),
27632800
"key" : reference.keyNames()[ 1 ],
2764-
"joincolumn" : meta.originalMetadata.joincolumn
2801+
"joincolumn" : meta.joinColumn
27652802
};
27662803

2767-
if ( len( meta.originalMetadata.discriminatorValue ) ) {
2804+
if ( len( meta.discriminatorValue ) ) {
27682805
try {
2769-
var parentMeta = getComponentMetadata( meta.parentDefinition.meta.fullName );
2770-
meta.parentDefinition[ "discriminatorValue" ] = meta.originalMetadata.discriminatorValue;
2806+
var parentMeta = util.getInheritedMetaData( meta.parentDefinition.meta.fullName );
2807+
meta.parentDefinition[ "discriminatorValue" ] = meta.discriminatorValue;
27712808
meta.parentDefinition[ "discriminatorColumn" ] = parentMeta.discriminatorColumn;
27722809
} catch ( any e ) {
27732810
throw(
@@ -2781,7 +2818,7 @@ component accessors="true" {
27812818

27822819
var baseEntityFunctionNames = variables._cache.getOrSet( "quick-metadata:BaseEntity", function() {
27832820
return arrayReduce(
2784-
getComponentMetadata( "quick.models.BaseEntity" ).functions,
2821+
util.getInheritedMetaData( "quick.models.BaseEntity" ).functions,
27852822
function( acc, func ) {
27862823
arguments.acc[ arguments.func.name ] = "";
27872824
return arguments.acc;
@@ -2790,7 +2827,7 @@ component accessors="true" {
27902827
);
27912828
} );
27922829
meta[ "functionNames" ] = generateFunctionNameArray(
2793-
from = meta.originalMetadata.functions,
2830+
from = meta.functions,
27942831
without = baseEntityFunctionNames
27952832
);
27962833

@@ -2799,8 +2836,13 @@ component accessors="true" {
27992836
meta[ "attributes" ] = generateAttributesFromProperties(
28002837
meta.hasParentEntity ? meta.localMetadata.properties : meta.originalMetadata.properties
28012838
);
2802-
if ( structKeyExists( meta.localMetadata, "discriminatorColumn" ) ) {
2803-
meta.attributes[ meta.localMetaData.discriminatorColumn ] = paramAttribute( { "name" : meta.localMetaData.discriminatorColumn } );
2839+
if ( hasMetadataAttribute( "discriminatorColumn", meta.localMetadata ) ) {
2840+
var discriminatorColumn = getMetadataAttribute(
2841+
key = "discriminatorColumn",
2842+
metadata = meta.localMetadata
2843+
);
2844+
meta.attributes[ discriminatorColumn ] = paramAttribute( { "name" : discriminatorColumn } );
2845+
meta[ "discriminatorColumn" ] = discriminatorColumn;
28042846
}
28052847
arrayWrap( variables._key ).each( function( key ) {
28062848
if ( !meta.attributes.keyExists( key ) ) {
@@ -2826,8 +2868,10 @@ component accessors="true" {
28262868
}
28272869

28282870
param variables._queryOptions = {};
2829-
if ( variables._queryOptions.isEmpty() && variables._meta.originalMetadata.keyExists( "datasource" ) ) {
2830-
variables._queryOptions = { datasource : variables._meta.originalMetadata.datasource };
2871+
if ( variables._queryOptions.isEmpty() && hasMetadataAttribute( "datasource", variables._meta.originalMetadata ) ) {
2872+
variables._queryOptions = {
2873+
"datasource" : getMetadataAttribute( key = "datasource", metadata = variables._meta.originalMetadata )
2874+
};
28312875
}
28322876
variables._readonly = variables._meta.readonly;
28332877
explodeAttributesMetadata( variables._meta.attributes );
@@ -2872,9 +2916,18 @@ component accessors="true" {
28722916

28732917
private struct function generateCastsFromProperties( required array properties ) {
28742918
return arguments.properties.reduce( function( acc, prop ) {
2919+
if ( arguments.prop.keyExists( "annotations" ) ) {
2920+
structAppend(
2921+
arguments.prop,
2922+
arguments.prop.annotations,
2923+
true
2924+
);
2925+
}
2926+
28752927
if ( !arguments.prop.keyExists( "casts" ) || arguments.prop.casts == "" ) {
28762928
return arguments.acc;
28772929
}
2930+
28782931
arguments.acc[ arguments.prop.name ] = arguments.prop.casts;
28792932
return arguments.acc;
28802933
}, {} );
@@ -2925,6 +2978,15 @@ component accessors="true" {
29252978
* @return An attribute struct with all the keys needed.
29262979
*/
29272980
private struct function paramAttribute( required struct attr ) {
2981+
if ( arguments.attr.keyExists( "annotations" ) ) {
2982+
structAppend(
2983+
arguments.attr,
2984+
arguments.attr.annotations,
2985+
true
2986+
);
2987+
structDelete( arguments.attr, "annotations" );
2988+
}
2989+
29282990
param attr.column = arguments.attr.name;
29292991
param attr.persistent = true;
29302992
param attr.nullValue = "";
@@ -2972,11 +3034,11 @@ component accessors="true" {
29723034
}
29733035

29743036
public boolean function isDiscriminatedChild() {
2975-
return hasParentEntity() && variables._meta.localMetadata.keyExists( "discriminatorValue" );
3037+
return hasParentEntity() && hasMetadataAttribute( "discriminatorValue", variables._meta.localMetadata );
29763038
}
29773039

29783040
public boolean function isDiscriminatedParent() {
2979-
return variables._meta.localMetadata.keyExists( "discriminatorColumn" )
3041+
return hasMetadataAttribute( "discriminatorColumn", variables._meta.localMetadata )
29803042
&& variables._discriminators.len() > 0;
29813043
}
29823044

@@ -2996,13 +3058,13 @@ component accessors="true" {
29963058
// Can be ignored for singleTableInheritance since there's no join
29973059
if (
29983060
!isSingleTableInheritance() && (
2999-
!structKeyExists( childMeta, "joincolumn" ) ||
3000-
!structKeyExists( childMeta, "discriminatorValue" )
3061+
!hasMetadataAttribute( "joincolumn", childMeta ) ||
3062+
!hasMetadataAttribute( "discriminatorValue", childMeta )
30013063
)
30023064
) {
30033065
throw(
30043066
type = "QuickParentInstantiationException",
3005-
message = "Failed to instantiate the parent entity [#variables._meta.fullName#]. The discriminated child class [#childMeta.fullName#] did not contain either a `joinColumn` or `discriminatorValue` attribute"
3067+
message = "Failed to instantiate the parent entity [#variables._meta.fullName#]. The discriminated child class [#getMetadataAttribute( "fullName", "[unknown]", childMeta )#] did not contain either a `joinColumn` or `discriminatorValue` attribute"
30063068
);
30073069
}
30083070
var childAttributes = childClass
@@ -3021,12 +3083,16 @@ component accessors="true" {
30213083
return !arrayContainsNoCase( localColumns, column );
30223084
} );
30233085

3024-
acc[ childMeta.discriminatorValue ] = {
3025-
"mapping" : childMeta.fullName,
3026-
"table" : ( childMeta.keyExists( "table" ) ? childMeta.table : variables._meta.table ),
3086+
acc[ getMetadataAttribute( key = "discriminatorValue", metadata = childMeta ) ] = {
3087+
"mapping" : getMetadataAttribute( key = "fullName", metadata = childMeta ),
3088+
"table" : getMetadataAttribute(
3089+
"table",
3090+
variables._meta.table,
3091+
childMeta
3092+
),
30273093
"joincolumn" : (
3028-
childMeta.keyExists( "joinColumn" ) ? childClass.qualifyColumn(
3029-
column = childMeta.joinColumn,
3094+
hasMetadataAttribute( "joinColumn", childMeta ) ? childClass.qualifyColumn(
3095+
column = getMetadataAttribute( key = "joinColumn", metadata = childMeta ),
30303096
useParentLookup = false
30313097
) : ""
30323098
),
@@ -3221,7 +3287,7 @@ component accessors="true" {
32213287
private void function guardKeyHasNoDefaultValue( required struct attributes ) {
32223288
for ( var keyName in keyNames() ) {
32233289
if ( attributes.keyExists( keyName ) ) {
3224-
if ( attributes[ keyName ].keyExists( "default" ) ) {
3290+
if ( attributes[ keyName ].keyExists( "default" ) && !isNull( attributes[ keyName ].default ) ) {
32253291
throw(
32263292
type = "QuickEntityDefaultedKey",
32273293
message = "The key value [#keyName#] has a default value. Default values on keys prevents Quick from working as expected. Remove the default value to continue."
@@ -3621,7 +3687,36 @@ component accessors="true" {
36213687
* since the data for each sub entity originates from a single table
36223688
*/
36233689
public boolean function isSingleTableInheritance() {
3624-
return variables._meta.originalMetadata.singleTableInheritance;
3690+
return variables._meta.singleTableInheritance;
3691+
}
3692+
3693+
private boolean function hasMetadataAttribute(
3694+
required string key,
3695+
struct metadata = variables._meta.localMetadata
3696+
) {
3697+
return arguments.metadata.keyExists( arguments.key ) || (
3698+
arguments.metadata.keyExists( "annotations" ) &&
3699+
arguments.metadata.annotations.keyExists( arguments.key )
3700+
);
3701+
}
3702+
3703+
private any function getMetadataAttribute(
3704+
required string key,
3705+
any defaultValue,
3706+
struct metadata = variables._meta.localMetadata
3707+
) {
3708+
if ( arguments.metadata.keyExists( "annotations" ) && arguments.metadata.annotations.keyExists( arguments.key ) ) {
3709+
return arguments.metadata.annotations[ arguments.key ];
3710+
} else if ( arguments.metadata.keyExists( arguments.key ) ) {
3711+
return arguments.metadata[ arguments.key ];
3712+
} else if ( !isNull( arguments.defaultValue ) ) {
3713+
return arguments.defaultValue;
3714+
} else {
3715+
throw(
3716+
type = "MetadataAttributeNotFound",
3717+
message = "The metadata attribute [#arguments.key#] was not found."
3718+
);
3719+
}
36253720
}
36263721

36273722
}

models/QuickBuilder.cfc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,6 @@ component accessors="true" transientCache="false" {
944944
*/
945945
public any function first( struct options = {} ) {
946946
activateGlobalScopes();
947-
948947
var result = variables.qb.first( argumentCollection = arguments );
949948
return structIsEmpty( result ) ? javacast( "null", "" ) : handleTransformations(
950949
// wrap the single entity in an array to eager load, then grab it out again
@@ -1306,7 +1305,7 @@ component accessors="true" transientCache="false" {
13061305
* @return quick.models.BaseEntity
13071306
*/
13081307
public any function withoutGlobalScope( any name ) {
1309-
if ( !structKeyExists( arguments, "name" ) ) {
1308+
if ( !structKeyExists( arguments, "name" ) || isNull( arguments.name ) ) {
13101309
variables._globalScopeExcludeAll = true;
13111310
return this;
13121311
}
@@ -1389,15 +1388,15 @@ component accessors="true" transientCache="false" {
13891388
&&
13901389
getEntity().isDiscriminatedParent()
13911390
&&
1392-
structKeyExists( arguments.data, listLast( getEntity().get_meta().localMetadata.discriminatorColumn, "." ) )
1391+
structKeyExists( arguments.data, listLast( getEntity().get_meta().discriminatorColumn, "." ) )
13931392
&&
13941393
structKeyExists(
13951394
getEntity().getDiscriminations(),
1396-
arguments.data[ listLast( getEntity().get_meta().localMetadata.discriminatorColumn, "." ) ]
1395+
arguments.data[ listLast( getEntity().get_meta().discriminatorColumn, "." ) ]
13971396
)
13981397
) {
13991398
var discrimination = getEntity().getDiscriminations()[
1400-
arguments.data[ listLast( getEntity().get_meta().localMetadata.discriminatorColumn, "." ) ]
1399+
arguments.data[ listLast( getEntity().get_meta().discriminatorColumn, "." ) ]
14011400
];
14021401

14031402
var childClass = variables._wirebox.getInstance( discrimination.mapping );

tests/resources/ModuleIntegrationSpec.cfc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,9 @@ component extends="coldbox.system.testing.BaseTestCase" appMapping="/app" {
7171
return arraySlice( createObject( "java", "java.util.HashSet" ).init( arguments.items ).toArray(), 1 );
7272
}
7373

74+
private boolean function isBoxLangPrime() {
75+
return isBoxLang() && !server.boxlang.modules.keyExists( "compat-cfml" );
76+
}
77+
7478
}
79+

0 commit comments

Comments
 (0)