From b98aa9f564efb585ecba0ae5427d02f9fab72d3e Mon Sep 17 00:00:00 2001 From: Test Date: Fri, 27 Mar 2026 15:34:57 +0000 Subject: [PATCH 01/15] Upgrade ColdBox dependency from 5.4.0 to 6.9.0 with compatibility shims ColdBox 6.0 introduced significant breaking changes. This commit updates the coldboxModifications layer to bridge these changes while preserving Preside's existing API surface. Shims added to coldboxModifications: - InterceptorService: processState() calls super.announce() (renamed in CB6); announce() override suppresses events during interceptor registration - InterceptorState: accepts both 'data' (CB6) and 'interceptData' (CB5) params - Controller: restores getSettingStructure(), adapts getSetting() to handle both CB5 (name, fwSetting, defaultValue) and CB6 (name, defaultValue) signatures, lazy-inits viewsRefMap/layoutsRefMap removed in CB6 - EventHandler (new): restores setNextEvent() and getModel() for handlers - Interceptor (new): eagerly loads application helpers in constructor (CB6 deferred this to a lazy event, breaking startup interceptors) - Provider (new): restores get() renamed to $get() in CB6 - Builder: overrides getProviderDSL() to use Preside Provider shim - HandlerService: newHandler() uses Preside EventHandler for virtual inheritance - RoutingService: onRequestCapture() renamed to requestCapture() (CB6 API) - Injector: aliases variables.objectBuilder (renamed from builder in CB6), calls processEagerInits() after processMappings() (split in CB6) - DSL Builders: added targetID parameter to process() (CB6 interface change) - Renderer: getModel() changed to getInstance() - WireBox config: mapDirectory filter wraps file paths to component dot-paths (CB6 changed the filter callback contract) - presideProxies.cfm: added getModel() helper proxy for all views/handlers - errorReport.cfm: replaced missing CB6 CSS include with simple rethrow - Config: onInvalidEvent renamed to invalidEventHandler (CB6) - Router: removed setUniqueUrls() (removed in CB6), super.getModel() to super.getInstance() Also adds ColdBox version display to admin System Information page. Co-Authored-By: Claude Opus 4.6 (1M context) --- box.json | 2 +- system/coldboxModifications/Controller.cfc | 24 +- .../DelayedInjectorDsl.cfc | 2 +- system/coldboxModifications/EventHandler.cfc | 38 +++ .../FeatureDependentDsl.cfc | 2 +- system/coldboxModifications/Interceptor.cfc | 31 ++ .../coldboxModifications/InterceptorState.cfc | 13 +- .../coldboxModifications/LegacyDslBuilder.cfc | 2 +- .../PresideWireboxDsl.cfc | 2 +- .../includes/errorReport.cfm | 268 +----------------- system/coldboxModifications/ioc/Builder.cfc | 30 ++ system/coldboxModifications/ioc/Injector.cfc | 5 +- system/coldboxModifications/ioc/Provider.cfc | 13 + .../services/HandlerService.cfc | 32 +++ .../services/InterceptorService.cfc | 77 ++++- .../services/Renderer.cfc | 2 +- .../services/RoutingService.cfc | 26 +- system/config/Config.cfc | 2 +- system/config/Router.cfc | 3 +- system/config/WireBox.cfc | 37 ++- system/handlers/admin/SystemInformation.cfc | 1 + system/helpers/presideProxies.cfm | 8 + system/i18n/cms.properties | 1 + system/i18n/cms_de.properties | 1 + .../admin/systemInformation/_generalTab.cfm | 3 + 25 files changed, 333 insertions(+), 292 deletions(-) create mode 100644 system/coldboxModifications/EventHandler.cfc create mode 100644 system/coldboxModifications/Interceptor.cfc create mode 100644 system/coldboxModifications/ioc/Provider.cfc diff --git a/box.json b/box.json index 093e63db87..ec47fc36ce 100644 --- a/box.json +++ b/box.json @@ -37,7 +37,7 @@ "cbmessagebox":"2.2.0+10", "cbstorages":"1.3.0+14", "cbjavaloader":"1.5.0+35", - "coldbox":"5.4.0", + "coldbox":"6.9.0", "cfconcurrent":"3.0.0", "JSONPrettyPrint":"1.4.1", "cfflow":"0.8.0" diff --git a/system/coldboxModifications/Controller.cfc b/system/coldboxModifications/Controller.cfc index faadbdcfd7..f1c06e1d45 100644 --- a/system/coldboxModifications/Controller.cfc +++ b/system/coldboxModifications/Controller.cfc @@ -10,6 +10,7 @@ component extends="coldbox.system.web.Controller" { services.routingService = new preside.system.coldboxModifications.services.RoutingService( this ); variables.wireBox = CreateObject( "preside.system.coldboxModifications.ioc.Injector" ); variables.cacheBox = CreateObject( "preside.system.coldboxModifications.cachebox.CacheFactory" ); + } function getRenderer(){ @@ -258,8 +259,29 @@ component extends="coldbox.system.web.Controller" { return getRequestService().getContext(); } - public any function getSetting( required string name, boolean fwSetting=false, any defaultValue ) { + /** + * Compatibility shim: getSettingStructure() was removed in ColdBox 6.0 + * Delegates to the configSettings/coldboxSettings structs directly. + */ + public struct function getSettingStructure( boolean fwSetting=false, boolean deepCopyFlag=false ) { var target = arguments.fwSetting ? variables.coldboxSettings : variables.configSettings; + return arguments.deepCopyFlag ? duplicate( target ) : target; + } + + public any function getSetting( required string name, any fwSetting=false, any defaultValue ) { + // CB 6.0+ signature: getSetting( name, defaultValue ). If fwSetting + // is not a boolean, treat it as defaultValue for compatibility. + if ( !IsBoolean( arguments.fwSetting ) ) { + arguments.defaultValue = arguments.fwSetting; + arguments.fwSetting = false; + } + var target = arguments.fwSetting ? variables.coldboxSettings : variables.configSettings; + + // CB 6.0 removed viewsRefMap and layoutsRefMap from config settings. + // Preside's custom Renderer still uses them. Lazy-init on first access. + if ( !arguments.fwSetting && ListFindNoCase( "viewsRefMap,layoutsRefMap", arguments.name ) && !StructKeyExists( target, arguments.name ) ) { + target[ arguments.name ] = {}; + } if ( StructKeyExists( target, arguments.name ) ) { return target[ arguments.name ]; diff --git a/system/coldboxModifications/DelayedInjectorDsl.cfc b/system/coldboxModifications/DelayedInjectorDsl.cfc index bbaabbdac9..d604833060 100644 --- a/system/coldboxModifications/DelayedInjectorDsl.cfc +++ b/system/coldboxModifications/DelayedInjectorDsl.cfc @@ -6,7 +6,7 @@ component implements="coldbox.system.ioc.dsl.IDSLBuilder" { return this; } - public any function process( required any definition, any targetObject ) { + public any function process( required any definition, any targetObject, any targetID ) { var thisType = arguments.definition.dsl; var thisTypeLen = ListLen( thisType, ":" ); var injectorDsl = ""; diff --git a/system/coldboxModifications/EventHandler.cfc b/system/coldboxModifications/EventHandler.cfc new file mode 100644 index 0000000000..a47071f716 --- /dev/null +++ b/system/coldboxModifications/EventHandler.cfc @@ -0,0 +1,38 @@ +/** + * Preside compatibility shim for ColdBox 6.0+ + * + * ColdBox 6.0 removed setNextEvent() and getModel() from FrameworkSupertype. + * This shim adds them back so that all Preside handlers continue to work + * without needing to update 400+ call sites. + */ +component extends="coldbox.system.EventHandler" { + + /** + * Compatibility: setNextEvent() was removed in ColdBox 6.0. + * Delegates to relocate() which is the replacement. + */ + void function setNextEvent( + event + , URL + , URI + , queryString + , persist + , struct persistStruct + , boolean addToken + , boolean ssl + , baseURL + , boolean postProcessExempt + , numeric statusCode + ){ + controller.relocate( argumentCollection=arguments ); + } + + /** + * Compatibility: getModel() was removed in ColdBox 6.0. + * Delegates to getInstance() which is the replacement. + */ + function getModel( name, dsl, initArguments={} ){ + return getInstance( argumentCollection=arguments ); + } + +} diff --git a/system/coldboxModifications/FeatureDependentDsl.cfc b/system/coldboxModifications/FeatureDependentDsl.cfc index 6b73cd9f36..d6ce4fd918 100644 --- a/system/coldboxModifications/FeatureDependentDsl.cfc +++ b/system/coldboxModifications/FeatureDependentDsl.cfc @@ -6,7 +6,7 @@ component implements="coldbox.system.ioc.dsl.IDSLBuilder" { return this; } - public any function process( required any definition, any targetObject ) { + public any function process( required any definition, any targetObject, any targetID ) { var dsl = ListRest( arguments.definition.dsl ?: "", ":" ); if ( ListLen( dsl, ":" ) < 2 ) { diff --git a/system/coldboxModifications/Interceptor.cfc b/system/coldboxModifications/Interceptor.cfc new file mode 100644 index 0000000000..fdc435cb4e --- /dev/null +++ b/system/coldboxModifications/Interceptor.cfc @@ -0,0 +1,31 @@ +/** + * Preside Interceptor shim for ColdBox 6.0+ + * + * 1. ColdBox 6.0 moved loadApplicationHelpers() from the constructor to a + * lazy cbLoadInterceptorHelpers event. This means interceptors that fire + * during startup (e.g. afterConfigurationLoad) don't have helpers like + * isFeatureEnabled() available yet. This shim restores eager loading. + * + * 2. ColdBox 6.0 removed getModel() from FrameworkSupertype. This shim + * restores it as a passthrough to getInstance(). + */ +component extends="coldbox.system.Interceptor" { + + function init( required controller, struct properties = {} ){ + super.init( argumentCollection = arguments ); + + // CB 5.4 loaded helpers in init(); CB 6.0+ defers to cbLoadInterceptorHelpers. + // Restore eager loading so helpers are available during startup interceptions. + loadApplicationHelpers( force: true ); + + return this; + } + + /** + * Compatibility shim: getModel() was removed in ColdBox 6.0 + */ + function getModel( name, dsl, initArguments={} ){ + return getInstance( argumentCollection=arguments ); + } + +} diff --git a/system/coldboxModifications/InterceptorState.cfc b/system/coldboxModifications/InterceptorState.cfc index d659449d3e..b5c3928670 100644 --- a/system/coldboxModifications/InterceptorState.cfc +++ b/system/coldboxModifications/InterceptorState.cfc @@ -45,7 +45,8 @@ component { public any function process( required any event - , required any interceptData + , any data = {} + , any interceptData , required any buffer , boolean async = false , boolean asyncAll = false @@ -53,17 +54,23 @@ component { , string asyncPriority = "NORMAL" , numeric asyncJoinTimeout = 0 ) { + // ColdBox 6.0+ uses 'data', Preside uses 'interceptData' — normalise + if ( !isNull( arguments.interceptData ) ) { + arguments.data = arguments.interceptData; + } + if ( arguments.async && !instance.utility.inThread() ) { return processAsync( event = arguments.event - , interceptData = arguments.interceptData + , interceptData = arguments.data , asyncPriority = arguments.asyncPriority , buffer = arguments.buffer ); } else if ( arguments.asyncAll AND NOT instance.utility.inThread() ) { + arguments.interceptData = arguments.data; return processAsyncAll( argumentCollection=arguments ); } else { - processSync( event=arguments.event, interceptData=arguments.interceptData, buffer=arguments.buffer ); + processSync( event=arguments.event, interceptData=arguments.data, buffer=arguments.buffer ); } } diff --git a/system/coldboxModifications/LegacyDslBuilder.cfc b/system/coldboxModifications/LegacyDslBuilder.cfc index ffdda1cee5..00603ba87c 100644 --- a/system/coldboxModifications/LegacyDslBuilder.cfc +++ b/system/coldboxModifications/LegacyDslBuilder.cfc @@ -8,7 +8,7 @@ component { return this; } - function process( required any definition, targetObject ) { + function process( required any definition, targetObject, targetID ) { var dsl = arguments.definition.dsl; if( reFindNoCase( '^coldbox:myplugin:.*', dsl ) ) { diff --git a/system/coldboxModifications/PresideWireboxDsl.cfc b/system/coldboxModifications/PresideWireboxDsl.cfc index 06920ea361..756c729048 100644 --- a/system/coldboxModifications/PresideWireboxDsl.cfc +++ b/system/coldboxModifications/PresideWireboxDsl.cfc @@ -6,7 +6,7 @@ component implements="coldbox.system.ioc.dsl.IDSLBuilder" { return this; } - public any function process( required any definition, any targetObject ) { + public any function process( required any definition, any targetObject, any targetID ) { var dsl = ListRest( definition.dsl, ":" ); var namespace = ListFirst( dsl, ":" ); diff --git a/system/coldboxModifications/includes/errorReport.cfm b/system/coldboxModifications/includes/errorReport.cfm index 4762a714ce..4a589adb62 100644 --- a/system/coldboxModifications/includes/errorReport.cfm +++ b/system/coldboxModifications/includes/errorReport.cfm @@ -1,264 +1,4 @@ - - - // Detect Session Scope - local.sessionScopeExists = true; - try { structKeyExists( session ,'x' ); } - catch ( any e ) { - local.sessionScopeExists = false; - } - try{ - local.thisInetHost = createObject( "java", "java.net.InetAddress" ).getLocalHost().getHostName(); - } - catch( any e ){ - local.thisInetHost = "localhost"; - } - - - - - - -
-

- - #oException.getErrorCode()# : - - 500 : - - An error occurred

- -
- - -

#oException.getExtramessage()#

-
- - - Event: #event.getCurrentEvent()#N/A -
- Routed URL: #event.getCurrentRoutedURL()#N/A -
- Layout: #Event.getCurrentLayout()#N/A (Module: #event.getCurrentLayoutModule()#) -
- View: #Event.getCurrentView()#N/A -
- Timestamp: #dateformat(now(), "MM/DD/YYYY")# #timeformat(now(),"hh:MM:SS TT")# - -
- - - - Type: #oException.gettype()#
-
- - - - Messages: - #oException.getmessage()# - - #oException.getExtendedInfo()#
-
- - - #oException.getDetail()# - - -
- -
- -

Tag Context:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Tag:#local.arrayTagContext[ local.i ].ID#
Template:#local.arrayTagContext[ local.i ].Template#
LINE:#local.arrayTagContext[ local.i ].codePrintHTML#
Line:#local.arrayTagContext[ local.i ].LINE#
- -

Stack Trace:

-
#processStackTrace( oException.getstackTrace() )#
- - -

FRAMEWORK SNAPSHOT:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Bug Date:#dateformat(now(), "MM/DD/YYYY")# #timeformat(now(),"hh:MM:SS TT")#
Coldfusion ID: - - - CFID=#session.CFID# ; - - CFID=#client.CFID# ; - - - CFToken=#session.CFToken# ; - - CFToken=#client.CFToken# ; - - - JSessionID=#session.sessionID# - - - Session Scope Not Enabled - -
Template Path : #htmlEditFormat(CGI.CF_TEMPLATE_PATH)#
Path Info : #htmlEditFormat(CGI.PATH_INFO)#
Host & Server: #htmlEditFormat(cgi.http_host)# #local.thisInetHost#
Query String: #htmlEditFormat(cgi.QUERY_STRING)#
Referrer:#htmlEditFormat(cgi.HTTP_REFERER)#
Browser:#htmlEditFormat(cgi.HTTP_USER_AGENT)#
Remote Address: #htmlEditFormat(cgi.remote_addr)#
Database oException Information:
NativeErrorCode & SQL State:
#oException.getNativeErrorCode()# : #oException.getSQLState()#
SQL Sent:
#oException.getSQL()#
Database Driver Error Message:
#oException.getqueryError()#
Name-Value Pairs:
#oException.getWhere()#
Form variables:
#htmlEditFormat( key )#:#htmlEditFormat( form[ key ] )#
Session Storage:
#key#: #htmlEditFormat( session[ key ] )##key#
N/A Session Scope Not Enabled
Cookies:
#key#: #htmlEditFormat( cookie[ key ] )#
Extra Information Dump
- - [N/A]#oException.getExtraInfo()# - - - -
-
- -
-
\ No newline at end of file + + + + diff --git a/system/coldboxModifications/ioc/Builder.cfc b/system/coldboxModifications/ioc/Builder.cfc index e2dfd88b7f..5473443a38 100644 --- a/system/coldboxModifications/ioc/Builder.cfc +++ b/system/coldboxModifications/ioc/Builder.cfc @@ -5,6 +5,36 @@ */ component extends="coldbox.system.ioc.Builder" { + /** + * ColdBox 6.0 renamed Provider.get() to Provider.$get(). + * Override to use Preside's Provider shim that restores get(). + */ + private any function getProviderDSL( required definition, targetObject="", targetID ) { + var thisType = arguments.definition.dsl; + var thisTypeLen = listLen( thisType, ":" ); + var providerName = ""; + + switch ( thisTypeLen ) { + case 1: { providerName = arguments.definition.name; break; } + case 2: { providerName = getToken( thisType, 2, ":" ); break; } + default: { providerName = replaceNoCase( thisType, "provider:", "" ); } + } + + var args = { + scopeRegistration : variables.injector.getScopeRegistration() + , scopeStorage : variables.injector.getScopeStorage() + , targetObject : arguments.targetObject + }; + + if ( variables.injector.containsInstance( providerName ) ) { + args.name = providerName; + } else { + args.dsl = providerName; + } + + return new preside.system.coldboxModifications.ioc.Provider( argumentCollection=args ); + } + public any function buildCfc( required any mapping, struct initArguments={} ) { var thisMap = arguments.mapping; var oModel = createObject( "component", thisMap.getPath() ); diff --git a/system/coldboxModifications/ioc/Injector.cfc b/system/coldboxModifications/ioc/Injector.cfc index b3b398f7ac..ff62e47e22 100644 --- a/system/coldboxModifications/ioc/Injector.cfc +++ b/system/coldboxModifications/ioc/Injector.cfc @@ -49,7 +49,8 @@ component extends="coldbox.system.ioc.Injector" { // Register All Custom Listeners registerListeners(); // Create our object builder - variables.builder = new preside.system.coldboxModifications.ioc.Builder( this ); + variables.builder = new preside.system.coldboxModifications.ioc.Builder( this ); + variables.objectBuilder = variables.builder; // Register Custom DSL Builders variables.builder.registerCustomBuilders(); // Register Life Cycle Scopes @@ -78,6 +79,8 @@ component extends="coldbox.system.ioc.Injector" { // process mappings for metadata and initialization. variables.binder.processMappings(); + // ColdBox 6.0+ split eager init processing out of processMappings() + variables.binder.processEagerInits(); // Announce To Listeners we are online iData.injector = this; diff --git a/system/coldboxModifications/ioc/Provider.cfc b/system/coldboxModifications/ioc/Provider.cfc new file mode 100644 index 0000000000..b545d08089 --- /dev/null +++ b/system/coldboxModifications/ioc/Provider.cfc @@ -0,0 +1,13 @@ +/** + * Preside Provider shim for ColdBox 6.0+ + * + * ColdBox 6.0 renamed get() to $get() on Providers. + * This shim restores get() for backwards compatibility. + */ +component extends="coldbox.system.ioc.Provider" { + + any function get(){ + return $get(); + } + +} diff --git a/system/coldboxModifications/services/HandlerService.cfc b/system/coldboxModifications/services/HandlerService.cfc index 8438cf25ab..b909235e95 100644 --- a/system/coldboxModifications/services/HandlerService.cfc +++ b/system/coldboxModifications/services/HandlerService.cfc @@ -2,6 +2,38 @@ component extends="coldbox.system.web.services.HandlerService" { variables.handlerBeans = {}; + /** + * Override newHandler to use Preside's EventHandler shim + * which adds back setNextEvent() and getModel() compatibility + */ + function newHandler( required invocationPath ){ + if ( NOT variables.wirebox.getBinder().mappingExists( arguments.invocationPath ) ) { + wireboxSetup(); + variables.wirebox + .registerNewInstance( name=arguments.invocationPath, instancePath=arguments.invocationPath ) + .setVirtualInheritance( "preside.system.coldboxModifications.EventHandler" ) + .addDIConstructorArgument( name="controller", value=controller ) + .setThreadSafe( true ) + .setScope( + variables.handlerCaching ? variables.wirebox.getBinder().SCOPES.SINGLETON : variables.wirebox.getBinder().SCOPES.NOSCOPE + ) + .setCacheProperties( key="handlers-#arguments.invocationPath#" ); + } + return variables.wirebox.getInstance( arguments.invocationPath ); + } + + private function wireboxSetup(){ + super.wireboxSetup(); + if ( NOT variables.wirebox.getBinder().mappingExists( "preside.system.coldboxModifications.EventHandler" ) ) { + variables.wirebox + .registerNewInstance( + name = "preside.system.coldboxModifications.EventHandler" + , instancePath = "preside.system.coldboxModifications.EventHandler" + ) + .addDIConstructorArgument( name="controller", value=controller ); + } + } + public void function registerHandlers() { var appMapping = "/" & controller.getSetting( "appMapping" ).reReplace( "^/", "" ); var appMappingPath = controller.getSetting( "appMappingPath" ); diff --git a/system/coldboxModifications/services/InterceptorService.cfc b/system/coldboxModifications/services/InterceptorService.cfc index de60161b6c..3b0bca8ad1 100644 --- a/system/coldboxModifications/services/InterceptorService.cfc +++ b/system/coldboxModifications/services/InterceptorService.cfc @@ -28,6 +28,36 @@ component extends="coldbox.system.web.services.InterceptorService" { return super.registerInterceptor( argumentCollection=arguments ); } + /** + * ColdBox 6.0+ calls announce() directly from WireBox/CacheBox, + * bypassing processState(). Override to suppress events during + * interceptor registration — matching CB 5.4 behaviour where + * WireBox called processState() which had the safety check. + */ + public any function announce( + required any state + , any data = structNew() + , boolean async = false + , boolean asyncAll = false + , boolean asyncAllJoin = true + , string asyncPriority = "NORMAL" + , numeric asyncJoinTimeout = 0 + ) { + // During interceptor registration, only allow the WireBox lifecycle + // events that are unavoidably announced during instantiation. + // All other events (including afterInstanceAutowire) are suppressed + // to match CB 5.4 behaviour where they were not yet registered as states. + if ( _registeringInterceptors && !_ignoreStatesDuringLoadCheck.findNoCase( arguments.state ) ) { + return; + } + + if( !StructKeyExists( variables.interceptionStates, arguments.state ) ){ + return; + } + + return super.announce( argumentCollection=arguments ); + } + public any function processState( required any state , any interceptData = structNew() @@ -50,10 +80,55 @@ component extends="coldbox.system.web.services.InterceptorService" { return; } - return super.processState( argumentCollection=arguments ); + return super.announce( + state = arguments.state + , data = arguments.interceptData + , async = arguments.async + , asyncAll = arguments.asyncAll + , asyncAllJoin = arguments.asyncAllJoin + , asyncPriority = arguments.asyncPriority + , asyncJoinTimeout = arguments.asyncJoinTimeout + ); } + /** + * Override createInterceptor to use Preside's Interceptor shim + * which eagerly loads application helpers in the constructor (CB 5.4 behaviour). + */ + function createInterceptor( + required interceptorClass, + required interceptorName, + struct interceptorProperties = {} + ){ + if ( NOT variables.wirebox.getBinder().mappingExists( "interceptor-" & arguments.interceptorName ) ) { + wireboxSetup(); + variables.wirebox + .registerNewInstance( + name = "interceptor-" & arguments.interceptorName + , instancePath = arguments.interceptorClass + ) + .setScope( variables.wirebox.getBinder().SCOPES.SINGLETON ) + .setThreadSafe( true ) + .setVirtualInheritance( "preside.system.coldboxModifications.Interceptor" ) + .addDIConstructorArgument( name="controller", value=controller ) + .addDIConstructorArgument( name="properties", value=arguments.interceptorProperties ); + } + return getInterceptor( arguments.interceptorName ); + } + + private function wireboxSetup(){ + if ( NOT variables.wirebox.getBinder().mappingExists( "preside.system.coldboxModifications.Interceptor" ) ) { + variables.wirebox + .registerNewInstance( + name = "preside.system.coldboxModifications.Interceptor" + , instancePath = "preside.system.coldboxModifications.Interceptor" + ) + .addDIConstructorArgument( name="controller", value=controller ) + .addDIConstructorArgument( name="properties", value={} ); + } + } + public any function registerInterceptionPoint( required any interceptorKey , required any state diff --git a/system/coldboxModifications/services/Renderer.cfc b/system/coldboxModifications/services/Renderer.cfc index 104191e8eb..fa6ca09a48 100644 --- a/system/coldboxModifications/services/Renderer.cfc +++ b/system/coldboxModifications/services/Renderer.cfc @@ -913,7 +913,7 @@ component accessors="true" serializable="false" singleton="true" extends="coldbo private struct function _getViewMappings() { var site = getRequestContext().getSite(); var cacheKey = "viewsFullMappings" & ( site.template ?: "" ); - var ignoreFileSvc = getModel( "ignoreFileService" ); + var ignoreFileSvc = getInstance( "ignoreFileService" ); lock name="#lockName#" type="readonly" timeout="15" throwontimeout="true" { if ( controller.settingExists( cacheKey ) ) { diff --git a/system/coldboxModifications/services/RoutingService.cfc b/system/coldboxModifications/services/RoutingService.cfc index c8e5593ac8..caf00706d0 100644 --- a/system/coldboxModifications/services/RoutingService.cfc +++ b/system/coldboxModifications/services/RoutingService.cfc @@ -19,24 +19,32 @@ component extends="coldbox.system.web.services.RoutingService" accessors=true { variables.controller.getInterceptorService().registerInterceptor( interceptorClass="preside.system.interceptors.PageCachingInterceptor" ); } - public void function onRequestCapture( event, interceptData ) { + public void function requestCapture( required event ) { + var interceptData = {}; + var presideArgs = { event=arguments.event, interceptData=interceptData }; + _announceInterception( "prePresideRequestCapture", interceptData ); - _checkRedirectDomains( argumentCollection=arguments ); + _checkRedirectDomains( argumentCollection=presideArgs ); if ( featureService.isFeatureEnabled( "sites" ) ) { - _detectIncomingSite( argumentCollection=arguments ); + _detectIncomingSite( argumentCollection=presideArgs ); } - _setCustomTenants ( argumentCollection=arguments ); - _checkUrlRedirects ( argumentCollection=arguments ); - _detectLanguage ( argumentCollection=arguments ); - _setPresideUrlPath ( argumentCollection=arguments ); + _setCustomTenants ( argumentCollection=presideArgs ); + _checkUrlRedirects ( argumentCollection=presideArgs ); + _detectLanguage ( argumentCollection=presideArgs ); + _setPresideUrlPath ( argumentCollection=presideArgs ); - if ( !_routePresideSESRequest( argumentCollection=arguments ) ) { - super.onRequestCapture( argumentCollection=arguments ); + if ( !_routePresideSESRequest( argumentCollection=presideArgs ) ) { + super.requestCapture( argumentCollection=arguments ); } _announceInterception( "postPresideRequestCapture", interceptData ); } + public void function onRequestCapture( event, interceptData ) { + // No-op: In ColdBox 6.0+, routing is handled via requestCapture() above. + // This method is kept for backwards compatibility with any interceptor listeners. + } + public void function onBuildLink( event, interceptData ) { for( var route in _getPresideRoutes() ){ if ( route.get().reverseMatch( buildArgs=interceptData, event=event ) ) { diff --git a/system/config/Config.cfc b/system/config/Config.cfc index 9fb466c1d8..a96c69b4da 100644 --- a/system/config/Config.cfc +++ b/system/config/Config.cfc @@ -130,7 +130,7 @@ component { , requestStartHandler = "General.requestStart" , requestEndHandler = "General.requestEnd" , missingTemplateHandler = "General.notFound" - , onInvalidEvent = "General.notFound" + , invalidEventHandler = "General.notFound" , coldboxExtensionsLocation = "preside.system.coldboxModifications" , customErrorTemplate = "/preside/system/coldboxModifications/includes/errorReport.cfm" }; diff --git a/system/config/Router.cfc b/system/config/Router.cfc index 217afcc215..86c0d64daf 100644 --- a/system/config/Router.cfc +++ b/system/config/Router.cfc @@ -1,7 +1,6 @@ component extends="coldbox.system.web.routing.Router" { public void function configure() { - setUniqueUrls( false ); setExtensionDetection( false ); setBaseUrl( "/" ); @@ -101,7 +100,7 @@ component extends="coldbox.system.web.routing.Router" { arguments.dsl = "delayedInjector:" & arguments.dsl; } - return super.getModel( + return super.getInstance( dsl = arguments.dsl ?: NullValue() , initArguments = arguments.initArguments ); diff --git a/system/config/WireBox.cfc b/system/config/WireBox.cfc index f148d524c9..9efb3bf080 100644 --- a/system/config/WireBox.cfc +++ b/system/config/WireBox.cfc @@ -29,7 +29,11 @@ } private void function _mapCommonSystemServices() { - mapDirectory( packagePath="preside.system.services", filter=this._filterServices, influence=function( mapping, objectPath ) { + var pkg = "preside.system.services"; + var dir = ExpandPath( "/#Replace( pkg, '.', '/', 'all' )#" ); + mapDirectory( packagePath=pkg, filter=function( thisPath ) { + return _filterServices( _toComponentPath( thisPath, dir, pkg ) ); + }, influence=function( mapping, objectPath ) { _injectPresideSuperClass( argumentCollection=arguments ); } ); } @@ -39,7 +43,11 @@ var appMappingPath = getColdbox().getSetting( name="appMappingPath", defaultValue="app" ); if ( DirectoryExists( "/#appMapping#/services" ) ) { - mapDirectory( packagePath="#appMappingPath#.services", filter=this._filterServices, influence=function( mapping, objectPath ) { + var pkg = "#appMappingPath#.services"; + var dir = ExpandPath( "/#Replace( pkg, '.', '/', 'all' )#" ); + mapDirectory( packagePath=pkg, filter=function( thisPath ) { + return _filterServices( _toComponentPath( thisPath, dir, pkg ) ); + }, influence=function( mapping, objectPath ) { _injectPresideSuperClass( argumentCollection=arguments ); } ); } @@ -50,7 +58,11 @@ for( var i=1; i<=extensions.len(); i++ ){ var servicesDir = ListAppend( extensions[i].directory, "services", "/" ) if ( DirectoryExists( servicesDir ) ) { - mapDirectory( packagePath=servicesDir, filter=this._filterServices, influence=function( mapping, objectPath ) { + var pkg = servicesDir; + var dir = ExpandPath( servicesDir ); + mapDirectory( packagePath=pkg, filter=function( thisPath ) { + return _filterServices( _toComponentPath( thisPath, dir, pkg ) ); + }, influence=function( mapping, objectPath ) { _injectPresideSuperClass( argumentCollection=arguments ); } ); } @@ -170,7 +182,7 @@ return false; } - private boolean function _filterServices( objectPath ) { + private boolean function _filterServices( required string objectPath ) { if ( ignoreFileService.isIgnored( "service", arguments.objectPath ) ) { return false; } @@ -184,6 +196,23 @@ return true; } + private string function _toComponentPath( required string filePath, required string targetDir, required string packagePath ) { + // If already a dot-path (CB 5.4 behaviour), return as-is + if ( !FindNoCase( ".cfc", arguments.filePath ) ) { + return arguments.filePath; + } + + // Convert absolute file path to component dot-path + // Strip target directory prefix, remove .cfc, convert slashes to dots + var relativePath = ReplaceNoCase( arguments.filePath, arguments.targetDir, "" ); + relativePath = ReplaceNoCase( relativePath, ".cfc", "" ); + relativePath = ReReplace( relativePath, "(\\|/)", ".", "all" ); + + // Prepend package path (strip leading dots) + var result = ReReplace( arguments.packagePath, "^/", "" ) & relativePath; + return ReReplace( result, "^\.", "" ); + } + private boolean function _featureDisabled( required struct meta ) { if ( StructKeyExists( arguments.meta, "feature" ) ) { return Len( arguments.meta.feature ) && !featureService.isFeatureEnabled( arguments.meta.feature ); diff --git a/system/handlers/admin/SystemInformation.cfc b/system/handlers/admin/SystemInformation.cfc index f266ffda41..177d8fe87e 100644 --- a/system/handlers/admin/SystemInformation.cfc +++ b/system/handlers/admin/SystemInformation.cfc @@ -54,6 +54,7 @@ component extends="preside.system.base.AdminHandler" { args.presideCmsVersion = updateManagerService.getCurrentVersion(); + args.coldboxVersion = getSetting( name="version", fwSetting=true, defaultValue="Unknown" ); args.applicationServer = productName & ' (' & productVersion & ')'; args.java = javaVersion; args.os = osName & ' (' & osVersion & ')'; diff --git a/system/helpers/presideProxies.cfm b/system/helpers/presideProxies.cfm index 2554470d3e..93120dbb6e 100644 --- a/system/helpers/presideProxies.cfm +++ b/system/helpers/presideProxies.cfm @@ -269,6 +269,14 @@ + + + + + + + + diff --git a/system/i18n/cms.properties b/system/i18n/cms.properties index 2de38855ab..e15425f874 100644 --- a/system/i18n/cms.properties +++ b/system/i18n/cms.properties @@ -1072,6 +1072,7 @@ sites.clonesite.confirmation=Site was cloned successfully systemInformation.menu.title=System Information systemInformation.cms.th=Preside +systemInformation.coldbox.th=ColdBox Framework systemInformation.applicationServer.th=Application Server systemInformation.dataBase.th=Database Server systemInformation.java.th=Java diff --git a/system/i18n/cms_de.properties b/system/i18n/cms_de.properties index 0fdf7e5aa9..2d6af270ed 100644 --- a/system/i18n/cms_de.properties +++ b/system/i18n/cms_de.properties @@ -901,6 +901,7 @@ sites.clonesite.btn=Seite klonen sites.clonesite.confirmation=Die Seite wurde erfolgreich geklont systemInformation.menu.title=Systeminformationen systemInformation.cms.th=Preside +systemInformation.coldbox.th=ColdBox Framework systemInformation.applicationServer.th=Application Server systemInformation.dataBase.th=Datenbank Server systemInformation.java.th=Java diff --git a/system/views/admin/systemInformation/_generalTab.cfm b/system/views/admin/systemInformation/_generalTab.cfm index 185ae8384b..3fc15883b6 100644 --- a/system/views/admin/systemInformation/_generalTab.cfm +++ b/system/views/admin/systemInformation/_generalTab.cfm @@ -2,6 +2,7 @@ pageTitle = args.pageTitle ?: ""; presideCmsVersion = args.presideCmsVersion ?: ""; + coldboxVersion = args.coldboxVersion ?: ""; applicationServer = args.applicationServer ?: ""; java = args.java ?: ""; os = args.os ?: ""; @@ -13,6 +14,7 @@ #translateResource( uri="cms:systemInformation.cms.th" )# + #translateResource( uri="cms:systemInformation.coldbox.th" )# #translateResource( uri="cms:systemInformation.applicationServer.th" )# #translateResource( uri="cms:systemInformation.dataBase.th" )# #translateResource( uri="cms:systemInformation.java.th" )# @@ -22,6 +24,7 @@ #presideCmsVersion# + #coldboxVersion# #applicationServer# #dataBase# #java# From 2d0526a45077808f48b4786c8df048e0cae15a45 Mon Sep 17 00:00:00 2001 From: Test Date: Fri, 27 Mar 2026 17:36:46 +0000 Subject: [PATCH 02/15] ColdBox 7.5.2 upgrade: additional shims for CB 7 breaking changes - MetadataIndexer: removed extends (class deleted in CB7), made standalone - DiskStore: added getSortedKeys() and getCachedObjectMetadata() for IObjectStore interface, pointed indexer at Preside's MetadataIndexer - Interceptor shim: removed init() override (CB7 changed constructor signature), relies on cbLoadInterceptorHelpers event instead - HandlerService: updated newHandler() for CB7 signature (ehBean instead of invocationPath), handles both string and object args for Preside compat. Replaced wireboxSetup() with injectorSeedBaseClasses() (renamed in CB7) - Builder: inject cbInjectedHelpers into variables scope for components extending FrameworkSupertype that skip super.init() (CB7 requirement) - Provider shim: added injectorName parameter (required in CB7) - Renderer: added startup() method (called by CB7 LoaderService), moved init logic to startup() with deferred execution support - Router: changed super.getInstance() to controller.getWirebox().getInstance() (CB7 changed method visibility) - EventHandler: removed unnecessary _privateInvoker override - errorReport: simplified to rethrow for debugging Known issues under investigation: - variable [listing] doesn't exist in DataManager._listing handler - Frontend content rendering blank page Co-Authored-By: Claude Opus 4.6 (1M context) --- box.json | 2 +- system/coldboxModifications/Interceptor.cfc | 21 ++--- .../cachebox/store/DiskStore.cfc | 19 +++- .../store/indexers/MetadataIndexer.cfc | 14 ++- system/coldboxModifications/ioc/Builder.cfc | 24 ++--- .../services/HandlerService.cfc | 43 +++++---- .../services/Renderer.cfc | 87 ++++++++++--------- system/config/Router.cfc | 2 +- 8 files changed, 126 insertions(+), 86 deletions(-) diff --git a/box.json b/box.json index ec47fc36ce..23d2d2d295 100644 --- a/box.json +++ b/box.json @@ -37,7 +37,7 @@ "cbmessagebox":"2.2.0+10", "cbstorages":"1.3.0+14", "cbjavaloader":"1.5.0+35", - "coldbox":"6.9.0", + "coldbox":"7.5.2", "cfconcurrent":"3.0.0", "JSONPrettyPrint":"1.4.1", "cfflow":"0.8.0" diff --git a/system/coldboxModifications/Interceptor.cfc b/system/coldboxModifications/Interceptor.cfc index fdc435cb4e..13d27f02fd 100644 --- a/system/coldboxModifications/Interceptor.cfc +++ b/system/coldboxModifications/Interceptor.cfc @@ -1,24 +1,21 @@ /** - * Preside Interceptor shim for ColdBox 6.0+ + * Preside Interceptor shim for ColdBox 6.0+/7.0+ * - * 1. ColdBox 6.0 moved loadApplicationHelpers() from the constructor to a - * lazy cbLoadInterceptorHelpers event. This means interceptors that fire - * during startup (e.g. afterConfigurationLoad) don't have helpers like - * isFeatureEnabled() available yet. This shim restores eager loading. + * 1. ColdBox 6.0+ moved loadApplicationHelpers() from the constructor to a + * lazy cbLoadInterceptorHelpers event. This shim eagerly loads helpers + * via cbLoadInterceptorHelpers so they're available for startup interceptions. * * 2. ColdBox 6.0 removed getModel() from FrameworkSupertype. This shim * restores it as a passthrough to getInstance(). */ component extends="coldbox.system.Interceptor" { - function init( required controller, struct properties = {} ){ - super.init( argumentCollection = arguments ); - - // CB 5.4 loaded helpers in init(); CB 6.0+ defers to cbLoadInterceptorHelpers. - // Restore eager loading so helpers are available during startup interceptions. + /** + * Override cbLoadInterceptorHelpers to ensure helpers are loaded + * immediately when called, restoring CB 5.4 eager-loading behaviour. + */ + function cbLoadInterceptorHelpers( event, interceptData ){ loadApplicationHelpers( force: true ); - - return this; } /** diff --git a/system/coldboxModifications/cachebox/store/DiskStore.cfc b/system/coldboxModifications/cachebox/store/DiskStore.cfc index 65d7aab376..c5f04e2dd3 100644 --- a/system/coldboxModifications/cachebox/store/DiskStore.cfc +++ b/system/coldboxModifications/cachebox/store/DiskStore.cfc @@ -47,7 +47,7 @@ component implements="coldbox.system.cache.store.IObjectStore" accessors="true"{ // Prepare instance variables.cacheProvider = arguments.cacheProvider; variables.storeID = createObject( 'java', 'java.lang.System' ).identityHashCode( this ); - variables.indexer = new coldbox.system.cache.store.indexers.MetadataIndexer( fields ); + variables.indexer = new preside.system.coldboxModifications.cachebox.store.indexers.MetadataIndexer( fields ); variables.converter = new coldbox.system.core.conversion.ObjectMarshaller(); variables.directoryPath = ""; @@ -306,6 +306,23 @@ component implements="coldbox.system.cache.store.IObjectStore" accessors="true"{ return variables.indexer.getSize(); } + /** + * CB 7.0: IObjectStore now requires getSortedKeys() + */ + array function getSortedKeys( required property, sortType="text", sortOrder="asc" ) { + return getKeys(); + } + + /** + * CB 7.0: IObjectStore now requires getCachedObjectMetadata() + */ + struct function getCachedObjectMetadata( required objectKey ){ + if ( variables.indexer.objectExists( arguments.objectKey ) ) { + return variables.indexer.getObjectMetadata( arguments.objectKey ); + } + return {}; + } + //********************************* PRIVATE ************************************// /** diff --git a/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc b/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc index 4fac4c6e10..d20956651a 100644 --- a/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc +++ b/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc @@ -1,4 +1,8 @@ -component extends="coldbox.system.cache.store.indexers.MetadataIndexer" { +/** + * ColdBox 7.0 removed coldbox.system.cache.store.indexers.MetadataIndexer. + * This is a standalone replacement used by Preside's ConcurrentStore. + */ +component { public any function init( required any fields ) { variables.poolMetadata = CreateObject( "java", "java.util.concurrent.ConcurrentHashMap" ).init() @@ -47,4 +51,12 @@ component extends="coldbox.system.cache.store.indexers.MetadataIndexer" { public any function getSize() { return variables.poolMetadata.size(); } + + public void function setFields( required any fields ) { + variables.fields = arguments.fields; + } + + public any function getFields() { + return variables.fields; + } } diff --git a/system/coldboxModifications/ioc/Builder.cfc b/system/coldboxModifications/ioc/Builder.cfc index 5473443a38..54e5c1b541 100644 --- a/system/coldboxModifications/ioc/Builder.cfc +++ b/system/coldboxModifications/ioc/Builder.cfc @@ -20,25 +20,27 @@ component extends="coldbox.system.ioc.Builder" { default: { providerName = replaceNoCase( thisType, "provider:", "" ); } } - var args = { + return new preside.system.coldboxModifications.ioc.Provider( scopeRegistration : variables.injector.getScopeRegistration() - , scopeStorage : variables.injector.getScopeStorage() , targetObject : arguments.targetObject - }; - - if ( variables.injector.containsInstance( providerName ) ) { - args.name = providerName; - } else { - args.dsl = providerName; - } - - return new preside.system.coldboxModifications.ioc.Provider( argumentCollection=args ); + , name : providerName + , injectorName : variables.injector.getName() + ); } public any function buildCfc( required any mapping, struct initArguments={} ) { var thisMap = arguments.mapping; var oModel = createObject( "component", thisMap.getPath() ); + // CB 7.0: FrameworkSupertype.init() sets variables.cbInjectedHelpers but + // some Preside components extend FrameworkSupertype without calling super.init(). + // Use WireBox's utility to inject it into the target's variables scope. + if ( StructKeyExists( oModel, "loadApplicationHelpers" ) ) { + variables.utility.getMixerUtil().start( oModel ); + oModel.injectPropertyMixin( "cbInjectedHelpers", {} ); + variables.utility.getMixerUtil().stop( oModel ); + } + // Do we have virtual inheritance? if( arguments.mapping.isVirtualInheritance() ){ // retrieve the VI mapping. diff --git a/system/coldboxModifications/services/HandlerService.cfc b/system/coldboxModifications/services/HandlerService.cfc index b909235e95..85cffb8586 100644 --- a/system/coldboxModifications/services/HandlerService.cfc +++ b/system/coldboxModifications/services/HandlerService.cfc @@ -4,33 +4,42 @@ component extends="coldbox.system.web.services.HandlerService" { /** * Override newHandler to use Preside's EventHandler shim - * which adds back setNextEvent() and getModel() compatibility + * which adds back setNextEvent() and getModel() compatibility. + * CB 7 changed signature from newHandler(invocationPath) to newHandler(ehBean). */ - function newHandler( required invocationPath ){ - if ( NOT variables.wirebox.getBinder().mappingExists( arguments.invocationPath ) ) { - wireboxSetup(); - variables.wirebox - .registerNewInstance( name=arguments.invocationPath, instancePath=arguments.invocationPath ) + function newHandler( required ehBean ){ + // Preside calls newHandler with a string path; CB 7 calls with an ehBean object + if ( IsSimpleValue( arguments.ehBean ) ) { + var injector = variables.wirebox; + var handlerPath = arguments.ehBean; + } else { + var injector = arguments.ehBean.isModule() ? variables.modules[ arguments.ehBean.getModule() ].injector : variables.wirebox; + var handlerPath = arguments.ehBean.getRunnable(); + } + + if ( NOT injector.getBinder().mappingExists( handlerPath ) ) { + injectorSeedBaseClasses( injector ); + injector + .registerNewInstance( name=handlerPath, instancePath=handlerPath ) .setVirtualInheritance( "preside.system.coldboxModifications.EventHandler" ) - .addDIConstructorArgument( name="controller", value=controller ) .setThreadSafe( true ) - .setScope( - variables.handlerCaching ? variables.wirebox.getBinder().SCOPES.SINGLETON : variables.wirebox.getBinder().SCOPES.NOSCOPE - ) - .setCacheProperties( key="handlers-#arguments.invocationPath#" ); + .setScope( variables.handlerCaching ? "singleton" : "NoScope" ) + .setCacheProperties( key="handlers-#handlerPath#" ) + .setExtraAttributes( { handlerPath: handlerPath, isHandler: true } ); } - return variables.wirebox.getInstance( arguments.invocationPath ); + + return injector.getInstance( handlerPath ); } - private function wireboxSetup(){ - super.wireboxSetup(); - if ( NOT variables.wirebox.getBinder().mappingExists( "preside.system.coldboxModifications.EventHandler" ) ) { - variables.wirebox + private function injectorSeedBaseClasses( required injector ){ + super.injectorSeedBaseClasses( arguments.injector ); + if ( NOT arguments.injector.getBinder().mappingExists( "preside.system.coldboxModifications.EventHandler" ) ) { + arguments.injector .registerNewInstance( name = "preside.system.coldboxModifications.EventHandler" , instancePath = "preside.system.coldboxModifications.EventHandler" ) - .addDIConstructorArgument( name="controller", value=controller ); + .setScope( "singleton" ); } } diff --git a/system/coldboxModifications/services/Renderer.cfc b/system/coldboxModifications/services/Renderer.cfc index fa6ca09a48..8d1e0307c2 100644 --- a/system/coldboxModifications/services/Renderer.cfc +++ b/system/coldboxModifications/services/Renderer.cfc @@ -57,50 +57,53 @@ component accessors="true" serializable="false" singleton="true" extends="coldbo * @controller The ColdBox main controller * @controller.inject coldbox */ - function init( required controller ){ - // setup controller - variables.controller = arguments.controller; + /** + * CB 7.0: LoaderService calls renderer.startup() after all modules loaded. + * In CB 7, controller is injected via DI rather than passed to init(). + * We use startup() to perform the initialisation that was in init(). + */ + function startup() { + if ( variables._startupDone ?: false ) { return; } + variables._startupDone = true; + + // In CB 7, controller may be injected as a property rather than passed to init + if ( IsNull( variables.controller ) ) { return; } + // Register LogBox - variables.logBox = arguments.controller.getLogBox(); - // Register Log object + variables.logBox = variables.controller.getLogBox(); variables.log = variables.logBox.getLogger( this ); - // Register Flash RAM - variables.flash = arguments.controller.getRequestService().getFlashScope(); - // Register CacheBox - variables.cacheBox = arguments.controller.getCacheBox(); - // Register WireBox - variables.wireBox = arguments.controller.getWireBox(); - // Register thread utils - variables.threadUtil = wirebox.getInstance( "threadUtil" ); - - // Set Conventions, Settings and Properties - variables.layoutsConvention = variables.controller.getSetting( "layoutsConvention", true ); - variables.viewsConvention = variables.controller.getSetting( "viewsConvention", true ); - variables.appMapping = variables.controller.getSetting( "AppMapping" ); - variables.viewsExternalLocation = variables.controller.getSetting( "ViewsExternalLocation" ); - variables.layoutsExternalLocation = variables.controller.getSetting( "LayoutsExternalLocation" ); - variables.modulesConfig = variables.controller.getSetting( "modules" ); - variables.viewsHelper = variables.controller.getSetting( "viewsHelper" ); - variables.viewCaching = variables.controller.getSetting( "viewCaching" ); - variables.isViewsHelperIncluded = false; - - // Verify View Helper Template extension + location - if( len( variables.viewsHelper ) ){ - // extension detection - variables.viewsHelper = ( listLast( variables.viewsHelper, "." ) eq "cfm" ? variables.viewsHelper : variables.viewsHelper & ".cfm" ); - // Append mapping to it. - variables.viewsHelper = "/#variables.appMapping#/#variables.viewsHelper#"; - } - - // Template Cache & Caching Maps - variables.renderedHelpers = {}; - variables.lockName = "rendering.#variables.controller.getAppHash()#"; - - // Discovery caching is tied to handlers for discovery. - variables.isDiscoveryCaching = controller.getSetting( "handlerCaching" ); - - // Load global UDF Libraries into target - loadApplicationHelpers(); + variables.flash = variables.controller.getRequestService().getFlashScope(); + variables.cacheBox = variables.controller.getCacheBox(); + variables.wireBox = variables.controller.getWireBox(); + variables.threadUtil = variables.wireBox.getInstance( "threadUtil" ); + + variables.layoutsConvention = variables.controller.getSetting( "layoutsConvention", true ); + variables.viewsConvention = variables.controller.getSetting( "viewsConvention", true ); + variables.appMapping = variables.controller.getSetting( "AppMapping" ); + variables.viewsExternalLocation = variables.controller.getSetting( "ViewsExternalLocation" ); + variables.layoutsExternalLocation = variables.controller.getSetting( "LayoutsExternalLocation" ); + variables.modulesConfig = variables.controller.getSetting( "modules" ); + variables.viewsHelper = variables.controller.getSetting( "viewsHelper" ); + variables.viewCaching = variables.controller.getSetting( "viewCaching" ); + variables.isDiscoveryCaching = variables.controller.getSetting( "handlerCaching" ); + variables.templateCache = variables.cacheBox.getCache( "template" ); + + if ( Len( variables.viewsHelper ) ) { + variables.viewsHelper = ( ListLast( variables.viewsHelper, "." ) eq "cfm" ? variables.viewsHelper : variables.viewsHelper & ".cfm" ); + } + + variables.renderedHelpers = variables.renderedHelpers ?: {}; + variables.lockName = "rendering.#variables.controller.getAppHash()#"; + + loadApplicationHelpers( force: true ); + } + + function init( controller ){ + if ( !IsNull( arguments.controller ) ) { + variables.controller = arguments.controller; + startup(); + } + variables.renderedHelpers = {}; return this; } diff --git a/system/config/Router.cfc b/system/config/Router.cfc index 86c0d64daf..28166d3962 100644 --- a/system/config/Router.cfc +++ b/system/config/Router.cfc @@ -100,7 +100,7 @@ component extends="coldbox.system.web.routing.Router" { arguments.dsl = "delayedInjector:" & arguments.dsl; } - return super.getInstance( + return variables.controller.getWirebox().getInstance( dsl = arguments.dsl ?: NullValue() , initArguments = arguments.initArguments ); From 053469a111142f65e90b03fddff83c9a3306f535 Mon Sep 17 00:00:00 2001 From: Test Date: Fri, 27 Mar 2026 17:59:30 +0000 Subject: [PATCH 03/15] Fix CB 7.0 renderView/renderLayout not returning values + Renderer init fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CB 7.0 deprecated renderView(), renderLayout() and renderExternalView() on FrameworkSupertype — critically, the deprecated wrappers no longer return values. This caused blank frontend pages and undefined variable errors throughout Preside where handler/view code relies on return values. Fix: restore returning versions in EventHandler shim, Interceptor shim, and presideProxies application helper. Also fixes: - Renderer.startup(): restored missing isViewsHelperIncluded, viewsHelper path prepend with appMapping, removed duplicate renderedHelpers reset - Controller.getRenderer(): call startup() on first creation - MetadataIndexer: added missing clearAll() method --- system/coldboxModifications/Controller.cfc | 1 + system/coldboxModifications/EventHandler.cfc | 23 +++++++++++++++++++ system/coldboxModifications/Interceptor.cfc | 15 ++++++++++++ .../store/indexers/MetadataIndexer.cfc | 4 ++++ .../services/Renderer.cfc | 13 +++++++---- system/helpers/presideProxies.cfm | 9 ++++++++ 6 files changed, 61 insertions(+), 4 deletions(-) diff --git a/system/coldboxModifications/Controller.cfc b/system/coldboxModifications/Controller.cfc index f1c06e1d45..d12e7692e3 100644 --- a/system/coldboxModifications/Controller.cfc +++ b/system/coldboxModifications/Controller.cfc @@ -18,6 +18,7 @@ component extends="coldbox.system.web.Controller" { return variables._renderer; } catch( any e ) { variables._renderer = variables.wireBox.getInstance( "presideRenderer" ); + variables._renderer.startup(); } return variables._renderer; } diff --git a/system/coldboxModifications/EventHandler.cfc b/system/coldboxModifications/EventHandler.cfc index a47071f716..20bb8d5f34 100644 --- a/system/coldboxModifications/EventHandler.cfc +++ b/system/coldboxModifications/EventHandler.cfc @@ -35,4 +35,27 @@ component extends="coldbox.system.EventHandler" { return getInstance( argumentCollection=arguments ); } + /** + * CB 7.0: renderView() deprecated and no longer returns a value. + * Restore the return so Preside handlers get their rendered content. + */ + function renderView(){ + return getRenderer().renderView( argumentCollection=arguments ); + } + + /** + * CB 7.0: renderLayout() deprecated and no longer returns a value. + * Restore the return so Preside handlers get their rendered content. + */ + function renderLayout(){ + return getRenderer().renderLayout( argumentCollection=arguments ); + } + + /** + * CB 7.0: renderExternalView() deprecated and no longer returns a value. + */ + function renderExternalView(){ + return getRenderer().renderExternalView( argumentCollection=arguments ); + } + } diff --git a/system/coldboxModifications/Interceptor.cfc b/system/coldboxModifications/Interceptor.cfc index 13d27f02fd..bcdef30f09 100644 --- a/system/coldboxModifications/Interceptor.cfc +++ b/system/coldboxModifications/Interceptor.cfc @@ -25,4 +25,19 @@ component extends="coldbox.system.Interceptor" { return getInstance( argumentCollection=arguments ); } + /** + * CB 7.0: renderView() deprecated and no longer returns a value. + */ + function renderView(){ + return getRenderer().renderView( argumentCollection=arguments ); + } + + function renderLayout(){ + return getRenderer().renderLayout( argumentCollection=arguments ); + } + + function renderExternalView(){ + return getRenderer().renderExternalView( argumentCollection=arguments ); + } + } diff --git a/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc b/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc index d20956651a..1fc77a72f2 100644 --- a/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc +++ b/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc @@ -48,6 +48,10 @@ component { } } + public void function clearAll() { + variables.poolMetadata.clear(); + } + public any function getSize() { return variables.poolMetadata.size(); } diff --git a/system/coldboxModifications/services/Renderer.cfc b/system/coldboxModifications/services/Renderer.cfc index 8d1e0307c2..139d290a2b 100644 --- a/system/coldboxModifications/services/Renderer.cfc +++ b/system/coldboxModifications/services/Renderer.cfc @@ -86,16 +86,22 @@ component accessors="true" serializable="false" singleton="true" extends="coldbo variables.viewsHelper = variables.controller.getSetting( "viewsHelper" ); variables.viewCaching = variables.controller.getSetting( "viewCaching" ); variables.isDiscoveryCaching = variables.controller.getSetting( "handlerCaching" ); - variables.templateCache = variables.cacheBox.getCache( "template" ); + variables.isViewsHelperIncluded = false; + // Verify View Helper Template extension + location if ( Len( variables.viewsHelper ) ) { variables.viewsHelper = ( ListLast( variables.viewsHelper, "." ) eq "cfm" ? variables.viewsHelper : variables.viewsHelper & ".cfm" ); + variables.viewsHelper = "/#variables.appMapping#/#variables.viewsHelper#"; } - variables.renderedHelpers = variables.renderedHelpers ?: {}; + // Template Cache & Caching Maps + variables.renderedHelpers = {}; variables.lockName = "rendering.#variables.controller.getAppHash()#"; - loadApplicationHelpers( force: true ); + // Load global UDF Libraries into target + loadApplicationHelpers(); + + return this; } function init( controller ){ @@ -103,7 +109,6 @@ component accessors="true" serializable="false" singleton="true" extends="coldbo variables.controller = arguments.controller; startup(); } - variables.renderedHelpers = {}; return this; } diff --git a/system/helpers/presideProxies.cfm b/system/helpers/presideProxies.cfm index 93120dbb6e..c929478431 100644 --- a/system/helpers/presideProxies.cfm +++ b/system/helpers/presideProxies.cfm @@ -269,6 +269,15 @@ + + + + + + + + + From 2ff76017ee67828f38eaccd9c867f758d29c44c5 Mon Sep 17 00:00:00 2001 From: Test Date: Fri, 27 Mar 2026 18:12:40 +0000 Subject: [PATCH 04/15] Update ColdBox dependency to 8.0.5 --- box.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/box.json b/box.json index 23d2d2d295..a0ef074a2c 100644 --- a/box.json +++ b/box.json @@ -37,7 +37,7 @@ "cbmessagebox":"2.2.0+10", "cbstorages":"1.3.0+14", "cbjavaloader":"1.5.0+35", - "coldbox":"7.5.2", + "coldbox":"8.0.5", "cfconcurrent":"3.0.0", "JSONPrettyPrint":"1.4.1", "cfflow":"0.8.0" From db11fd2de035e66a19e57ed80948587e6a9dbcdc Mon Sep 17 00:00:00 2001 From: Test Date: Fri, 27 Mar 2026 18:24:42 +0000 Subject: [PATCH 05/15] Update ColdBox dependency to 8.1.0-snapshot --- box.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/box.json b/box.json index a0ef074a2c..7f7c9b8eb1 100644 --- a/box.json +++ b/box.json @@ -37,7 +37,7 @@ "cbmessagebox":"2.2.0+10", "cbstorages":"1.3.0+14", "cbjavaloader":"1.5.0+35", - "coldbox":"8.0.5", + "coldbox":"8.1.0-snapshot", "cfconcurrent":"3.0.0", "JSONPrettyPrint":"1.4.1", "cfflow":"0.8.0" From 098b3e71483a059f37cdad6e756c63e5b5b08860 Mon Sep 17 00:00:00 2001 From: Test Date: Fri, 27 Mar 2026 19:19:07 +0000 Subject: [PATCH 06/15] Fix CB 8.0 getSystemSetting() shadowing Preside's helper CB 8.0 added getSystemSetting(key, defaultValue) to FrameworkSupertype for env variable lookup. This shadows Preside's getSystemSetting(category, setting, default) which delegates to systemConfigurationService. Added override to EventHandler and Interceptor shims to restore Preside's version. --- system/coldboxModifications/EventHandler.cfc | 9 +++++++++ system/coldboxModifications/Interceptor.cfc | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/system/coldboxModifications/EventHandler.cfc b/system/coldboxModifications/EventHandler.cfc index 20bb8d5f34..09fc609edf 100644 --- a/system/coldboxModifications/EventHandler.cfc +++ b/system/coldboxModifications/EventHandler.cfc @@ -35,6 +35,15 @@ component extends="coldbox.system.EventHandler" { return getInstance( argumentCollection=arguments ); } + /** + * CB 8.0: FrameworkSupertype added getSystemSetting(key, defaultValue) which + * shadows Preside's getSystemSetting(category, setting, default) helper. + * Restore Preside's version. + */ + function getSystemSetting(){ + return getInstance( "systemConfigurationService" ).getSetting( argumentCollection=arguments ); + } + /** * CB 7.0: renderView() deprecated and no longer returns a value. * Restore the return so Preside handlers get their rendered content. diff --git a/system/coldboxModifications/Interceptor.cfc b/system/coldboxModifications/Interceptor.cfc index bcdef30f09..ec0d874aff 100644 --- a/system/coldboxModifications/Interceptor.cfc +++ b/system/coldboxModifications/Interceptor.cfc @@ -25,6 +25,14 @@ component extends="coldbox.system.Interceptor" { return getInstance( argumentCollection=arguments ); } + /** + * CB 8.0: FrameworkSupertype added getSystemSetting(key, defaultValue) which + * shadows Preside's getSystemSetting(category, setting, default) helper. + */ + function getSystemSetting(){ + return getInstance( "systemConfigurationService" ).getSetting( argumentCollection=arguments ); + } + /** * CB 7.0: renderView() deprecated and no longer returns a value. */ From dd757cbf2929772a794b86a86abaa8237b8af17e Mon Sep 17 00:00:00 2001 From: Test Date: Fri, 27 Mar 2026 19:46:53 +0000 Subject: [PATCH 07/15] Fix CB 8 interceptor helper loading order and createInterceptor signature - InterceptorService.announce(): trigger cbLoadInterceptorHelpers before afterConfigurationLoad so Preside interceptors have access to helpers like isFeatureEnabled() during startup - InterceptorService.createInterceptor(): updated for CB 8 signature (injector parameter, no controller constructor arg) - InterceptorService.injectorSeedBaseClasses(): replaced wireboxSetup() which was removed in CB 7/8 --- .../services/InterceptorService.cfc | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/system/coldboxModifications/services/InterceptorService.cfc b/system/coldboxModifications/services/InterceptorService.cfc index 3b0bca8ad1..e04419e91b 100644 --- a/system/coldboxModifications/services/InterceptorService.cfc +++ b/system/coldboxModifications/services/InterceptorService.cfc @@ -55,6 +55,13 @@ component extends="coldbox.system.web.services.InterceptorService" { return; } + // CB 7/8: cbLoadInterceptorHelpers fires AFTER afterConfigurationLoad, + // but Preside interceptors need helpers (isFeatureEnabled etc.) during + // afterConfigurationLoad. Ensure helpers are loaded first. + if ( arguments.state == "afterConfigurationLoad" && StructKeyExists( variables.interceptionStates, "cbLoadInterceptorHelpers" ) ) { + super.announce( state="cbLoadInterceptorHelpers", data={} ); + } + return super.announce( argumentCollection=arguments ); } @@ -94,38 +101,39 @@ component extends="coldbox.system.web.services.InterceptorService" { /** * Override createInterceptor to use Preside's Interceptor shim - * which eagerly loads application helpers in the constructor (CB 5.4 behaviour). + * which restores getModel(), renderView() etc. + * Updated for CB 8 signature (injector parameter, no controller constructor arg). */ function createInterceptor( required interceptorClass, required interceptorName, - struct interceptorProperties = {} + struct interceptorProperties = {}, + injector = variables.wirebox ){ - if ( NOT variables.wirebox.getBinder().mappingExists( "interceptor-" & arguments.interceptorName ) ) { - wireboxSetup(); - variables.wirebox + if ( NOT arguments.injector.getBinder().mappingExists( "interceptor-" & arguments.interceptorName ) ) { + injectorSeedBaseClasses( arguments.injector ); + arguments.injector .registerNewInstance( name = "interceptor-" & arguments.interceptorName , instancePath = arguments.interceptorClass ) - .setScope( variables.wirebox.getBinder().SCOPES.SINGLETON ) + .setScope( arguments.injector.getBinder().SCOPES.SINGLETON ) .setThreadSafe( true ) .setVirtualInheritance( "preside.system.coldboxModifications.Interceptor" ) - .addDIConstructorArgument( name="controller", value=controller ) .addDIConstructorArgument( name="properties", value=arguments.interceptorProperties ); } return getInterceptor( arguments.interceptorName ); } - private function wireboxSetup(){ - if ( NOT variables.wirebox.getBinder().mappingExists( "preside.system.coldboxModifications.Interceptor" ) ) { - variables.wirebox + private function injectorSeedBaseClasses( required injector ){ + super.injectorSeedBaseClasses( arguments.injector ); + if ( NOT arguments.injector.getBinder().mappingExists( "preside.system.coldboxModifications.Interceptor" ) ) { + arguments.injector .registerNewInstance( name = "preside.system.coldboxModifications.Interceptor" , instancePath = "preside.system.coldboxModifications.Interceptor" ) - .addDIConstructorArgument( name="controller", value=controller ) - .addDIConstructorArgument( name="properties", value={} ); + .setScope( "singleton" ); } } From d4e79a61fa8e621cc6d44107d672f346cdebfa54 Mon Sep 17 00:00:00 2001 From: Test Date: Tue, 31 Mar 2026 17:14:59 +0100 Subject: [PATCH 08/15] Fix StackOverflow from layout() infinite recursion in CB 7.0+ ColdBox 7.0 renamed renderLayout() to layout() in FrameworkSupertype. Since Renderer extends FrameworkSupertype and Preside's Renderer only overrides renderLayout(), calling layout() fell through to FrameworkSupertype.layout() which calls getRenderer().layout() in a loop. Add layout() shims to Renderer, EventHandler and Interceptor that delegate to renderLayout(). --- system/coldboxModifications/EventHandler.cfc | 8 ++++++++ system/coldboxModifications/Interceptor.cfc | 8 ++++++++ .../coldboxModifications/services/Renderer.cfc | 17 +++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/system/coldboxModifications/EventHandler.cfc b/system/coldboxModifications/EventHandler.cfc index 09fc609edf..3245b5aa82 100644 --- a/system/coldboxModifications/EventHandler.cfc +++ b/system/coldboxModifications/EventHandler.cfc @@ -60,6 +60,14 @@ component extends="coldbox.system.EventHandler" { return getRenderer().renderLayout( argumentCollection=arguments ); } + /** + * CB 7.0: layout() replaced renderLayout() in FrameworkSupertype. + * Override to prevent infinite recursion via FrameworkSupertype.layout() -> getRenderer().layout() + */ + function layout(){ + return getRenderer().renderLayout( argumentCollection=arguments ); + } + /** * CB 7.0: renderExternalView() deprecated and no longer returns a value. */ diff --git a/system/coldboxModifications/Interceptor.cfc b/system/coldboxModifications/Interceptor.cfc index ec0d874aff..5d2020f322 100644 --- a/system/coldboxModifications/Interceptor.cfc +++ b/system/coldboxModifications/Interceptor.cfc @@ -44,6 +44,14 @@ component extends="coldbox.system.Interceptor" { return getRenderer().renderLayout( argumentCollection=arguments ); } + /** + * CB 7.0: layout() replaced renderLayout() in FrameworkSupertype. + * Override to prevent infinite recursion via FrameworkSupertype.layout() -> getRenderer().layout() + */ + function layout(){ + return getRenderer().renderLayout( argumentCollection=arguments ); + } + function renderExternalView(){ return getRenderer().renderExternalView( argumentCollection=arguments ); } diff --git a/system/coldboxModifications/services/Renderer.cfc b/system/coldboxModifications/services/Renderer.cfc index 139d290a2b..1dd760f030 100644 --- a/system/coldboxModifications/services/Renderer.cfc +++ b/system/coldboxModifications/services/Renderer.cfc @@ -518,6 +518,23 @@ component accessors="true" serializable="false" singleton="true" extends="coldbo * @viewModule The module to explicitly render the view from * @prePostExempt If true, pre/post layout interceptors will not be fired. By default they do fire */ + /** + * CB 7.0: layout() is the new name for renderLayout(). + * Delegate to our renderLayout() override to avoid infinite recursion + * via FrameworkSupertype.layout() -> getRenderer().layout() -> FrameworkSupertype.layout() + */ + function layout( + layout, + module="", + view="", + struct args=getRequestContext().getCurrentViewArgs(), + viewModule="", + boolean prePostExempt=false, + viewVariables={} + ){ + return renderLayout( argumentCollection=arguments ); + } + function renderLayout( layout, module="", From 89bb1fb2594d1641d1ee9f05e0c6f8e94c9e1bfa Mon Sep 17 00:00:00 2001 From: Test Date: Tue, 31 Mar 2026 17:32:36 +0100 Subject: [PATCH 09/15] Add CB 7.0 compatibility shims for renamed rendering methods ColdBox 7.0 renamed renderView() -> view(), renderExternalView() -> externalView(), and removed setNextEvent() from Controller. The deprecated renderView() now delegates to this.view(), bypassing Preside's custom view path resolution and causing layouts to render within themselves with no page content. Add view() and externalView() shims to Renderer, EventHandler and Interceptor that delegate to the existing renderView()/ renderExternalView() implementations. Add setNextEvent() shim to Controller that delegates to relocate(). --- system/coldboxModifications/Controller.cfc | 20 +++++++++ system/coldboxModifications/EventHandler.cfc | 14 ++++++ system/coldboxModifications/Interceptor.cfc | 14 ++++++ .../services/Renderer.cfc | 43 +++++++++++++++++++ 4 files changed, 91 insertions(+) diff --git a/system/coldboxModifications/Controller.cfc b/system/coldboxModifications/Controller.cfc index d12e7692e3..1ab3fe0853 100644 --- a/system/coldboxModifications/Controller.cfc +++ b/system/coldboxModifications/Controller.cfc @@ -260,6 +260,26 @@ component extends="coldbox.system.web.Controller" { return getRequestService().getContext(); } + /** + * Compatibility shim: setNextEvent() was removed in ColdBox 7.0. + * Delegates to relocate() which is the replacement. + */ + void function setNextEvent( + event + , URL + , URI + , queryString + , persist + , struct persistStruct + , boolean addToken + , boolean ssl + , baseURL + , boolean postProcessExempt + , numeric statusCode + ){ + relocate( argumentCollection=arguments ); + } + /** * Compatibility shim: getSettingStructure() was removed in ColdBox 6.0 * Delegates to the configSettings/coldboxSettings structs directly. diff --git a/system/coldboxModifications/EventHandler.cfc b/system/coldboxModifications/EventHandler.cfc index 3245b5aa82..f053600252 100644 --- a/system/coldboxModifications/EventHandler.cfc +++ b/system/coldboxModifications/EventHandler.cfc @@ -68,6 +68,13 @@ component extends="coldbox.system.EventHandler" { return getRenderer().renderLayout( argumentCollection=arguments ); } + /** + * CB 7.0: view() replaced renderView() in FrameworkSupertype. + */ + function view(){ + return getRenderer().renderView( argumentCollection=arguments ); + } + /** * CB 7.0: renderExternalView() deprecated and no longer returns a value. */ @@ -75,4 +82,11 @@ component extends="coldbox.system.EventHandler" { return getRenderer().renderExternalView( argumentCollection=arguments ); } + /** + * CB 7.0: externalView() replaced renderExternalView() in FrameworkSupertype. + */ + function externalView(){ + return getRenderer().renderExternalView( argumentCollection=arguments ); + } + } diff --git a/system/coldboxModifications/Interceptor.cfc b/system/coldboxModifications/Interceptor.cfc index 5d2020f322..47f92a267e 100644 --- a/system/coldboxModifications/Interceptor.cfc +++ b/system/coldboxModifications/Interceptor.cfc @@ -52,8 +52,22 @@ component extends="coldbox.system.Interceptor" { return getRenderer().renderLayout( argumentCollection=arguments ); } + /** + * CB 7.0: view() replaced renderView() in FrameworkSupertype. + */ + function view(){ + return getRenderer().renderView( argumentCollection=arguments ); + } + function renderExternalView(){ return getRenderer().renderExternalView( argumentCollection=arguments ); } + /** + * CB 7.0: externalView() replaced renderExternalView() in FrameworkSupertype. + */ + function externalView(){ + return getRenderer().renderExternalView( argumentCollection=arguments ); + } + } diff --git a/system/coldboxModifications/services/Renderer.cfc b/system/coldboxModifications/services/Renderer.cfc index 1dd760f030..d9f182c914 100644 --- a/system/coldboxModifications/services/Renderer.cfc +++ b/system/coldboxModifications/services/Renderer.cfc @@ -518,6 +518,49 @@ component accessors="true" serializable="false" singleton="true" extends="coldbo * @viewModule The module to explicitly render the view from * @prePostExempt If true, pre/post layout interceptors will not be fired. By default they do fire */ + /** + * CB 7.0: view() is the new name for renderView(). + * Delegate to our renderView() override so Preside's custom view + * path resolution is used instead of vanilla ColdBox view(). + */ + function view( + view="", + struct args=getRequestContext().getCurrentViewArgs(), + module="", + boolean cache=false, + cacheTimeout="", + cacheLastAccessTimeout="", + cacheSuffix="", + cacheProvider="template", + collection, + collectionAs="", + numeric collectionStartRow="1", + numeric collectionMaxRows=0, + collectionDelim="", + boolean prePostExempt=false, + name, + viewVariables={} + ){ + return renderView( argumentCollection=arguments ); + } + + /** + * CB 7.0: externalView() is the new name for renderExternalView(). + * Delegate to our renderExternalView() override. + */ + function externalView( + required view, + struct args=getRequestContext().getCurrentViewArgs(), + boolean cache=false, + cacheTimeout="", + cacheLastAccessTimeout="", + cacheSuffix="", + cacheProvider="template", + viewVariables={} + ){ + return renderExternalView( argumentCollection=arguments ); + } + /** * CB 7.0: layout() is the new name for renderLayout(). * Delegate to our renderLayout() override to avoid infinite recursion From eadf82901fa1962be06ca2b6c2a9d3a0f940eaff Mon Sep 17 00:00:00 2001 From: Test Date: Tue, 31 Mar 2026 18:04:27 +0100 Subject: [PATCH 10/15] Remove layout(), view(), externalView() shims from EventHandler/Interceptor These public shims get mixed into all handlers via WireBox virtual inheritance, shadowing any handler-defined private viewlets with the same name (e.g. webflow/Default.cfc has a private layout() viewlet). This caused the ColdBox layout system to be invoked instead of the viewlet, producing double site layouts with missing webflow content. The Renderer retains its shims to prevent the FrameworkSupertype infinite recursion. EventHandler/Interceptor retain renderView(), renderLayout(), renderExternalView() shims since CB 7.0's deprecated versions don't return values. --- system/coldboxModifications/EventHandler.cfc | 22 -------------------- system/coldboxModifications/Interceptor.cfc | 22 -------------------- 2 files changed, 44 deletions(-) diff --git a/system/coldboxModifications/EventHandler.cfc b/system/coldboxModifications/EventHandler.cfc index f053600252..09fc609edf 100644 --- a/system/coldboxModifications/EventHandler.cfc +++ b/system/coldboxModifications/EventHandler.cfc @@ -60,21 +60,6 @@ component extends="coldbox.system.EventHandler" { return getRenderer().renderLayout( argumentCollection=arguments ); } - /** - * CB 7.0: layout() replaced renderLayout() in FrameworkSupertype. - * Override to prevent infinite recursion via FrameworkSupertype.layout() -> getRenderer().layout() - */ - function layout(){ - return getRenderer().renderLayout( argumentCollection=arguments ); - } - - /** - * CB 7.0: view() replaced renderView() in FrameworkSupertype. - */ - function view(){ - return getRenderer().renderView( argumentCollection=arguments ); - } - /** * CB 7.0: renderExternalView() deprecated and no longer returns a value. */ @@ -82,11 +67,4 @@ component extends="coldbox.system.EventHandler" { return getRenderer().renderExternalView( argumentCollection=arguments ); } - /** - * CB 7.0: externalView() replaced renderExternalView() in FrameworkSupertype. - */ - function externalView(){ - return getRenderer().renderExternalView( argumentCollection=arguments ); - } - } diff --git a/system/coldboxModifications/Interceptor.cfc b/system/coldboxModifications/Interceptor.cfc index 47f92a267e..ec0d874aff 100644 --- a/system/coldboxModifications/Interceptor.cfc +++ b/system/coldboxModifications/Interceptor.cfc @@ -44,30 +44,8 @@ component extends="coldbox.system.Interceptor" { return getRenderer().renderLayout( argumentCollection=arguments ); } - /** - * CB 7.0: layout() replaced renderLayout() in FrameworkSupertype. - * Override to prevent infinite recursion via FrameworkSupertype.layout() -> getRenderer().layout() - */ - function layout(){ - return getRenderer().renderLayout( argumentCollection=arguments ); - } - - /** - * CB 7.0: view() replaced renderView() in FrameworkSupertype. - */ - function view(){ - return getRenderer().renderView( argumentCollection=arguments ); - } - function renderExternalView(){ return getRenderer().renderExternalView( argumentCollection=arguments ); } - /** - * CB 7.0: externalView() replaced renderExternalView() in FrameworkSupertype. - */ - function externalView(){ - return getRenderer().renderExternalView( argumentCollection=arguments ); - } - } From f984f83198586cc87c375814239ca9ecffa15d31 Mon Sep 17 00:00:00 2001 From: Test Date: Tue, 31 Mar 2026 18:18:24 +0100 Subject: [PATCH 11/15] Add layout(), view(), externalView() back as private methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FrameworkSupertype's public layout()/view() get mixed into handlers via virtual inheritance's injectMixin(), which writes to both this AND variables scope — overwriting any handler-defined private method of the same name (e.g. webflow handler's private layout() viewlet). Making these private on EventHandler/Interceptor prevents them from appearing in the this scope, so virtual inheritance's public loop skips them and handler private methods are preserved. --- system/coldboxModifications/EventHandler.cfc | 18 ++++++++++++++++++ system/coldboxModifications/Interceptor.cfc | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/system/coldboxModifications/EventHandler.cfc b/system/coldboxModifications/EventHandler.cfc index 09fc609edf..56106d255b 100644 --- a/system/coldboxModifications/EventHandler.cfc +++ b/system/coldboxModifications/EventHandler.cfc @@ -67,4 +67,22 @@ component extends="coldbox.system.EventHandler" { return getRenderer().renderExternalView( argumentCollection=arguments ); } + /** + * CB 7.0: layout(), view(), externalView() replaced the render* versions. + * These MUST be private to prevent virtual inheritance from overwriting + * handler-defined private viewlets with the same name (e.g. webflow + * handler's private layout() viewlet). FrameworkSupertype's public + * layout()/view() would otherwise be mixed into the handler's variables + * scope via injectMixin, shadowing the handler's own private method. + */ + private function layout(){ + return getRenderer().renderLayout( argumentCollection=arguments ); + } + private function view(){ + return getRenderer().renderView( argumentCollection=arguments ); + } + private function externalView(){ + return getRenderer().renderExternalView( argumentCollection=arguments ); + } + } diff --git a/system/coldboxModifications/Interceptor.cfc b/system/coldboxModifications/Interceptor.cfc index ec0d874aff..5c3704cc09 100644 --- a/system/coldboxModifications/Interceptor.cfc +++ b/system/coldboxModifications/Interceptor.cfc @@ -48,4 +48,18 @@ component extends="coldbox.system.Interceptor" { return getRenderer().renderExternalView( argumentCollection=arguments ); } + /** + * CB 7.0: layout(), view(), externalView() replaced the render* versions. + * Private to avoid shadowing interceptor-defined methods of the same name. + */ + private function layout(){ + return getRenderer().renderLayout( argumentCollection=arguments ); + } + private function view(){ + return getRenderer().renderView( argumentCollection=arguments ); + } + private function externalView(){ + return getRenderer().renderExternalView( argumentCollection=arguments ); + } + } From 84739329ca97bb756db9a9444c65007ff4315ae2 Mon Sep 17 00:00:00 2001 From: Test Date: Tue, 31 Mar 2026 18:27:45 +0100 Subject: [PATCH 12/15] Fix CacheBox reap error: override getCachedObjectMetadata() on stores CB 7.0+ ConcurrentStore uses inline metadata (pool entries are structs with hits, timeout, etc.). Preside's store overrides use a separate MetadataIndexer with raw objects in the pool. The parent's getCachedObjectMetadata() reads from the pool expecting a struct but gets raw cached values (e.g. booleans), causing "no property [hits] found in [boolean]" during cache reaping. Override getCachedObjectMetadata() on both ConcurrentStore and ConcurrentSoftReferenceStore to read from the MetadataIndexer. --- .../cachebox/store/ConcurrentSoftReferenceStore.cfc | 8 ++++++++ .../cachebox/store/ConcurrentStore.cfc | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/system/coldboxModifications/cachebox/store/ConcurrentSoftReferenceStore.cfc b/system/coldboxModifications/cachebox/store/ConcurrentSoftReferenceStore.cfc index 0bad362283..097bc2344d 100644 --- a/system/coldboxModifications/cachebox/store/ConcurrentSoftReferenceStore.cfc +++ b/system/coldboxModifications/cachebox/store/ConcurrentSoftReferenceStore.cfc @@ -101,6 +101,14 @@ component extends="coldbox.system.cache.store.ConcurrentSoftReferenceStore" impl } ); } + public struct function getCachedObjectMetadata( required any objectKey ) { + var meta = variables.indexer.getObjectMetadata( arguments.objectKey ); + if ( IsNull( local.meta ) || !IsStruct( local.meta ) ) { + return {}; + } + return meta; + } + public any function clear( required any objectKey ) { var isSR = variables.indexer.getObjectMetadataProperty( arguments.objectKey, "isSoftReference" ); diff --git a/system/coldboxModifications/cachebox/store/ConcurrentStore.cfc b/system/coldboxModifications/cachebox/store/ConcurrentStore.cfc index d3817ac367..a735165418 100644 --- a/system/coldboxModifications/cachebox/store/ConcurrentStore.cfc +++ b/system/coldboxModifications/cachebox/store/ConcurrentStore.cfc @@ -69,6 +69,14 @@ component extends="coldbox.system.cache.store.ConcurrentStore" implements="" { } ); } + public struct function getCachedObjectMetadata( required any objectKey ) { + var meta = indexer.getObjectMetadata( arguments.objectKey ); + if ( IsNull( local.meta ) || !IsStruct( local.meta ) ) { + return {}; + } + return meta; + } + public any function clear( required any objectKey ) { var removedObj = pool.remove( arguments.objectKey ); var removedMeta = indexer.clear( arguments.objectKey ); From 6c9956bfaff51fc440f1f501025ddebb3a7d89c4 Mon Sep 17 00:00:00 2001 From: Test Date: Tue, 31 Mar 2026 18:41:13 +0100 Subject: [PATCH 13/15] Add getSortedKeys() to MetadataIndexer for cache eviction policies CB 7.0 eviction policies (LRU, LFU, FIFO, LIFO) call getIndexer().getSortedKeys() to sort cache entries for eviction. Preside's MetadataIndexer replacement was missing this method, which would prevent proper cache eviction. --- .../cachebox/store/indexers/MetadataIndexer.cfc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc b/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc index 1fc77a72f2..7050d4960b 100644 --- a/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc +++ b/system/coldboxModifications/cachebox/store/indexers/MetadataIndexer.cfc @@ -48,6 +48,19 @@ component { } } + public array function getSortedKeys( + required any property, + any sortType = "text", + any sortOrder = "asc" + ) { + return structSort( + variables.poolMetadata, + arguments.sortType, + arguments.sortOrder, + arguments.property + ); + } + public void function clearAll() { variables.poolMetadata.clear(); } From d8194b91dd3560ca7fd2a17f7214c9e8dfe99f51 Mon Sep 17 00:00:00 2001 From: Test Date: Tue, 31 Mar 2026 18:42:51 +0100 Subject: [PATCH 14/15] Move startup guard after controller null check in Renderer Set _startupDone only after confirming controller is available, so startup() can be retried if called before DI completes. --- system/coldboxModifications/services/Renderer.cfc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/coldboxModifications/services/Renderer.cfc b/system/coldboxModifications/services/Renderer.cfc index d9f182c914..b93eaf7f47 100644 --- a/system/coldboxModifications/services/Renderer.cfc +++ b/system/coldboxModifications/services/Renderer.cfc @@ -64,11 +64,12 @@ component accessors="true" serializable="false" singleton="true" extends="coldbo */ function startup() { if ( variables._startupDone ?: false ) { return; } - variables._startupDone = true; // In CB 7, controller may be injected as a property rather than passed to init if ( IsNull( variables.controller ) ) { return; } + variables._startupDone = true; + // Register LogBox variables.logBox = variables.controller.getLogBox(); variables.log = variables.logBox.getLogger( this ); From 03d3e51ec3cd5f19ef9335de47dbaddff945e8ef Mon Sep 17 00:00:00 2001 From: Test Date: Tue, 31 Mar 2026 18:43:42 +0100 Subject: [PATCH 15/15] Remove orphaned DI annotation comment from Renderer The old init() doc block with @controller.inject was left above startup(), which is misleading and could confuse WireBox annotation scanning. --- system/coldboxModifications/services/Renderer.cfc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/system/coldboxModifications/services/Renderer.cfc b/system/coldboxModifications/services/Renderer.cfc index b93eaf7f47..b6f2e17e23 100644 --- a/system/coldboxModifications/services/Renderer.cfc +++ b/system/coldboxModifications/services/Renderer.cfc @@ -52,11 +52,6 @@ component accessors="true" serializable="false" singleton="true" extends="coldbo /************************************** CONSTRUCTOR *********************************************/ - /** - * Constructor - * @controller The ColdBox main controller - * @controller.inject coldbox - */ /** * CB 7.0: LoaderService calls renderer.startup() after all modules loaded. * In CB 7, controller is injected via DI rather than passed to init().