PageRenderTime 38ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/wheels/model/onmissingmethod.cfm

http://cfwheels.googlecode.com/
ColdFusion | 397 lines | 394 code | 3 blank | 0 comment | 56 complexity | c35fbe6917136c9c674b9f5e09c76edf MD5 | raw file
Possible License(s): Apache-2.0, CPL-1.0
  1. <cffunction name="onMissingMethod" returntype="any" access="public" output="false" hint="This method handles dynamic finders, properties, and association methods. It is not part of the public API.">
  2. <cfargument name="missingMethodName" type="string" required="true" hint="Name of method attempted to load.">
  3. <cfargument name="missingMethodArguments" type="struct" required="true" hint="Name/value pairs of arguments that were passed to the attempted method call.">
  4. <cfscript>
  5. var loc = {};
  6. if (Right(arguments.missingMethodName, 10) == "hasChanged" && StructKeyExists(variables.wheels.class.properties,ReplaceNoCase(arguments.missingMethodName, "hasChanged", "")))
  7. loc.returnValue = hasChanged(property=ReplaceNoCase(arguments.missingMethodName, "hasChanged", ""));
  8. else if (Right(arguments.missingMethodName, 11) == "changedFrom" && StructKeyExists(variables.wheels.class.properties, ReplaceNoCase(arguments.missingMethodName, "changedFrom", "")))
  9. loc.returnValue = changedFrom(property=ReplaceNoCase(arguments.missingMethodName, "changedFrom", ""));
  10. else if (Right(arguments.missingMethodName, 9) == "IsPresent" && StructKeyExists(variables.wheels.class.properties, ReplaceNoCase(arguments.missingMethodName, "IsPresent", "")))
  11. loc.returnValue = propertyIsPresent(property=ReplaceNoCase(arguments.missingMethodName, "IsPresent", ""));
  12. else if (Left(arguments.missingMethodName, 9) == "columnFor" && StructKeyExists(variables.wheels.class.properties, ReplaceNoCase(arguments.missingMethodName, "columnFor", "")))
  13. loc.returnValue = columnForProperty(property=ReplaceNoCase(arguments.missingMethodName, "columnFor", ""));
  14. else if (Left(arguments.missingMethodName, 6) == "toggle" && StructKeyExists(variables.wheels.class.properties, ReplaceNoCase(arguments.missingMethodName, "toggle", "")))
  15. loc.returnValue = toggle(property=ReplaceNoCase(arguments.missingMethodName, "toggle", ""), argumentCollection=arguments.missingMethodArguments);
  16. else if (Left(arguments.missingMethodName, 3) == "has" && StructKeyExists(variables.wheels.class.properties, ReplaceNoCase(arguments.missingMethodName, "has", "")))
  17. loc.returnValue = hasProperty(property=ReplaceNoCase(arguments.missingMethodName, "has", ""));
  18. else if (Left(arguments.missingMethodName, 6) == "update" && StructKeyExists(variables.wheels.class.properties, ReplaceNoCase(arguments.missingMethodName, "update", "")))
  19. {
  20. if (!StructKeyExists(arguments.missingMethodArguments, "value"))
  21. $throw(type="Wheels.IncorrectArguments", message="The `value` argument is required but was not passed in.", extendedInfo="Pass in a value to the dynamic updateProperty in the `value` argument.");
  22. loc.returnValue = updateProperty(property=ReplaceNoCase(arguments.missingMethodName, "update", ""), value=arguments.missingMethodArguments.value);
  23. }
  24. else if (Left(arguments.missingMethodName, 9) == "findOneBy" || Left(arguments.missingMethodName, 9) == "findAllBy")
  25. {
  26. if (StructKeyExists(server, "railo"))
  27. loc.finderProperties = ListToArray(LCase(ReplaceNoCase(ReplaceNoCase(ReplaceNoCase(arguments.missingMethodName, "And", "|"), "findAllBy", ""), "findOneBy", "")), "|"); // since Railo passes in the method name in all upper case we have to do this here
  28. else
  29. loc.finderProperties = ListToArray(ReplaceNoCase(ReplaceNoCase(Replace(arguments.missingMethodName, "And", "|"), "findAllBy", ""), "findOneBy", ""), "|");
  30. loc.firstProperty = loc.finderProperties[1];
  31. loc.secondProperty = IIf(ArrayLen(loc.finderProperties) == 2, "loc.finderProperties[2]", "");
  32. // throw an error when more than one argument is passed in but not `value` (for single property) or `values` (for multiple properties)
  33. // this means that model("artist").findOneByName("U2") will still work but not model("artist").findOneByName(values="U2", returnAs="query"), need to pass in just `value` there instead.
  34. if (application.wheels.showErrorInformation)
  35. {
  36. if (StructCount(arguments.missingMethodArguments) gt 1)
  37. {
  38. if (Len(loc.secondProperty))
  39. {
  40. if (!StructKeyExists(arguments.missingMethodArguments, "values"))
  41. $throw(type="Wheels.IncorrectArguments", message="The `values` argument is required but was not passed in.", extendedInfo="Pass in a list of values to the dynamic finder in the `values` argument.");
  42. }
  43. else
  44. {
  45. if (!StructKeyExists(arguments.missingMethodArguments, "value"))
  46. $throw(type="Wheels.IncorrectArguments", message="The `value` argument is required but was not passed in.", extendedInfo="Pass in a value to the dynamic finder in the `value` argument.");
  47. }
  48. }
  49. }
  50. if (StructCount(arguments.missingMethodArguments) == 1)
  51. loc.firstValue = Trim(ListFirst(arguments.missingMethodArguments[1]));
  52. else if (StructKeyExists(arguments.missingMethodArguments, "value"))
  53. loc.firstValue = arguments.missingMethodArguments.value;
  54. else if (StructKeyExists(arguments.missingMethodArguments, "values"))
  55. loc.firstValue = Trim(ListFirst(arguments.missingMethodArguments.values));
  56. loc.addToWhere = loc.firstProperty & " " & $dynamicFinderOperator(loc.firstProperty) & " '" & loc.firstValue & "'";
  57. if (Len(loc.secondProperty))
  58. {
  59. if (StructCount(arguments.missingMethodArguments) == 1)
  60. loc.secondValue = Trim(ListLast(arguments.missingMethodArguments[1]));
  61. else if (StructKeyExists(arguments.missingMethodArguments, "values"))
  62. loc.secondValue = Trim(ListLast(arguments.missingMethodArguments.values));
  63. loc.addToWhere = loc.addToWhere & " AND " & loc.secondProperty & " " & $dynamicFinderOperator(loc.secondProperty) & " '" & loc.secondValue & "'";
  64. }
  65. arguments.missingMethodArguments.where = IIf(StructKeyExists(arguments.missingMethodArguments, "where"), "'(' & arguments.missingMethodArguments.where & ') AND (' & loc.addToWhere & ')'", "loc.addToWhere");
  66. StructDelete(arguments.missingMethodArguments, "1");
  67. StructDelete(arguments.missingMethodArguments, "value");
  68. StructDelete(arguments.missingMethodArguments, "values");
  69. loc.returnValue = IIf(Left(arguments.missingMethodName, 9) == "findOneBy", "findOne(argumentCollection=arguments.missingMethodArguments)", "findAll(argumentCollection=arguments.missingMethodArguments)");
  70. }
  71. else
  72. {
  73. loc.returnValue = $associationMethod(argumentCollection=arguments);
  74. }
  75. if (!StructKeyExists(loc, "returnValue"))
  76. $throw(type="Wheels.MethodNotFound", message="The method `#arguments.missingMethodName#` was not found in the `#variables.wheels.class.modelName#` model.", extendedInfo="Check your spelling or add the method to the model's CFC file.");
  77. </cfscript>
  78. <cfreturn loc.returnValue>
  79. </cffunction>
  80. <cffunction name="$dynamicFinderOperator" returntype="string" access="public" output="false">
  81. <cfargument name="property" type="string" required="true">
  82. <cfscript>
  83. if (StructKeyExists(variables.wheels.class.properties, arguments.property) && variables.wheels.class.properties[arguments.property].dataType == "text")
  84. return "LIKE";
  85. else
  86. return "=";
  87. </cfscript>
  88. </cffunction>
  89. <cffunction name="$associationMethod" returntype="any" access="public" output="false">
  90. <cfscript>
  91. var loc = {};
  92. for (loc.key in variables.wheels.class.associations)
  93. {
  94. loc.method = "";
  95. if (StructKeyExists(variables.wheels.class.associations[loc.key], "shortcut") && arguments.missingMethodName == variables.wheels.class.associations[loc.key].shortcut)
  96. {
  97. loc.method = "findAll";
  98. loc.joinAssociation = $expandedAssociations(include=loc.key);
  99. loc.joinAssociation = loc.joinAssociation[1];
  100. loc.joinClass = loc.joinAssociation.modelName;
  101. loc.info = model(loc.joinClass).$expandedAssociations(include=ListFirst(variables.wheels.class.associations[loc.key].through));
  102. loc.info = loc.info[1];
  103. loc.componentReference = model(loc.info.modelName);
  104. loc.include = ListLast(variables.wheels.class.associations[loc.key].through);
  105. if (StructKeyExists(arguments.missingMethodArguments, "include"))
  106. loc.include = "#loc.include#(#arguments.missingMethodArguments.include#)";
  107. arguments.missingMethodArguments.include = loc.include;
  108. loc.where = $keyWhereString(properties=loc.joinAssociation.foreignKey, keys=loc.componentReference.primaryKeys());
  109. if (StructKeyExists(arguments.missingMethodArguments, "where"))
  110. loc.where = "(#loc.where#) AND (#arguments.missingMethodArguments.where#)";
  111. arguments.missingMethodArguments.where = loc.where;
  112. if (!StructKeyExists(arguments.missingMethodArguments, "returnIncluded"))
  113. arguments.missingMethodArguments.returnIncluded = false;
  114. }
  115. else if (ListFindNoCase(variables.wheels.class.associations[loc.key].methods, arguments.missingMethodName))
  116. {
  117. loc.info = $expandedAssociations(include=loc.key);
  118. loc.info = loc.info[1];
  119. loc.componentReference = model(loc.info.modelName);
  120. if (loc.info.type == "hasOne")
  121. {
  122. loc.where = $keyWhereString(properties=loc.info.foreignKey, keys=primaryKeys());
  123. if (StructKeyExists(arguments.missingMethodArguments, "where"))
  124. loc.where = "(#loc.where#) AND (#arguments.missingMethodArguments.where#)";
  125. loc.name = ReplaceNoCase(arguments.missingMethodName, loc.key, "object"); // create a generic method name (example: "hasProfile" becomes "hasObject")
  126. if (loc.name == "object")
  127. {
  128. loc.method = "findOne";
  129. arguments.missingMethodArguments.where = loc.where;
  130. }
  131. else if (loc.name == "hasObject")
  132. {
  133. loc.method = "exists";
  134. arguments.missingMethodArguments.where = loc.where;
  135. }
  136. else if (loc.name == "newObject")
  137. {
  138. loc.method = "new";
  139. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey);
  140. }
  141. else if (loc.name == "createObject")
  142. {
  143. loc.method = "create";
  144. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey);
  145. }
  146. else if (loc.name == "removeObject")
  147. {
  148. loc.method = "updateOne";
  149. arguments.missingMethodArguments.where = loc.where;
  150. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey, setToNull=true);
  151. }
  152. else if (loc.name == "deleteObject")
  153. {
  154. loc.method = "deleteOne";
  155. arguments.missingMethodArguments.where = loc.where;
  156. }
  157. else if (loc.name == "setObject")
  158. {
  159. // single argument, must be either the key or the object
  160. if (StructCount(arguments.missingMethodArguments) eq 1)
  161. {
  162. if (IsObject(arguments.missingMethodArguments[1]))
  163. {
  164. loc.componentReference = arguments.missingMethodArguments[1];
  165. loc.method = "update";
  166. }
  167. else
  168. {
  169. arguments.missingMethodArguments.key = arguments.missingMethodArguments[1];
  170. loc.method = "updateByKey";
  171. }
  172. StructDelete(arguments.missingMethodArguments, "1");
  173. }
  174. // multiple arguments so ensure that either 'key' or the association name exists (loc.key)
  175. else
  176. {
  177. if (StructKeyExists(arguments.missingMethodArguments, loc.key) and IsObject(arguments.missingMethodArguments[loc.key]))
  178. {
  179. loc.componentReference = arguments.missingMethodArguments[loc.key];
  180. loc.method = "update";
  181. StructDelete(arguments.missingMethodArguments, loc.key);
  182. }
  183. else if (StructKeyExists(arguments.missingMethodArguments, "key"))
  184. loc.method = "updateByKey";
  185. else
  186. $throw(type="Wheels.IncorrectArguments", message="The `#loc.key#` or `key` named argument is required.", extendedInfo="When using multiple arguments for #loc.name#() you must supply an object using the argument `#loc.key#` or a key using the argument `key`, e.g. #loc.name#(#loc.key#=post) or #loc.name#(key=post.id).");
  187. }
  188. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey);
  189. }
  190. }
  191. else if (loc.info.type == "hasMany")
  192. {
  193. loc.where = $keyWhereString(properties=loc.info.foreignKey, keys=primaryKeys());
  194. if (StructKeyExists(arguments.missingMethodArguments, "where"))
  195. loc.where = "(#loc.where#) AND (#arguments.missingMethodArguments.where#)";
  196. loc.singularKey = singularize(loc.key);
  197. loc.name = ReplaceNoCase(ReplaceNoCase(arguments.missingMethodName, loc.key, "objects"), loc.singularKey, "object"); // create a generic method name (example: "hasComments" becomes "hasObjects")
  198. if (loc.name == "objects")
  199. {
  200. loc.method = "findAll";
  201. arguments.missingMethodArguments.where = loc.where;
  202. }
  203. else if (loc.name == "addObject")
  204. {
  205. // single argument, must be either the key or the object
  206. if (StructCount(arguments.missingMethodArguments) eq 1)
  207. {
  208. if (IsObject(arguments.missingMethodArguments[1]))
  209. {
  210. loc.componentReference = arguments.missingMethodArguments[1];
  211. loc.method = "update";
  212. }
  213. else
  214. {
  215. arguments.missingMethodArguments.key = arguments.missingMethodArguments[1];
  216. loc.method = "updateByKey";
  217. }
  218. StructDelete(arguments.missingMethodArguments, "1");
  219. }
  220. // multiple arguments so ensure that either 'key' or the singularized association name exists (loc.singularKey)
  221. else
  222. {
  223. if (StructKeyExists(arguments.missingMethodArguments, loc.singularKey) and IsObject(arguments.missingMethodArguments[loc.singularKey]))
  224. {
  225. loc.componentReference = arguments.missingMethodArguments[loc.singularKey];
  226. loc.method = "update";
  227. StructDelete(arguments.missingMethodArguments, loc.singularKey);
  228. }
  229. else if (StructKeyExists(arguments.missingMethodArguments, "key"))
  230. loc.method = "updateByKey";
  231. else
  232. $throw(type="Wheels.IncorrectArguments", message="The `#loc.singularKey#` or `key` named argument is required.", extendedInfo="When using multiple arguments for #loc.name#() you must supply an object using the argument `#loc.singularKey#` or a key using the argument `key`, e.g. #loc.name#(#loc.singularKey#=post) or #loc.name#(key=post.id).");
  233. }
  234. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey);
  235. }
  236. else if (loc.name == "removeObject")
  237. {
  238. // single argument, must be either the key or the object
  239. if (StructCount(arguments.missingMethodArguments) eq 1)
  240. {
  241. if (IsObject(arguments.missingMethodArguments[1]))
  242. {
  243. loc.componentReference = arguments.missingMethodArguments[1];
  244. loc.method = "update";
  245. }
  246. else
  247. {
  248. arguments.missingMethodArguments.key = arguments.missingMethodArguments[1];
  249. loc.method = "updateByKey";
  250. }
  251. StructDelete(arguments.missingMethodArguments, "1");
  252. }
  253. // multiple arguments so ensure that either 'key' or the singularized object name exists (loc.singularKey)
  254. else
  255. {
  256. if (StructKeyExists(arguments.missingMethodArguments, loc.singularKey) and IsObject(arguments.missingMethodArguments[loc.singularKey]))
  257. {
  258. loc.componentReference = arguments.missingMethodArguments[loc.singularKey];
  259. loc.method = "update";
  260. StructDelete(arguments.missingMethodArguments, loc.singularKey);
  261. }
  262. else if (StructKeyExists(arguments.missingMethodArguments, "key"))
  263. loc.method = "updateByKey";
  264. else
  265. $throw(type="Wheels.IncorrectArguments", message="The `#loc.singularKey#` or `key` named argument is required.", extendedInfo="When using multiple arguments for #loc.name#() you must supply an object using the argument `#loc.singularKey#` or a key using the argument `key`, e.g. #loc.name#(#loc.singularKey#=post) or #loc.name#(key=post.id).");
  266. }
  267. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey, setToNull=true);
  268. }
  269. else if (loc.name == "deleteObject")
  270. {
  271. // single argument, must be either the key or the object
  272. if (StructCount(arguments.missingMethodArguments) eq 1)
  273. {
  274. if (IsObject(arguments.missingMethodArguments[1]))
  275. {
  276. loc.componentReference = arguments.missingMethodArguments[1];
  277. loc.method = "delete";
  278. }
  279. else
  280. {
  281. arguments.missingMethodArguments.key = arguments.missingMethodArguments[1];
  282. loc.method = "deleteByKey";
  283. }
  284. StructDelete(arguments.missingMethodArguments, "1");
  285. }
  286. // multiple arguments so ensure that either 'key' or the singularized object name exists (loc.singularKey)
  287. else
  288. {
  289. if (StructKeyExists(arguments.missingMethodArguments, loc.singularKey) and IsObject(arguments.missingMethodArguments[loc.singularKey]))
  290. {
  291. loc.componentReference = arguments.missingMethodArguments[loc.singularKey];
  292. loc.method = "delete";
  293. StructDelete(arguments.missingMethodArguments, loc.singularKey);
  294. }
  295. else if (StructKeyExists(arguments.missingMethodArguments, "key"))
  296. loc.method = "deleteByKey";
  297. else
  298. $throw(type="Wheels.IncorrectArguments", message="The `#loc.singularKey#` or `key` named argument is required.", extendedInfo="When using multiple arguments for #loc.name#() you must supply an object using the argument `#loc.singularKey#` or a key using the argument `key`, e.g. #loc.name#(#loc.singularKey#=post) or #loc.name#(key=post.id).");
  299. }
  300. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey);
  301. }
  302. else if (loc.name == "hasObjects")
  303. {
  304. loc.method = "exists";
  305. arguments.missingMethodArguments.where = loc.where;
  306. }
  307. else if (loc.name == "newObject")
  308. {
  309. loc.method = "new";
  310. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey);
  311. }
  312. else if (loc.name == "createObject")
  313. {
  314. loc.method = "create";
  315. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey);
  316. }
  317. else if (loc.name == "objectCount")
  318. {
  319. loc.method = "count";
  320. arguments.missingMethodArguments.where = loc.where;
  321. }
  322. else if (loc.name == "findOneObject")
  323. {
  324. loc.method = "findOne";
  325. arguments.missingMethodArguments.where = loc.where;
  326. }
  327. else if (loc.name == "removeAllObjects")
  328. {
  329. loc.method = "updateAll";
  330. arguments.missingMethodArguments.where = loc.where;
  331. $setForeignKeyValues(missingMethodArguments=arguments.missingMethodArguments, keys=loc.info.foreignKey, setToNull=true);
  332. }
  333. else if (loc.name == "deleteAllObjects")
  334. {
  335. loc.method = "deleteAll";
  336. arguments.missingMethodArguments.where = loc.where;
  337. }
  338. }
  339. else if (loc.info.type == "belongsTo")
  340. {
  341. loc.where = $keyWhereString(keys=loc.info.foreignKey, properties=loc.componentReference.primaryKeys());
  342. if (StructKeyExists(arguments.missingMethodArguments, "where"))
  343. loc.where = "(#loc.where#) AND (#arguments.missingMethodArguments.where#)";
  344. loc.name = ReplaceNoCase(arguments.missingMethodName, loc.key, "object"); // create a generic method name (example: "hasAuthor" becomes "hasObject")
  345. if (loc.name == "object")
  346. {
  347. loc.method = "findByKey";
  348. arguments.missingMethodArguments.key = $propertyValue(name=loc.info.foreignKey);
  349. }
  350. else if (loc.name == "hasObject")
  351. {
  352. loc.method = "exists";
  353. arguments.missingMethodArguments.key = $propertyValue(name=loc.info.foreignKey);
  354. }
  355. }
  356. }
  357. if (Len(loc.method))
  358. loc.returnValue = $invoke(componentReference=loc.componentReference, method=loc.method, invokeArgs=arguments.missingMethodArguments);
  359. }
  360. </cfscript>
  361. <cfif StructKeyExists(loc, "returnValue")>
  362. <cfreturn loc.returnValue>
  363. </cfif>
  364. </cffunction>
  365. <cffunction name="$propertyValue" returntype="string" access="public" output="false" hint="Returns the object's value of the passed in property name. If you pass in a list of property names you will get the values back in a list as well.">
  366. <cfargument name="name" type="string" required="true" hint="Name of property to get value for.">
  367. <cfscript>
  368. var loc = {};
  369. loc.returnValue = "";
  370. loc.iEnd = ListLen(arguments.name);
  371. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  372. loc.returnValue = ListAppend(loc.returnValue, this[ListGetAt(arguments.name, loc.i)]);
  373. </cfscript>
  374. <cfreturn loc.returnValue>
  375. </cffunction>
  376. <cffunction name="$setForeignKeyValues" returntype="void" access="public" output="false">
  377. <cfargument name="missingMethodArguments" type="struct" required="true">
  378. <cfargument name="keys" type="string" required="true">
  379. <cfargument name="setToNull" type="boolean" required="false" default="false">
  380. <cfscript>
  381. var loc = {};
  382. loc.iEnd = ListLen(arguments.keys);
  383. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  384. {
  385. if (arguments.setToNull)
  386. arguments.missingMethodArguments[ListGetAt(arguments.keys, loc.i)] = "";
  387. else
  388. arguments.missingMethodArguments[ListGetAt(arguments.keys, loc.i)] = this[primaryKeys(loc.i)];
  389. }
  390. </cfscript>
  391. </cffunction>