PageRenderTime 282ms CodeModel.GetById 121ms app.highlight 4ms RepoModel.GetById 116ms app.codeStats 0ms

/wheels/model/initialization.cfm

http://cfwheels.googlecode.com/
ColdFusion | 230 lines | 207 code | 23 blank | 0 comment | 42 complexity | 4381885185c5c59dc0a1ffe8515852ba MD5 | raw file
  1<cffunction name="$initModelClass" returntype="any" access="public" output="false">
  2	<cfargument name="name" type="string" required="true">
  3	<cfargument name="path" type="string" required="true">
  4	<cfscript>
  5		var loc = {};
  6		variables.wheels = {};
  7		variables.wheels.class = {};
  8		variables.wheels.class.alias = arguments.name;
  9		variables.wheels.class.modelName = arguments.name;
 10		variables.wheels.class.path = arguments.path;
 11
 12		// if our name has pathing in it, remove it and add it to the end of of the $class.path variable
 13		if (Find("/", arguments.name))
 14		{
 15			variables.wheels.class.modelName = ListLast(arguments.name, "/");
 16			variables.wheels.class.path = ListAppend(arguments.path, ListDeleteAt(arguments.name, ListLen(arguments.name, "/"), "/"), "/");
 17		}
 18
 19		variables.wheels.class.RESQLAs = "[[:space:]]AS[[:space:]][A-Za-z1-9]+";
 20		variables.wheels.class.RESQLOperators = "((?: (?:NOT )?LIKE)|(?: (?:NOT )?IN)|(?: IS(?: NOT)?)|(?:<>)|(?:<=)|(?:>=)|(?:!=)|(?:!<)|(?:!>)|=|<|>)";
 21		variables.wheels.class.RESQLWhere = "(#variables.wheels.class.RESQLOperators# ?)(\('.+?'\)|\((-?[0-9\.],?)+\)|'.+?'()|''|(-?[0-9\.]+)()|NULL)(($|\)| (AND|OR)))";
 22
 23		variables.wheels.class.aliases = {};
 24		variables.wheels.class.mapping = {};
 25		variables.wheels.class.properties = {};
 26		variables.wheels.class.accessibleProperties = {};
 27		variables.wheels.class.calculatedProperties = {};
 28		variables.wheels.class.associations = {};
 29		variables.wheels.class.callbacks = {};
 30		variables.wheels.class.keys = "";
 31		variables.wheels.class.connection = {datasource=application.wheels.dataSourceName, username=application.wheels.dataSourceUserName, password=application.wheels.dataSourcePassword};
 32		variables.wheels.class.automaticValidations = application.wheels.automaticValidations;
 33
 34		setTableNamePrefix(get("tableNamePrefix"));
 35		table(LCase(pluralize(variables.wheels.class.modelName)));
 36
 37		loc.callbacks = "afterNew,afterFind,afterInitialization,beforeDelete,afterDelete,beforeSave,afterSave,beforeCreate,afterCreate,beforeUpdate,afterUpdate,beforeValidation,afterValidation,beforeValidationOnCreate,afterValidationOnCreate,beforeValidationOnUpdate,afterValidationOnUpdate";
 38		loc.iEnd = ListLen(loc.callbacks);
 39		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
 40			variables.wheels.class.callbacks[ListGetAt(loc.callbacks, loc.i)] = ArrayNew(1);
 41		loc.validations = "onSave,onCreate,onUpdate";
 42		loc.iEnd = ListLen(loc.validations);
 43		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
 44			variables.wheels.class.validations[ListGetAt(loc.validations, loc.i)] = ArrayNew(1);
 45
 46		// run developer's init method if it exists
 47		if (StructKeyExists(variables, "init"))
 48			init();
 49
 50		// make sure that the tablename has the respected prefix
 51		table(getTableNamePrefix() & tableName());
 52
 53		// load the database adapter
 54		variables.wheels.class.adapter = $createObjectFromRoot(path="#application.wheels.wheelsComponentPath#", fileName="Connection", method="init", datasource="#variables.wheels.class.connection.datasource#", username="#variables.wheels.class.connection.username#", password="#variables.wheels.class.connection.password#");
 55
 56		// get columns for the table
 57		loc.columns = variables.wheels.class.adapter.$getColumns(tableName());
 58
 59		variables.wheels.class.propertyList = "";
 60		variables.wheels.class.columnList = "";
 61		loc.processedColumns = "";
 62		loc.iEnd = loc.columns.recordCount;
 63		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
 64		{
 65			// set up properties and column mapping
 66			if (!ListFind(loc.processedColumns, loc.columns["column_name"][loc.i]))
 67			{
 68				loc.property = loc.columns["column_name"][loc.i]; // default the column to map to a property with the same name
 69				for (loc.key in variables.wheels.class.mapping)
 70				{
 71					if (StructKeyExists(variables.wheels.class.mapping[loc.key], "type") and variables.wheels.class.mapping[loc.key].type == "column" && variables.wheels.class.mapping[loc.key].value == loc.property)
 72					{
 73						// developer has chosen to map this column to a property with a different name so set that here
 74						loc.property = loc.key;
 75						break;
 76					}
 77				}
 78				loc.type = SpanExcluding(loc.columns["type_name"][loc.i], "( ");
 79
 80				// set the info we need for each property
 81				variables.wheels.class.properties[loc.property] = {};
 82				variables.wheels.class.properties[loc.property].dataType = loc.type;
 83				variables.wheels.class.properties[loc.property].type = variables.wheels.class.adapter.$getType(loc.type, loc.columns["decimal_digits"][loc.i]);
 84				variables.wheels.class.properties[loc.property].column = loc.columns["column_name"][loc.i];
 85				variables.wheels.class.properties[loc.property].scale = loc.columns["decimal_digits"][loc.i];
 86
 87				// get a boolean value for whether this column can be set to null or not
 88				// if we don't get a boolean back we try to translate y/n to proper boolean values in cfml (yes/no)
 89				variables.wheels.class.properties[loc.property].nullable = Trim(loc.columns["is_nullable"][loc.i]);
 90				if (!IsBoolean(variables.wheels.class.properties[loc.property].nullable))
 91					variables.wheels.class.properties[loc.property].nullable = ReplaceList(variables.wheels.class.properties[loc.property].nullable, "N,Y", "No,Yes");
 92
 93				variables.wheels.class.properties[loc.property].size = loc.columns["column_size"][loc.i];
 94				variables.wheels.class.properties[loc.property].label = Humanize(loc.property);
 95				variables.wheels.class.properties[loc.property].validationtype = variables.wheels.class.adapter.$getValidationType(variables.wheels.class.properties[loc.property].type);
 96
 97				if (StructKeyExists(variables.wheels.class.mapping, loc.property)) {
 98					if (StructKeyExists(variables.wheels.class.mapping[loc.property], "label"))
 99						variables.wheels.class.properties[loc.property].label = variables.wheels.class.mapping[loc.property].label;
100					if (StructKeyExists(variables.wheels.class.mapping[loc.property], "defaultValue"))
101						variables.wheels.class.properties[loc.property].defaultValue = variables.wheels.class.mapping[loc.property].defaultValue;
102				}
103
104				if (loc.columns["is_primarykey"][loc.i])
105				{
106					setPrimaryKey(loc.property);
107				}
108				else if (variables.wheels.class.automaticValidations and not ListFindNoCase("#application.wheels.timeStampOnCreateProperty#,#application.wheels.timeStampOnUpdateProperty#,#application.wheels.softDeleteProperty#", loc.property))
109				{
110					// set nullable validations if the developer has not
111					loc.defaultValidationsAllowBlank = variables.wheels.class.properties[loc.property].nullable;
112					if (!variables.wheels.class.properties[loc.property].nullable and !Len(loc.columns["column_default_value"][loc.i]) and !$validationExists(property=loc.property, validation="validatesPresenceOf"))
113					{
114						validatesPresenceOf(properties=loc.property);
115					}
116					// always allowblank if a database default or validatesPresenceOf() has been set
117					if (Len(loc.columns["column_default_value"][loc.i]) or $validationExists(property=loc.property, validation="validatesPresenceOf"))
118						loc.defaultValidationsAllowBlank = true;
119					// set length validations if the developer has not
120					if (variables.wheels.class.properties[loc.property].validationtype eq "string" and !$validationExists(property=loc.property, validation="validatesLengthOf"))
121						validatesLengthOf(properties=loc.property, allowBlank=loc.defaultValidationsAllowBlank, maximum=variables.wheels.class.properties[loc.property].size);
122					// set numericality validations if the developer has not
123					if (ListFindNoCase("integer,float", variables.wheels.class.properties[loc.property].validationtype) and !$validationExists(property=loc.property, validation="validatesNumericalityOf"))
124						validatesNumericalityOf(properties=loc.property, allowBlank=loc.defaultValidationsAllowBlank, onlyInteger=(variables.wheels.class.properties[loc.property].validationtype eq "integer"));
125					// set date validations if the developer has not (checks both dates or times as per the IsDate() function)
126					if (variables.wheels.class.properties[loc.property].validationtype eq "datetime" and !$validationExists(property=loc.property, validation="validatesFormatOf"))
127						validatesFormatOf(properties=loc.property, allowBlank=loc.defaultValidationsAllowBlank, type="date");
128				}
129
130				variables.wheels.class.propertyList = ListAppend(variables.wheels.class.propertyList, loc.property);
131				variables.wheels.class.columnList = ListAppend(variables.wheels.class.columnList, variables.wheels.class.properties[loc.property].column);
132				loc.processedColumns = ListAppend(loc.processedColumns, loc.columns["column_name"][loc.i]);
133			}
134		}
135
136		// raise error when no primary key has been defined for the table
137		if (!Len(primaryKeys()))
138		{
139			$throw(type="Wheels.NoPrimaryKey", message="No primary key exists on the `#tableName()#` table.", extendedInfo="Set an appropriate primary key on the `#tableName()#` table.");
140		}
141
142		// add calculated properties
143		variables.wheels.class.calculatedPropertyList = "";
144		for (loc.key in variables.wheels.class.mapping)
145		{
146			if (StructKeyExists(variables.wheels.class.mapping[loc.key], "type") and variables.wheels.class.mapping[loc.key].type != "column")
147			{
148				variables.wheels.class.calculatedPropertyList = ListAppend(variables.wheels.class.calculatedPropertyList, loc.key);
149				variables.wheels.class.calculatedProperties[loc.key] = {};
150				variables.wheels.class.calculatedProperties[loc.key][variables.wheels.class.mapping[loc.key].type] = variables.wheels.class.mapping[loc.key].value;
151			}
152		}
153
154		// set up soft deletion and time stamping if the necessary columns in the table exist
155		if (Len(application.wheels.softDeleteProperty) && StructKeyExists(variables.wheels.class.properties, application.wheels.softDeleteProperty))
156		{
157			variables.wheels.class.softDeletion = true;
158			variables.wheels.class.softDeleteColumn = variables.wheels.class.properties[application.wheels.softDeleteProperty].column;
159		}
160		else
161		{
162			variables.wheels.class.softDeletion = false;
163		}
164
165		if (Len(application.wheels.timeStampOnCreateProperty) && StructKeyExists(variables.wheels.class.properties, application.wheels.timeStampOnCreateProperty))
166		{
167			variables.wheels.class.timeStampingOnCreate = true;
168			variables.wheels.class.timeStampOnCreateProperty = application.wheels.timeStampOnCreateProperty;
169		}
170		else
171		{
172			variables.wheels.class.timeStampingOnCreate = false;
173		}
174
175		if (Len(application.wheels.timeStampOnUpdateProperty) && StructKeyExists(variables.wheels.class.properties, application.wheels.timeStampOnUpdateProperty))
176		{
177			variables.wheels.class.timeStampingOnUpdate = true;
178			variables.wheels.class.timeStampOnUpdateProperty = application.wheels.timeStampOnUpdateProperty;
179		}
180		else
181		{
182			variables.wheels.class.timeStampingOnUpdate = false;
183		}
184	</cfscript>
185	<cfreturn this>
186</cffunction>
187
188<cffunction name="$initModelObject" returntype="any" access="public" output="false">
189	<cfargument name="name" type="string" required="true">
190	<cfargument name="properties" type="any" required="true">
191	<cfargument name="persisted" type="boolean" required="true">
192	<cfargument name="row" type="numeric" required="false" default="1">
193	<cfargument name="base" type="boolean" required="false" default="true">
194	<cfargument name="useFilterLists" type="boolean" required="false" default="true">
195	<cfscript>
196		var loc = {};
197
198		variables.wheels = {};
199		variables.wheels.instance = {};
200		variables.wheels.instance.errors = [];
201		// keep a unique identifier for each model created in case we need it for nested properties
202		variables.wheels.instance.tickCountId = GetTickCount().toString(); // make sure we have it in milliseconds
203
204		// copy class variables from the object in the application scope
205		if (!StructKeyExists(variables.wheels, "class"))
206			variables.wheels.class = $namedReadLock(name="classLock", object=application.wheels.models[arguments.name], method="$classData");
207		// setup object properties in the this scope
208		if (IsQuery(arguments.properties) && arguments.properties.recordCount != 0)
209			arguments.properties = $queryRowToStruct(argumentCollection=arguments);
210
211		if (IsStruct(arguments.properties) && !StructIsEmpty(arguments.properties))
212			$setProperties(properties=arguments.properties, setOnModel=true, $useFilterLists=arguments.useFilterLists);
213
214		if (arguments.persisted)
215			$updatePersistedProperties();
216	</cfscript>
217	<cfreturn this>
218</cffunction>
219
220<cffunction name="$classData" returntype="struct" access="public" output="false">
221	<cfreturn variables.wheels.class>
222</cffunction>
223
224<cffunction name="$softDeletion" returntype="boolean" access="public" output="false">
225	<cfreturn variables.wheels.class.softDeletion>
226</cffunction>
227
228<cffunction name="$softDeleteColumn" returntype="string" access="public" output="false">
229	<cfreturn variables.wheels.class.softDeleteColumn>
230</cffunction>