diff --git a/CHANGELOG.md b/CHANGELOG.md index 268bc7d..f51c5a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v3.5.5 + +* [#73](https://github.com/pixl8/preside-ext-data-api/issues/73) Exit early from field rendering to avoid needless handler invocation + ## v3.5.4 * [#71](https://github.com/pixl8/preside-ext-data-api/issues/71) Remove unecessary helper methods diff --git a/config/Config.cfc b/config/Config.cfc index 78a1e62..ee4b44b 100755 --- a/config/Config.cfc +++ b/config/Config.cfc @@ -16,8 +16,9 @@ component { settings.features.restTokenAuth.enabled = true; settings.features.dataApiQueue = settings.features.dataApiQueue ?: { enabled=true }; - settings.features.dataApiUseNullForNumerics = settings.features.dataApiUseNullForNumerics ?: { enabled=true }; - settings.features.dataApiUseNullForStrings = settings.features.dataApiUseNullForStrings ?: { enabled=true }; + settings.features.dataApiUseNullForNumerics = settings.features.dataApiUseNullForNumerics ?: { enabled=true }; + settings.features.dataApiUseNullForStrings = settings.features.dataApiUseNullForStrings ?: { enabled=true }; + settings.features.dataApiFormulaFieldsForAtomic = settings.features.dataApiFormulaFieldsForAtomic ?: { enabled=true }; } private void function _setupRestApis( required struct settings ) { diff --git a/services/DataApiConfigurationService.cfc b/services/DataApiConfigurationService.cfc index af1da9f..a4ca816 100755 --- a/services/DataApiConfigurationService.cfc +++ b/services/DataApiConfigurationService.cfc @@ -127,6 +127,27 @@ component { } ); } + public array function getEntityFormulaFields( required string entity, boolean aliases=false ) { + var args = arguments; + var cacheKey = "getEntityFormulaFields" & _getDataApiNamespace() & args.entity & args.aliases; + + return _simpleLocalCache( cacheKey, function(){ + var entities = getEntities(); + var fields = entities[ args.entity ].formulaFields ?: []; + + if ( !args.aliases ) { + return fields; + } + + var aliases = []; + var fieldSettings = getFieldSettings( args.entity ); + for( var field in fields ) { + ArrayAppend( aliases, fieldSettings[ field ].alias ?: field ); + } + return aliases; + } ); + } + public array function getFilterFields( required string entity ) { var args = arguments; var cacheKey = "getFilterFields" & _getDataApiNamespace() & args.entity; @@ -235,6 +256,10 @@ component { entities[ entityName ].upsertFields = _cleanupUpsertFields( objectName, entities[ entityName ].upsertFields, entities[ entityName ].allowIdInsert ); + if ( $isFeatureEnabled( "dataApiFormulaFieldsForAtomic" ) ) { + entities[ entityName ].formulaFields = _formulaFields( objectName, namespace ); + } + if ( excludeFields.len() ) { for( var field in ListToArray( excludeFields ) ) { entities[ entityName ].selectFields.delete( field ); @@ -648,6 +673,22 @@ component { return fields; } + private array function _formulaFields( required string objectName, required string namespace ) { + var props = $getPresideObjectService().getObjectProperties( arguments.objectName ); + var propEnabledKey = "dataApiEnabled#arguments.namespace#"; + var fields = []; + + for( var fieldName in props ) { + if ( ( len( trim( props[ fieldName ].formula ?: "" ) ) || len( trim( props[ fieldName ].default ?: "" ) ) ) && + ( !isBoolean( props[ fieldName ][ propEnabledKey ] ?: "" ) || !props[ fieldName ][ propEnabledKey ] ) + ) { + arrayAppend( fields, fieldName ); + } + } + + return fields; + } + private array function _cleanupUpsertFields( required string objectName, required array fields, required boolean allowIdInsert ) { var props = $getPresideObjectService().getObjectProperties( objectName ); var idField = $getPresideObjectService().getIdField( objectName ); diff --git a/services/DataApiQueueService.cfc b/services/DataApiQueueService.cfc index db309dd..f209a93 100755 --- a/services/DataApiQueueService.cfc +++ b/services/DataApiQueueService.cfc @@ -53,7 +53,7 @@ component { switch( record.operation ) { case "delete": - returnStruct.data.append( { + StructAppend( returnStruct.data, { operation = "delete" , entity = entity , recordId = record.record_id @@ -72,14 +72,24 @@ component { }; if ( queueSettings.atomicChanges && Len( Trim( record.data ) ) ) { try { - dataEntry.record = _aliasFields( record.object_name, DeserializeJson( record.data ) ); + var recordData = DeserializeJson( record.data ); + + if ( $isFeatureEnabled( "dataApiFormulaFieldsForAtomic" ) ) { + var formulaFields = configSvc.getEntityFormulaFields( entity=entity ); + + if ( ArrayLen( formulaFields ) ) { + StructAppend( recordData, apiSvc.getSingleRecord( entity=entity, recordId=record.record_id, fields=formulaFields ), false ); + } + } + + dataEntry.record = _aliasFields( record.object_name, recordData ); } catch( any e ) { dataEntry.record = record.data; } } else { dataEntry.record = apiSvc.getSingleRecord( entity=entity, recordId=record.record_id, fields=[] ) } - returnStruct.data.append( dataEntry ); + StructAppend( returnStruct.data, dataEntry ); } } } @@ -391,7 +401,7 @@ component { var configService = _getConfigService(); for( var key in arguments.data ) { var alias = configService.getAliasForPropertyName( arguments.objectName, key ); - aliased[ alias ] = arguments.data[ key ]; + aliased[ alias ] = arguments.data[ key ] ?: nullValue(); } return aliased; diff --git a/services/DataApiService.cfc b/services/DataApiService.cfc index 0cbc3a2..b6c317d 100644 --- a/services/DataApiService.cfc +++ b/services/DataApiService.cfc @@ -336,6 +336,10 @@ component { return $isFeatureEnabled( "dataApiUseNullForStrings" ) ? NullValue() : ""; } + if ( !Len( arguments.value ?: "" ) ) { + return $isFeatureEnabled( "dataApiUseNullForStrings" ) ? NullValue() : ""; + } + if ( $getContentRendererService().rendererExists( renderer, "dataapi" ) ) { try { var renderedContent = $renderContent( renderer, arguments.value, "dataapi", arguments.fieldSettings );