Thoughts on Overrides that Survive Upgrading

Hello all.

Let me begin with the caveat that I may be missing something that enables the functionality I am about to describe. If that is true, please let me know and I will adjust my methodology accordingly.

I’m working on setting up a ContentBox site that will involve editing the out of the box security to increase the security of encryption and hashing. In working on this site it occurs to me that one potential issue with being able to edit ContentBox code is the fact that making such modifications to the ContentBox cfcs requires every change be thoroughly documented and tracked (never a bad thing, of course) to ensure that the same changes are made in the future if/when we find a need to upgrade to a future version of the ContentBox core. But I think we all know that when you’re working on a project, especially during those final hours/days before deployment when last minute changes in requirements come in, documentation can be missed or mistakes made in the documentation. Adjusting the framework to facilitate easy upgrades of modified ContentBox sites would greatly increase the sustainability ContentBox sites.

It seems to me that the way to enable this would be to create a mirrored shell of the core framework files that mimics the entire structure of the framework. Ok, now I’ll wait for the shock and laughter to subside as I know this would be a monumental task.

What would it entail? My concept would be that there would be a mirror directory structure containing a blank cfc for each and every cfc in the core. Each cfc would extend its matching, fully coded core file. Each injection, function call, etc. in the core would point to the shell mirror instead of the coded core file. This way, any upgrades would update the files in the core, leaving any modifications made in the shell mirror in tact. Either way a developer would need to work to make their site function properly upon upgrading to the newer version. But if all of the developer’s modifications are in a separate set of files from the out of the box code, I think that would encourage developers to take ContentBox (and ColdBox, for that matter, if the same were done with ColdBox) and really push it further without fear of needing to re-implement modified code every time you upgrade.

I’m curious to hear what others think of this concept?

John

You certainly can, although this is for the captcha plugin I have been able to do it for any wired aspect of ContentBox.

http://www.andyscott.id.au/blog/a-funky-way-to-replacing-captcha-in-contentbox

tldr; Modifying the core files of a framework is NEVER* a good idea.

It has been a really long time since I have used ColdBox, but I am 100% certain that there are multiple extension options in place that will allow you to override to extend functionality, etc. The documentation (http://wiki.coldbox.org/) is a good place to start learning about those options. You’ll likely be interested in interceptors and “external locations” that will allow you to have your own custom CFCs - that might extend the core CFCs - for your added requirements.

*If you are adding functionality that would be useful to the core, forking the project, making the enhancements, and submitting a pull request is the one exception to the “never modify the core files of a framework” rule. By doing this, assuming the changes are accepted, you would be contributing to the community and the overall health of the framework project. If your enhancements are application-specific, or include business logic that is proprietary in nature, then refer back to the never modify rule. :slight_smile:

Ok, looks like the functionality I need is indeed in place. So my entire post can pretty much be ignored. Thanks for the quick response all.

I’m glad you have this worked out. Just to reinforce what Matt and Andrew said, there should be zero reason to ever need to touch core ContentBox code. We pride ourselves in being the most extensible CFML CMS and most of it is all built around interceptions points which are best wrapped up in a module. If you ever find yourself wanting to modify anything in the core, please ask here and we’ll show you how to extend it properly, or we’ll fix it so you can :slight_smile:

You can see some examples of ContentBox modules here on ForgeBox:
http://www.coldbox.org/forgebox/type/contentbox-modules

We also have a webinar recording you can watch that shows you how to extend ContentBox with modules:
http://www.coldbox.org/media/cbdw2013#5_2

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Looks like I’m going to have to re-open this item.

First, let me say I greatly appreciate how helpful everyone here is and how quickly people jump in to give support.

Now, on to the problem. I’ve been reading up on interceptors and models, but I don’t think they are addressing my issue.

If I were writing the code that consumes the extended core functionality, this would be easy. But I need the core to consume the extended version of the core file. That’s where I have a problem.

I need to change modules.contentbox.model.security.AuthorService.cfc line 41

from
setHashType( “SHA-256” );

to
setHashType( “SHA-512” );

That would be a hardcoded version. I actually intend the following:

dynamic
setHashType( getSetting(“globalHashAlgorithm”) );

Of course, I don’t want to actually change the AuthorService.cfc file. This entire thread is about the desire to not have to edit the core. I want to leave it alone and simply override the init function to make this one change. Nothing I have seen in interceptors or models addresses this issue. Creating a module won’t change the built-in functionality in the core. I could create an interceptor that extends the AuthorService, but there is no built-in core interceptor point that I can see that would enable me to override a single method or override a cfc.

Andrew’s example of a plugin interceptor would make it possible, but I would still have to make a change to a core file and I am then adding overhead to every time an instance of anything is created.

As for QuackFuzed’s suggestion to search for “external locations,” I get zero results on that phrase.

So, am I missing something? (Certainly possible. This is my first project using ColdBox and ContentBox. I’ve custom coded everything over the past 17 years I’ve been coding in ColdFusion.)

No, Luis has since fixed that issue. I should have mentioned that, I will need to update that post to reflect that.

Hi ,

You can easily alter this with a module and wirebox, actually in one simple function in your module:

onLoad(){
wirebox.getInstance( “AuthorService@cb” ).setHashType( “SHA-512” );
}

That’s it.

Luis Majano
CEO
Ortus Solutions, Corp

P/F: 1-888-557-8057
Direct: (909) 248-3408

ColdBox Platform: http://www.coldbox.org
ContentBox Platform: http://www.gocontentbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Social: twitter.com/ortussolutions | twitter.com/coldbox | twitter.com/lmajano | twitter.com/gocontentbox

Yes! That is simply beautiful (as in beautiful in its simplicity).

And to override the entire author service with my extended version, I simply bind the mapping in my module’s ModuleConfig.cfc configure() function to override built-in AuthorService as follows:

binder.map(“AuthorService@cb”).to("#moduleMapping#.model.security.AuthorService");

Ok, now I’m (slowly) starting to get it.

I knew you’d love the at least one of the options available. :slight_smile:

You will have to unmap it first. WireBox does not override mappings by default. So you have to choices:

  1. Use the force=true argument in the map()
  2. Unmap( “AuthorService@cb” ) and then map it again.

Luis Majano
CEO
Ortus Solutions, Corp

P/F: 1-888-557-8057
Direct: (909) 248-3408

ColdBox Platform: http://www.coldbox.org
ContentBox Platform: http://www.gocontentbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Social: twitter.com/ortussolutions | twitter.com/coldbox | twitter.com/lmajano | twitter.com/gocontentbox

That’s interesting. I did the one line as I posted and it did indeed override and use my extended version of the AuthorService.

To further this discussion a little, I was wondering if I was missing a way that I could override a core model. For instance, I typically use UMT for all datetimes stored in systems. ContentBox uses now() to set dates and times.

I did raise a ticker back in the Assembla days, where I asked for all the date/times to follow the number od seconds since and do have timezones support, therefore the Admin could be used to translate them. With my site in another time zone to me and many clients, make translating the data to local zones much easier than what we have.

Good to know. Times, though, was just an example. I would still like to know if there was a way to override base components (other than the services, which everyone has graciously pointed me in the right direction on).

As for the times, looking in the database I see that they are stored as the local timezone datetime. How do you accomplish timezone support?

What sort of base components?

Anything that is Wireboxed can be over ridden. Plenty of tips and tricks on ColdBox and ContentBox over here.

http://www.andyscott.id.au/blog/a-funky-way-to-replacing-captcha-in-contentbox

As I noted previously, I have read your blog on replacing captcha, but I find that to be rather inelegant as it creates overhead for every handler called rather than just on the targeted handler.

As for what kind of base components, really any kind. At different points in development I have found myself wanting to override handlers, models, plugins, etc. I would love to find ways for each aspect that make it as easy as with services.

My example had nothing to do with handlers, so if yours does then you need to look into the event pattern to stop that from happening.

Ok, yes, correction. Not a handler. But the point remains that the solution adds overhead to every instance creation. That just seems to be a lot of conditional statements that would end up being evaluated on the creation of every instance (assuming we end up overriding a bunch of items using this method). The preference would be to have a more direct override, as is done with the declaration of services. I’m not saying your solution isn’t cool, as I always appreciate ingenuity. I was just hoping there would be a solution with less overhead; something that says, “you’re looking for X? Here’s Y” instead of saying “you have X? Let me give you Y instead.”

How much of the core framework of ContentBox are you looking at surviving an upgrade?