PageRenderTime 16ms CodeModel.GetById 3ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/wheels/model/properties.cfm

http://cfwheels.googlecode.com/
ColdFusion | 539 lines | 501 code | 22 blank | 16 comment | 34 complexity | df208167323a8b67fde1d2b9b887fc4e MD5 | raw file
  1<!--- PUBLIC MODEL INITIALIZATION METHODS --->
  2
  3<cffunction name="accessibleProperties" returntype="void" access="public" output="false" hint="Use this method to specify which properties can be set through mass assignment."
  4	examples='
  5		<!--- In `models/User.cfc`, only `isActive` can be set through mass assignment operations like `updateAll()` --->
  6		<cffunction name="init">
  7			<cfset accessibleProperties("isActive")>
  8		</cffunction>
  9	'
 10	categories="model-initialization,miscellaneous" chapters="object-relational-mapping" functions="protectedProperties">
 11	<cfargument name="properties" type="string" required="false" default="" hint="Property name (or list of property names) that are allowed to be altered through mass assignment." />
 12	<cfscript>
 13		var loc = {};
 14		if (StructKeyExists(arguments, "property"))
 15			arguments.properties = ListAppend(arguments.properties, arguments.property);
 16		// see if any associations should be included in the white list
 17		for (loc.association in variables.wheels.class.associations)
 18			if (variables.wheels.class.associations[loc.association].nested.allow)
 19				arguments.properties = ListAppend(arguments.properties, loc.association);
 20		variables.wheels.class.accessibleProperties.whiteList = $listClean(arguments.properties);
 21	</cfscript>
 22</cffunction>
 23
 24<cffunction name="protectedProperties" returntype="void" access="public" output="false" hint="Use this method to specify which properties cannot be set through mass assignment."
 25	examples='
 26		<!--- In `models/User.cfc`, `firstName` and `lastName` cannot be changed through mass assignment operations like `updateAll()` --->
 27		<cffunction name="init">
 28			<cfset protectedProperties("firstName,lastName")>
 29		</cffunction>
 30	'
 31	categories="model-initialization,miscellaneous" chapters="object-relational-mapping" functions="accessibleProperties">
 32	<cfargument name="properties" type="string" required="false" default="" hint="Property name (or list of property names) that are not allowed to be altered through mass assignment." />
 33	<cfscript>
 34		var loc = {};
 35		if (StructKeyExists(arguments, "property"))
 36			arguments.properties = ListAppend(arguments.properties, arguments.property);
 37		variables.wheels.class.accessibleProperties.blackList = $listClean(arguments.properties);
 38	</cfscript>
 39</cffunction>
 40
 41<cffunction name="property" returntype="void" access="public" output="false" hint="Use this method to map an object property to either a table column with a different name than the property or to a SQL expression. You only need to use this method when you want to override the default object relational mapping that Wheels performs."
 42	examples=
 43	'
 44		<!--- Tell Wheels that when we are referring to `firstName` in the CFML code, it should translate to the `STR_USERS_FNAME` column when interacting with the database instead of the default (which would be the `firstname` column) --->
 45		<cfset property(name="firstName", column="STR_USERS_FNAME")>
 46
 47		<!--- Tell Wheels that when we are referring to `fullName` in the CFML code, it should concatenate the `STR_USERS_FNAME` and `STR_USERS_LNAME` columns --->
 48		<cfset property(name="fullName", sql="STR_USERS_FNAME + '' '' + STR_USERS_LNAME")>
 49
 50		<!--- Tell Wheels that when displaying error messages or labels for form fields, we want to use `First name(s)` as the label for the `STR_USERS_FNAME` column --->
 51		<cfset property(name="firstName", label="First name(s)")>
 52
 53		<!--- Tell Wheels that when creating new objects, we want them to be auto-populated with a `firstName` property of value `Dave` --->
 54		<cfset property(name="firstName", defaultValue="Dave")>
 55	'
 56	categories="model-initialization,miscellaneous" chapters="object-relational-mapping" functions="columnNames,dataSource,propertyNames,table,tableName">
 57	<cfargument name="name" type="string" required="true" hint="The name that you want to use for the column or SQL function result in the CFML code.">
 58	<cfargument name="column" type="string" required="false" default="" hint="The name of the column in the database table to map the property to.">
 59	<cfargument name="sql" type="string" required="false" default="" hint="A SQL expression to use to calculate the property value.">
 60	<cfargument name="label" type="string" required="false" default="" hint="A custom label for this property to be referenced in the interface and error messages.">
 61	<cfargument name="defaultValue" type="string" required="false" hint="A default value for this property.">
 62	<cfscript>
 63		// validate setup
 64		if (Len(arguments.column) and Len(arguments.sql))
 65			$throw(type="Wheels", message="Incorrect Arguments", extendedInfo="You cannot specify both a column and a sql statement when setting up the mapping for this property.");
 66		if (Len(arguments.sql) and StructKeyExists(arguments, "defaultValue"))
 67			$throw(type="Wheels", message="Incorrect Arguments", extendedInfo="You cannot specify a default value for calculated properties.");
 68
 69		// create the key
 70		if (!StructKeyExists(variables.wheels.class.mapping, arguments.name))
 71			variables.wheels.class.mapping[arguments.name] = {};
 72
 73		if (Len(arguments.column))
 74		{
 75			variables.wheels.class.mapping[arguments.name].type = "column";
 76			variables.wheels.class.mapping[arguments.name].value = arguments.column;
 77		}
 78
 79		if (Len(arguments.sql))
 80		{
 81			variables.wheels.class.mapping[arguments.name].type = "sql";
 82			variables.wheels.class.mapping[arguments.name].value = arguments.sql;
 83		}
 84
 85		if (Len(arguments.label))
 86			variables.wheels.class.mapping[arguments.name].label = arguments.label;
 87
 88		if (StructKeyExists(arguments, "defaultValue"))
 89			variables.wheels.class.mapping[arguments.name].defaultValue = arguments.defaultValue;
 90	</cfscript>
 91</cffunction>
 92
 93<!--- PUBLIC MODEL CLASS METHODS --->
 94
 95<cffunction name="propertyNames" returntype="string" access="public" output="false" hint="Returns a list of property names ordered by their respective column's ordinal position in the database table. Also includes calculated property names that will be generated by the Wheels ORM."
 96	examples=
 97	'
 98		<!--- Get a list of the property names in use in the user model --->
 99  		<cfset propNames = model("user").propertyNames()>
100	'
101	categories="model-class,miscellaneous" chapters="object-relational-mapping" functions="columnNames,dataSource,property,table,tableName">
102	<cfscript>
103		var loc = {};
104		loc.returnValue = variables.wheels.class.propertyList;
105		if (ListLen(variables.wheels.class.calculatedPropertyList))
106			loc.returnValue = ListAppend(loc.returnValue, variables.wheels.class.calculatedPropertyList);
107		</cfscript>
108	<cfreturn loc.returnValue>
109</cffunction>
110
111<cffunction name="columns" returntype="array" access="public" output="false" hint="Returns an array of columns names for the table associated with this class. Does not include calculated properties that will be generated by the Wheels ORM."
112	examples=
113	'
114		<!--- Get the columns names in the order they are in the database --->
115		<cfset employee = model("employee").columns()>
116	'
117	categories="model-class,miscellaneous" chapters="object-relational-mapping" functions="">
118	<cfreturn ListToArray(variables.wheels.class.columnList) />
119</cffunction>
120
121<cffunction name="columnForProperty" returntype="any" access="public" output="false" hint="Returns the column name mapped for the named model property."
122	examples=
123	'
124		<!--- Get an object, set a value and then see if the property exists --->
125		<cfset employee = model("employee").new()>
126		<cfset employee.columnForProperty("firstName")><!--- returns column name, in this case "firstname" if the convention is used --->
127	'
128	categories="model-class,miscellaneous" chapters="object-relational-mapping" functions="">
129	<cfargument name="property" type="string" required="true" hint="See documentation for @hasProperty." />
130	<cfscript>
131		var columnName = false;
132		if (StructKeyExists(variables.wheels.class.properties, arguments.property))
133			columnName = variables.wheels.class.properties[arguments.property].column;
134	</cfscript>
135	<cfreturn columnName />
136</cffunction>
137
138<cffunction name="columnDataForProperty" returntype="any" access="public" output="false" hint="Returns a struct with data for the named property."
139	examples=
140	'
141		<!--- Get an object, set a value and then see if the property exists --->
142		<cfset employee = model("employee").new()>
143		<cfset employee.columnDataForProperty("firstName")><!--- returns column struct --->
144	'
145	categories="model-class,miscellaneous" chapters="object-relational-mapping" functions="">
146	<cfargument name="property" type="string" required="true" hint="Name of column to retrieve data for." />
147	<cfscript>
148		var columnData = false;
149		if (StructKeyExists(variables.wheels.class.properties, arguments.property))
150			columnData = variables.wheels.class.properties[arguments.property];
151	</cfscript>
152	<cfreturn columnData />
153</cffunction>
154
155<!--- PUBLIC MODEL OBJECT METHODS --->
156
157<cffunction name="key" returntype="string" access="public" output="false" hint="Returns the value of the primary key for the object. If you have a single primary key named `id`, then `someObject.key()` is functionally equivalent to `someObject.id`. This method is more useful when you do dynamic programming and don't know the name of the primary key or when you use composite keys (in which case it's convenient to use this method to get a list of both key values returned)."
158	examples=
159	'
160		<!--- Get an object and then get the primary key value(s) --->
161		<cfset employee = model("employee").findByKey(params.key)>
162		<cfset val = employee.key()>
163	'
164	categories="model-object,miscellaneous" chapters="" functions="">
165	<cfargument name="$persisted" type="boolean" required="false" default="false">
166	<cfargument name="$returnTickCountWhenNew" type="boolean" required="false" default="false">
167	<cfscript>
168		var loc = {};
169		loc.returnValue = "";
170		loc.iEnd = ListLen(primaryKeys());
171		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
172		{
173			loc.property = primaryKeys(loc.i);
174			if (StructKeyExists(this, loc.property))
175			{
176				if (arguments.$persisted && hasChanged(loc.property))
177					loc.returnValue = ListAppend(loc.returnValue, changedFrom(loc.property));
178				else
179					loc.returnValue = ListAppend(loc.returnValue, this[loc.property]);
180			}
181		}
182		if (!Len(loc.returnValue) && arguments.$returnTickCountWhenNew)
183			loc.returnValue = variables.wheels.instance.tickCountId;
184		</cfscript>
185	<cfreturn loc.returnValue>
186</cffunction>
187
188<cffunction name="hasProperty" returntype="boolean" access="public" output="false" hint="Returns `true` if the specified property name exists on the model."
189	examples=
190	'
191		<!--- Get an object, set a value and then see if the property exists --->
192		<cfset employee = model("employee").new()>
193		<cfset employee.firstName = "dude">
194		<cfset employee.hasProperty("firstName")><!--- returns true --->
195
196		<!--- This is also a dynamic method that you could do --->
197		<cfset employee.hasFirstName()>
198	'
199	categories="model-object,miscellaneous" chapters="" functions="">
200	<cfargument name="property" type="string" required="true" hint="Name of property to inspect." />
201	<cfscript>
202		var hasProperty = false;
203		if (StructKeyExists(this, arguments.property) && !IsCustomFunction(this[arguments.property]))
204			hasProperty = true;
205	</cfscript>
206	<cfreturn hasProperty />
207</cffunction>
208
209<cffunction name="propertyIsPresent" returntype="boolean" access="public" output="false" hint="Returns `true` if the specified property exists on the model and is not a blank string."
210	examples=
211	'
212		<!--- Get an object, set a value and then see if the property exists --->
213		<cfset employee = model("employee").new()>
214		<cfset employee.firstName = "dude">
215		<cfreturn employee.propertyIsPresent("firstName")><!--- Returns true --->
216		
217		<cfset employee.firstName = "">
218		<cfreturn employee.propertyIsPresent("firstName")><!--- Returns false --->
219	'
220	categories="model-object,miscellaneous" chapters="" functions="">
221	<cfargument name="property" type="string" required="true" hint="See documentation for @hasProperty." />
222	<cfscript>
223		var isPresent = false;
224		if (StructKeyExists(this, arguments.property) && !IsCustomFunction(this[arguments.property]) && IsSimpleValue(this[arguments.property]) && Len(this[arguments.property]))
225			isPresent = true;
226	</cfscript>
227	<cfreturn isPresent />
228</cffunction>
229
230<cffunction name="toggle" returntype="any" access="public" output="false" hint="Assigns to the property specified the opposite of the property's current boolean value. Throws an error if the property cannot be converted to a boolean value. Returns this object if save called internally is `false`."
231	examples=
232	'
233		<!--- Get an object, and toggle a boolean property --->
234		<cfset user = model("user").findByKey(58)>
235		<cfset isSuccess = user.toggle("isActive")><!--- returns whether the object was saved properly --->
236		<!--- You can also use a dynamic helper for this --->
237		<cfset isSuccess = user.toggleIsActive()>
238	'
239	categories="model-object,crud" chapters="updating-records" functions="">
240	<cfargument name="property" type="string" required="true" />
241	<cfargument name="save" type="boolean" required="false" hint="Argument to decide whether save the property after it has been toggled. Defaults to true." />
242	<cfscript>
243		$args(name="toggle", args=arguments);
244		if (!StructKeyExists(this, arguments.property))
245			$throw(type="Wheels.PropertyDoesNotExist", message="Property Does Not Exist", extendedInfo="You may only toggle a property that exists on this model.");
246		if (!IsBoolean(this[arguments.property]))
247			$throw(type="Wheels.PropertyIsIncorrectType", message="Incorrect Arguments", extendedInfo="You may only toggle a property that evaluates to the boolean value.");
248		this[arguments.property] = !this[arguments.property];
249		if (arguments.save)
250			return updateProperty(property=arguments.property, value=this[arguments.property]);
251	</cfscript>
252	<cfreturn this />
253</cffunction>
254
255<cffunction name="properties" returntype="struct" access="public" output="false" hint="Returns a structure of all the properties with their names as keys and the values of the property as values."
256	examples=
257	'
258		<!--- Get a structure of all the properties for an object --->
259		<cfset user = model("user").findByKey(1)>
260		<cfset props = user.properties()>
261	'
262	categories="model-object,miscellaneous" chapters="" functions="setProperties">
263	<cfscript>
264		var loc = {};
265		loc.returnValue = {};
266
267		// loop through all properties and functions in the this scope
268		for (loc.key in this)
269		{
270			// we return anything that is not a function
271			if (!IsCustomFunction(this[loc.key]))
272			{
273				// try to get the property name from the list set on the object, this is just to avoid returning everything in ugly upper case which Adobe ColdFusion does by default
274				if (ListFindNoCase(propertyNames(), loc.key))
275					loc.key = ListGetAt(propertyNames(), ListFindNoCase(propertyNames(), loc.key));
276
277				// set property from the this scope in the struct that we will return
278				loc.returnValue[loc.key] = this[loc.key];
279			}
280		}
281	</cfscript>
282	<cfreturn loc.returnValue>
283</cffunction>
284
285<cffunction name="setProperties" returntype="void" access="public" output="false" hint="Allows you to set all the properties of an object at once by passing in a structure with keys matching the property names."
286	examples=
287	'
288		<!--- Update the properties of the object with the params struct containing the values of a form post --->
289		<cfset user = model("user").findByKey(1)>
290		<cfset user.setProperties(params.user)>
291	'
292	categories="model-object,miscellaneous" chapters="" functions="properties">
293	<cfargument name="properties" type="struct" required="false" default="#StructNew()#" hint="See documentation for @new.">
294	<cfset $setProperties(argumentCollection=arguments) />
295</cffunction>
296
297<!--- changes --->
298
299<cffunction name="hasChanged" returntype="boolean" access="public" output="false" hint="Returns `true` if the specified property (or any if none was passed in) has been changed but not yet saved to the database. Will also return `true` if the object is new and no record for it exists in the database."
300	examples=
301	'
302		<!--- Get a member object and change the `email` property on it --->
303		<cfset member = model("member").findByKey(params.memberId)>
304		<cfset member.email = params.newEmail>
305
306		<!--- Check if the `email` property has changed --->
307		<cfif member.hasChanged("email")>
308			<!--- Do something... --->
309		</cfif>
310
311		<!--- The above can also be done using a dynamic function like this --->
312		<cfif member.emailHasChanged()>
313			<!--- Do something... --->
314		</cfif>
315	'
316	categories="model-object,changes" chapters="dirty-records" functions="allChanges,changedFrom,changedProperties">
317	<cfargument name="property" type="string" required="false" default="" hint="Name of property to check for change.">
318	<cfscript>
319		var loc = {};
320
321		// always return true if $persistedProperties does not exists
322		if (!StructKeyExists(variables, "$persistedProperties"))
323			return true;
324
325		if (!Len(arguments.property))
326		{
327			// they haven't specified a particular property so loop through
328			// them all
329			arguments.property = StructKeyList(variables.wheels.class.properties);
330		}
331
332		arguments.property = ListToArray(arguments.property);
333
334		loc.iEnd = ArrayLen(arguments.property);
335		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
336		{
337			loc.key = arguments.property[loc.i];
338			if (StructKeyExists(this, loc.key))
339			{
340				if (!StructKeyExists(variables.$persistedProperties, loc.key))
341				{
342					return true;
343				}
344				else
345				{
346					// hehehehe... convert each datatype to a string
347					// for easier comparision
348					loc.a = $convertToString(this[loc.key]);
349					loc.b = $convertToString(variables.$persistedProperties[loc.key]);
350					if(Compare(loc.a, loc.b) neq 0)
351						return true;
352				}
353			}
354		}
355		// if we get here, it means that all of the properties that were checked had a value in
356		// $persistedProperties and it matched or some of the properties did not exist in the this scope
357	</cfscript>
358	<cfreturn false>
359</cffunction>
360
361<cffunction name="changedProperties" returntype="string" access="public" output="false" hint="Returns a list of the object properties that have been changed but not yet saved to the database."
362	examples=
363	'
364		<!--- Get an object, change it, and then ask for its changes (will return a list of the property names that have changed, not the values themselves) --->
365		<cfset member = model("member").findByKey(params.memberId)>
366		<cfset member.firstName = params.newFirstName>
367		<cfset member.email = params.newEmail>
368		<cfset changedProperties = member.changedProperties()>
369	'
370	categories="model-object,changes" chapters="dirty-records" functions="allChanges,changedFrom,hasChanged">
371	<cfscript>
372		var loc = {};
373		loc.returnValue = "";
374		for (loc.key in variables.wheels.class.properties)
375			if (hasChanged(loc.key))
376				loc.returnValue = ListAppend(loc.returnValue, loc.key);
377	</cfscript>
378	<cfreturn loc.returnValue>
379</cffunction>
380
381<cffunction name="changedFrom" returntype="string" access="public" output="false" hint="Returns the previous value of a property that has changed. Returns an empty string if no previous value exists. Wheels will keep a note of the previous property value until the object is saved to the database."
382	examples=
383	'
384		<!--- Get a member object and change the `email` property on it --->
385		<cfset member = model("member").findByKey(params.memberId)>
386		<cfset member.email = params.newEmail>
387
388		<!--- Get the previous value (what the `email` property was before it was changed)--->
389		<cfset oldValue = member.changedFrom("email")>
390
391		<!--- The above can also be done using a dynamic function like this --->
392		<cfset oldValue = member.emailChangedFrom()>
393	'
394	categories="model-object,changes" chapters="dirty-records" functions="allChanges,changedProperties,hasChanged">
395	<cfargument name="property" type="string" required="true" hint="Name of property to get the previous value for.">
396	<cfscript>
397		var returnValue = "";
398		if (StructKeyExists(variables, "$persistedProperties") && StructKeyExists(variables.$persistedProperties, arguments.property))
399			returnValue = variables.$persistedProperties[arguments.property];
400	</cfscript>
401	<cfreturn returnValue>
402</cffunction>
403
404<cffunction name="allChanges" returntype="struct" access="public" output="false" hint="Returns a struct detailing all changes that have been made on the object but not yet saved to the database."
405	examples=
406	'
407		<!--- Get an object, change it, and then ask for its changes (will return a struct containing the changes, both property names and their values) --->
408		<cfset member = model("member").findByKey(params.memberId)>
409		<cfset member.firstName = params.newFirstName>
410		<cfset member.email = params.newEmail>
411		<cfset allChanges = member.allChanges()>
412	'
413	categories="model-object,changes" chapters="dirty-records" functions="changedFrom,changedProperties,hasChanged">
414	<cfscript>
415		var loc = {};
416		loc.returnValue = {};
417		if (hasChanged())
418		{
419			loc.changedProperties = changedProperties();
420			loc.iEnd = ListLen(loc.changedProperties);
421			for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
422			{
423				loc.item = ListGetAt(loc.changedProperties, loc.i);
424				loc.returnValue[loc.item] = {};
425				loc.returnValue[loc.item].changedFrom = changedFrom(loc.item);
426				if (StructKeyExists(this, loc.item))
427					loc.returnValue[loc.item].changedTo = this[loc.item];
428				else
429					loc.returnValue[loc.item].changedTo = "";
430			}
431		}
432	</cfscript>
433	<cfreturn loc.returnValue>
434</cffunction>
435
436<!--- PRIVATE MODEL OBJECT METHODS --->
437
438<cffunction name="$setProperties" returntype="any" access="public" output="false" hint="I am the behind the scenes method to turn arguments into the properties argument.">
439	<cfargument name="properties" type="struct" required="true" />
440	<cfargument name="filterList" type="string" required="false" default="" />
441	<cfargument name="setOnModel" type="boolean" required="false" default="true" />
442	<cfargument name="$useFilterLists" type="boolean" required="false" default="true" />
443	<cfscript>
444		var loc = {};
445
446		loc.allowedProperties = {};
447
448		arguments.filterList = ListAppend(arguments.filterList, "properties,filterList,setOnModel,$useFilterLists");
449
450		// add eventual named arguments to properties struct (named arguments will take precedence)
451		for (loc.key in arguments)
452			if (!ListFindNoCase(arguments.filterList, loc.key))
453				arguments.properties[loc.key] = arguments[loc.key];
454
455		for (loc.key in arguments.properties) // loop throug the properties and see if they can be set based off of the accessible properties lists
456		{
457			loc.accessible = true;
458			if (arguments.$useFilterLists && StructKeyExists(variables.wheels.class.accessibleProperties, "whiteList") && !ListFindNoCase(variables.wheels.class.accessibleProperties.whiteList, loc.key))
459				loc.accessible = false;
460			if (arguments.$useFilterLists && StructKeyExists(variables.wheels.class.accessibleProperties, "blackList") && ListFindNoCase(variables.wheels.class.accessibleProperties.blackList, loc.key))
461				loc.accessible = false;
462			if (loc.accessible)
463				loc.allowedProperties[loc.key] = arguments.properties[loc.key];
464			if (loc.accessible && arguments.setOnModel)
465				$setProperty(property=loc.key, value=loc.allowedProperties[loc.key]);
466		}
467
468		if (arguments.setOnModel)
469			return;
470	</cfscript>
471	<cfreturn loc.allowedProperties />
472</cffunction>
473
474<cffunction name="$setProperty" returntype="void" access="public" output="false">
475	<cfargument name="property" type="string" required="true" />
476	<cfargument name="value" type="any" required="true" />
477	<cfargument name="associations" type="struct" required="false" default="#variables.wheels.class.associations#" />
478	<cfscript>
479		if (IsObject(arguments.value))
480			this[arguments.property] = arguments.value;
481		else if (IsStruct(arguments.value) && StructKeyExists(arguments.associations, arguments.property) && arguments.associations[arguments.property].nested.allow && ListFindNoCase("belongsTo,hasOne", arguments.associations[arguments.property].type))
482			$setOneToOneAssociationProperty(property=arguments.property, value=arguments.value, association=arguments.associations[arguments.property]);
483		else if (IsStruct(arguments.value) && StructKeyExists(arguments.associations, arguments.property) && arguments.associations[arguments.property].nested.allow && arguments.associations[arguments.property].type == "hasMany")
484			$setCollectionAssociationProperty(property=arguments.property, value=arguments.value, association=arguments.associations[arguments.property]);
485		else if (IsArray(arguments.value) && ArrayLen(arguments.value) && !IsObject(arguments.value[1]) && StructKeyExists(arguments.associations, arguments.property) && arguments.associations[arguments.property].nested.allow && arguments.associations[arguments.property].type == "hasMany")
486			$setCollectionAssociationProperty(property=arguments.property, value=arguments.value, association=arguments.associations[arguments.property]);
487		else
488			this[arguments.property] = arguments.value;
489	</cfscript>
490	<cfreturn />
491</cffunction>
492
493<cffunction name="$updatePersistedProperties" returntype="void" access="public" output="false">
494	<cfscript>
495		var loc = {};
496		variables.$persistedProperties = {};
497		for (loc.key in variables.wheels.class.properties)
498			if (StructKeyExists(this, loc.key))
499				variables.$persistedProperties[loc.key] = this[loc.key];
500	</cfscript>
501</cffunction>
502
503<cffunction name="$setDefaultValues" returntype="any" access="public" output="false">
504	<cfscript>
505	var loc = {};
506	for (loc.key in variables.wheels.class.properties)
507	{
508		if (StructKeyExists(variables.wheels.class.properties[loc.key], "defaultValue") && (!StructKeyExists(this, loc.key) || !Len(this[loc.key])))
509		{
510			// set the default value unless it is blank or a value already exists for that property on the object
511			this[loc.key] = variables.wheels.class.properties[loc.key].defaultValue;
512		}
513	}
514	</cfscript>
515</cffunction>
516
517<cffunction name="$propertyInfo" returntype="struct" access="public" output="false">
518	<cfargument name="property" type="string" required="true">
519	<cfscript>
520		var returnValue = {};
521		if (StructKeyExists(variables.wheels.class.properties, arguments.property))
522			returnValue = variables.wheels.class.properties[arguments.property];
523	</cfscript>
524	<cfreturn returnValue />
525</cffunction>
526
527<cffunction name="$label" returntype="string" access="public" output="false">
528	<cfargument name="property" type="string" required="true">
529	<cfargument name="properties" type="struct" required="false" default="#variables.wheels.class.properties#">
530	<cfargument name="mapping" type="struct" required="false" default="#variables.wheels.class.mapping#">
531	<cfscript>
532		if (StructKeyExists(arguments.properties, arguments.property) && StructKeyExists(arguments.properties[arguments.property], "label"))
533			return arguments.properties[arguments.property].label;
534		else if (StructKeyExists(arguments.mapping, arguments.property) && StructKeyExists(arguments.mapping[arguments.property], "label"))
535			return arguments.mapping[arguments.property].label;
536		else
537			return Humanize(arguments.property);
538	</cfscript>
539</cffunction>