| 1 | <!--- |
|---|
| 2 | Name : cfcs/question.cfc |
|---|
| 3 | Author : Raymond Camden |
|---|
| 4 | Created : |
|---|
| 5 | Last Updated : April 10, 2006 |
|---|
| 6 | History : throw error on add/update if rank already exists |
|---|
| 7 | : support for tableprefix (3/10/06) |
|---|
| 8 | : tableprefix fix (rkc 3/30/06) |
|---|
| 9 | : Fix for bug that occurs when you delete a question and don't fix rank (rkc 4/10/06) |
|---|
| 10 | Purpose : |
|---|
| 11 | ---> |
|---|
| 12 | <cfcomponent displayName="Question" hint="Handles all question interactions." output="false"> |
|---|
| 13 | |
|---|
| 14 | <cfset variables.utils = createObject("component","utils")> |
|---|
| 15 | |
|---|
| 16 | <cffunction name="init" access="public" returnType="question" output="false" |
|---|
| 17 | hint="Returns an instance of the CFC initialized with the correct DSN."> |
|---|
| 18 | <cfargument name="dsn" type="string" required="true" hint="DSN used for all operations in the CFC."> |
|---|
| 19 | <cfargument name="dbtype" type="string" required="true" hint="Database type."> |
|---|
| 20 | <cfargument name="tableprefix" type="string" required="true" hint="Table prefix."> |
|---|
| 21 | |
|---|
| 22 | <cfset variables.dsn = arguments.dsn> |
|---|
| 23 | <cfset variables.dbtype = arguments.dbtype> |
|---|
| 24 | <cfset variables.tableprefix = arguments.tableprefix> |
|---|
| 25 | |
|---|
| 26 | <cfset variables.survey = createObject("component","survey").init(variables.dsn,variables.dbtype,variables.tableprefix)> |
|---|
| 27 | <cfset variables.questiontype = createObject("component","questiontype").init(variables.dsn,variables.dbtype,variables.tableprefix)> |
|---|
| 28 | |
|---|
| 29 | <cfreturn this> |
|---|
| 30 | |
|---|
| 31 | </cffunction> |
|---|
| 32 | |
|---|
| 33 | <cffunction name="addAnswers" access="public" returnType="void" output="false" |
|---|
| 34 | hint="Adds a set of answers."> |
|---|
| 35 | <cfargument name="questionidfk" type="uuid" required="true" hint="Related question."> |
|---|
| 36 | <cfargument name="answers" type="array" required="true" hint="Array of answer structs"> |
|---|
| 37 | <cfset var x = ""> |
|---|
| 38 | |
|---|
| 39 | <cfloop index="x" from="1" to="#arrayLen(arguments.answers)#"> |
|---|
| 40 | <cfif structKeyExists(arguments.answers[x],"answer") and |
|---|
| 41 | structKeyExists(arguments.answers[x],"rank")> |
|---|
| 42 | <cfquery datasource="#variables.dsn#"> |
|---|
| 43 | insert into #variables.tableprefix#answers(id, questionidfk, answer, rank) |
|---|
| 44 | values(<cfqueryparam value="#createUUID()#" cfsqltype="CF_SQL_VARCHAR" maxlength="35">, |
|---|
| 45 | <cfqueryparam value="#arguments.questionidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35">, |
|---|
| 46 | <cfqueryparam value="#arguments.answers[x].answer#" cfsqltype="CF_SQL_VARCHAR" maxlength="255">, |
|---|
| 47 | <cfqueryparam value="#arguments.answers[x].rank#" cfsqltype="CF_SQL_INTEGER">) |
|---|
| 48 | </cfquery> |
|---|
| 49 | </cfif> |
|---|
| 50 | </cfloop> |
|---|
| 51 | |
|---|
| 52 | </cffunction> |
|---|
| 53 | |
|---|
| 54 | <cffunction name="addQuestion" access="public" returnType="string" output="false" |
|---|
| 55 | hint="Adds a question."> |
|---|
| 56 | <cfargument name="question" type="string" required="true" hint="The Question itself."> |
|---|
| 57 | <cfargument name="rank" type="numeric" required="true" hint="Rank of the question in the survey."> |
|---|
| 58 | <cfargument name="required" type="boolean" required="true" hint="Is the question required?"> |
|---|
| 59 | <cfargument name="surveyidfk" type="uuid" required="true" hint="Survey we are adding to."> |
|---|
| 60 | <cfargument name="questionTypeidfk" type="uuid" required="true" hint="Type of question."> |
|---|
| 61 | <cfargument name="answers" type="array" required="false" hint="Array of answer structs"> |
|---|
| 62 | <cfset var newID = createUUID()> |
|---|
| 63 | <cfset var check = ""> |
|---|
| 64 | |
|---|
| 65 | <!--- first see if this rank exists already ---> |
|---|
| 66 | <cfquery name="check" datasource="#variables.dsn#"> |
|---|
| 67 | select id |
|---|
| 68 | from #variables.tableprefix#questions |
|---|
| 69 | where rank = <cfqueryparam value="#arguments.rank#" cfsqltype="CF_SQL_INTEGER"> |
|---|
| 70 | and surveyidfk = <cfqueryparam value="#arguments.surveyidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 71 | </cfquery> |
|---|
| 72 | |
|---|
| 73 | <cfif check.recordCount> |
|---|
| 74 | <cfthrow type="Question" message="A question with this rank exists already."> |
|---|
| 75 | </cfif> |
|---|
| 76 | |
|---|
| 77 | <cfquery datasource="#variables.dsn#"> |
|---|
| 78 | insert into #variables.tableprefix#questions(id, question, rank, required, surveyidfk, questiontypeidfk) |
|---|
| 79 | values( |
|---|
| 80 | <cfqueryparam value="#newid#" cfsqltype="CF_SQL_VARCHAR" maxlength="35">, |
|---|
| 81 | <cfqueryparam value="#arguments.question#" cfsqltype="CF_SQL_VARCHAR" maxlength="255">, |
|---|
| 82 | <cfqueryparam value="#arguments.rank#" cfsqltype="CF_SQL_INTEGER">, |
|---|
| 83 | <cfqueryparam value="#arguments.required#" cfsqltype="#variables.utils.getQueryParamType(variables.dbtype,"CF_SQL_BIT")#">, |
|---|
| 84 | <cfqueryparam value="#arguments.surveyidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35">, |
|---|
| 85 | <cfqueryparam value="#arguments.questionTypeidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 86 | ) |
|---|
| 87 | </cfquery> |
|---|
| 88 | |
|---|
| 89 | <cfif isDefined("arguments.answers") and arrayLen(arguments.answers)> |
|---|
| 90 | <cfset addAnswers(newID,answers)> |
|---|
| 91 | </cfif> |
|---|
| 92 | |
|---|
| 93 | <cfreturn newID> |
|---|
| 94 | |
|---|
| 95 | </cffunction> |
|---|
| 96 | |
|---|
| 97 | <cffunction name="deleteAnswer" access="public" returnType="void" output="false" |
|---|
| 98 | hint="Deletes an answer."> |
|---|
| 99 | <cfargument name="id" type="uuid" required="true" hint="Answer ID"> |
|---|
| 100 | |
|---|
| 101 | <cfquery datasource="#variables.dsn#"> |
|---|
| 102 | delete from #variables.tableprefix#answers |
|---|
| 103 | where id = <cfqueryparam value="#arguments.id#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 104 | </cfquery> |
|---|
| 105 | <cfquery datasource="#variables.dsn#"> |
|---|
| 106 | delete from #variables.tableprefix#results |
|---|
| 107 | where answeridfk = <cfqueryparam value="#arguments.id#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 108 | </cfquery> |
|---|
| 109 | |
|---|
| 110 | </cffunction> |
|---|
| 111 | |
|---|
| 112 | <cffunction name="deleteAnswers" access="public" returnType="void" output="false" |
|---|
| 113 | hint="Deletes a set of answers."> |
|---|
| 114 | <cfargument name="questionidfk" type="uuid" required="true" hint="Related question."> |
|---|
| 115 | |
|---|
| 116 | <cfquery datasource="#variables.dsn#"> |
|---|
| 117 | delete from #variables.tableprefix#answers |
|---|
| 118 | where questionidfk = <cfqueryparam value="#arguments.questionidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 119 | </cfquery> |
|---|
| 120 | |
|---|
| 121 | </cffunction> |
|---|
| 122 | |
|---|
| 123 | <cffunction name="deleteQuestion" access="public" returnType="void" output="false" |
|---|
| 124 | hint="Deletes a questions. Also does cleanup on results/answers."> |
|---|
| 125 | <cfargument name="id" type="uuid" required="true" hint="The UUID of the question to delete."> |
|---|
| 126 | |
|---|
| 127 | <cfset deleteAnswers(arguments.id)> |
|---|
| 128 | |
|---|
| 129 | <cfquery datasource="#variables.dsn#"> |
|---|
| 130 | delete from #variables.tableprefix#questions |
|---|
| 131 | where id = <cfqueryparam value="#arguments.id#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 132 | </cfquery> |
|---|
| 133 | <!--- remove from results ---> |
|---|
| 134 | <cfquery datasource="#variables.dsn#"> |
|---|
| 135 | delete from #variables.tableprefix#results |
|---|
| 136 | where questionidfk = <cfqueryparam value="#arguments.id#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 137 | </cfquery> |
|---|
| 138 | |
|---|
| 139 | </cffunction> |
|---|
| 140 | |
|---|
| 141 | <cffunction name="duplicateQuestion" access="public" returnType="void" output="false" |
|---|
| 142 | hint="Duplicates a question."> |
|---|
| 143 | <cfargument name="id" type="uuid" required="true" hint="The UUID of the question to duplicate."> |
|---|
| 144 | <cfargument name="surveyidfk" type="uuid" required="true" hint="The UUID of the survey for the question."> |
|---|
| 145 | |
|---|
| 146 | <cfset var q = getQuestion(arguments.id)> |
|---|
| 147 | <cfset var answers = getAnswers(arguments.id)> |
|---|
| 148 | <cfset var aData = arrayNew(1)> |
|---|
| 149 | |
|---|
| 150 | <cfloop query="answers"> |
|---|
| 151 | <cfset aData[arrayLen(aData)+1] = structNew()> |
|---|
| 152 | <cfset aData[arrayLen(aData)].answer = answers.answer> |
|---|
| 153 | <cfset aData[arrayLen(aData)].rank = answers.rank> |
|---|
| 154 | </cfloop> |
|---|
| 155 | |
|---|
| 156 | <cfset addQuestion(q.question,q.rank,q.required,arguments.surveyidfk,q.questionTypeIDFK,aData)> |
|---|
| 157 | |
|---|
| 158 | </cffunction> |
|---|
| 159 | |
|---|
| 160 | <cffunction name="getAnswers" access="public" returnType="query" output="false" |
|---|
| 161 | hint="Grabs a set of answers for a question."> |
|---|
| 162 | <cfargument name="id" type="uuid" required="true" hint="The UUID for the related question."> |
|---|
| 163 | |
|---|
| 164 | <cfset var qAnswers = ""> |
|---|
| 165 | |
|---|
| 166 | <cfquery name="qAnswers" datasource="#variables.dsn#"> |
|---|
| 167 | select id, answer, rank |
|---|
| 168 | from #variables.tableprefix#answers |
|---|
| 169 | where questionidfk = <cfqueryparam value="#arguments.id#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 170 | order by rank asc |
|---|
| 171 | </cfquery> |
|---|
| 172 | |
|---|
| 173 | <cfreturn qAnswers> |
|---|
| 174 | |
|---|
| 175 | </cffunction> |
|---|
| 176 | |
|---|
| 177 | <cffunction name="getQuestion" access="public" returnType="struct" output="false" |
|---|
| 178 | hint="Grabs a question."> |
|---|
| 179 | <cfargument name="id" type="uuid" required="true" hint="The UUID of the question to get."> |
|---|
| 180 | <cfset var qQuestion = ""> |
|---|
| 181 | <cfset var result = ""> |
|---|
| 182 | |
|---|
| 183 | <cfquery name="qQuestion" datasource="#variables.dsn#"> |
|---|
| 184 | select #variables.tableprefix#questions.id, surveyidfk, question, questiontypeidfk, rank, required, |
|---|
| 185 | #variables.tableprefix#questiontypes.name as questiontype |
|---|
| 186 | from #variables.tableprefix#questions, #variables.tableprefix#questiontypes |
|---|
| 187 | where #variables.tableprefix#questions.id = <cfqueryparam value="#arguments.id#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 188 | and #variables.tableprefix#questions.questiontypeidfk = #variables.tableprefix#questiontypes.id |
|---|
| 189 | </cfquery> |
|---|
| 190 | |
|---|
| 191 | <cfset result = variables.utils.queryToStruct(qQuestion)> |
|---|
| 192 | <cfset result.answers = getAnswers(arguments.id)> |
|---|
| 193 | <cfreturn result> |
|---|
| 194 | |
|---|
| 195 | </cffunction> |
|---|
| 196 | |
|---|
| 197 | |
|---|
| 198 | <cffunction name="getQuestions" access="public" returnType="query" output="false" |
|---|
| 199 | hint="Returns all the questions for a survey."> |
|---|
| 200 | <cfargument name="surveyidfk" type="string" required="true" hint="Survey ID"> |
|---|
| 201 | <cfargument name="rank" type="numeric" required="false" hint="Returns just a particular rank."> |
|---|
| 202 | <cfset var qGetQuestions = ""> |
|---|
| 203 | <cfset var ranklink = ""> |
|---|
| 204 | <cfset var getRanks = ""> |
|---|
| 205 | |
|---|
| 206 | <!--- So, rank was written to assume that the first question was rank 1. But it's possible a admin |
|---|
| 207 | may make a survey and delete question one. So now I want to change rank from 1 to the 1st rank. ---> |
|---|
| 208 | <cfif isDefined("arguments.rank")> |
|---|
| 209 | <cfquery name="getRanks" datasource="#variables.dsn#"> |
|---|
| 210 | select rank |
|---|
| 211 | from #variables.tableprefix#questions |
|---|
| 212 | where surveyidfk = <cfqueryparam value="#arguments.surveyidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 213 | order by rank asc |
|---|
| 214 | </cfquery> |
|---|
| 215 | <!--- rewrite rank ---> |
|---|
| 216 | <cfset ranklist = valueList(getRanks.rank)> |
|---|
| 217 | <cfif arguments.rank lte listLen(ranklist)> |
|---|
| 218 | <cfset arguments.rank = listGetAt(ranklist, arguments.rank)> |
|---|
| 219 | <cfelse> |
|---|
| 220 | <cfset arguments.rank = listFirst(ranklist)> |
|---|
| 221 | </cfif> |
|---|
| 222 | </cfif> |
|---|
| 223 | |
|---|
| 224 | <cfquery name="qGetQuestions" datasource="#variables.dsn#"> |
|---|
| 225 | select #variables.tableprefix#questions.id, surveyidfk, question, questiontypeidfk, rank, required, |
|---|
| 226 | #variables.tableprefix#questiontypes.name as questiontype, |
|---|
| 227 | #variables.tableprefix#questiontypes.handlerroot as handlerroot |
|---|
| 228 | from #variables.tableprefix#questions, #variables.tableprefix#questiontypes |
|---|
| 229 | where surveyidfk = <cfqueryparam value="#arguments.surveyidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 230 | and #variables.tableprefix#questions.questiontypeidfk = #variables.tableprefix#questiontypes.id |
|---|
| 231 | <cfif isDefined("arguments.rank")> |
|---|
| 232 | and #variables.tableprefix#questions.rank = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#arguments.rank#"> |
|---|
| 233 | </cfif> |
|---|
| 234 | order by rank asc |
|---|
| 235 | </cfquery> |
|---|
| 236 | |
|---|
| 237 | <cfreturn qGetQuestions> |
|---|
| 238 | |
|---|
| 239 | </cffunction> |
|---|
| 240 | |
|---|
| 241 | <cffunction name="updateAnswers" access="public" returnType="void" output="false" |
|---|
| 242 | hint="Updates a set of answers in the db."> |
|---|
| 243 | <cfargument name="questionidfk" type="uuid" required="true" hint="Question ID."> |
|---|
| 244 | <cfargument name="answers" type="array" required="true" hint="Array of answer structs"> |
|---|
| 245 | <cfset var x = ""> |
|---|
| 246 | |
|---|
| 247 | <cfloop index="x" from="1" to="#arrayLen(arguments.answers)#"> |
|---|
| 248 | <cfif structKeyExists(arguments.answers[x], "answer") and |
|---|
| 249 | structKeyExists(arguments.answers[x], "rank") and |
|---|
| 250 | structKeyExists(arguments.answers[x], "id")> |
|---|
| 251 | <cfquery datasource="#variables.dsn#"> |
|---|
| 252 | update #variables.tableprefix#answers |
|---|
| 253 | set |
|---|
| 254 | answer = <cfqueryparam value="#arguments.answers[x].answer#" cfsqltype="CF_SQL_VARCHAR" maxlength="255">, |
|---|
| 255 | rank = <cfqueryparam value="#arguments.answers[x].rank#" cfsqltype="CF_SQL_INTEGER"> |
|---|
| 256 | where id = <cfqueryparam value="#arguments.answers[x].id#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 257 | </cfquery> |
|---|
| 258 | <cfelseif structKeyExists(arguments.answers[x], "answer") and |
|---|
| 259 | structKeyExists(arguments.answers[x], "rank")> |
|---|
| 260 | <!--- this is a new answer ---> |
|---|
| 261 | <cfquery datasource="#variables.dsn#"> |
|---|
| 262 | insert into #variables.tableprefix#answers(id,questionidfk,answer,rank) |
|---|
| 263 | values(<cfqueryparam value="#createUUID()#" cfsqltype="CF_SQL_VARCHAR" maxlength="35">, |
|---|
| 264 | <cfqueryparam value="#arguments.questionidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35">, |
|---|
| 265 | <cfqueryparam value="#arguments.answers[x].answer#" cfsqltype="CF_SQL_VARCHAR" maxlength="255">, |
|---|
| 266 | <cfqueryparam value="#arguments.answers[x].rank#" cfsqltype="CF_SQL_INTEGER">) |
|---|
| 267 | </cfquery> |
|---|
| 268 | </cfif> |
|---|
| 269 | </cfloop> |
|---|
| 270 | |
|---|
| 271 | </cffunction> |
|---|
| 272 | |
|---|
| 273 | <cffunction name="updateQuestion" access="public" returnType="void" output="false" |
|---|
| 274 | hint="Updates a question in the db."> |
|---|
| 275 | <cfargument name="id" type="uuid" required="true" hint="Question ID."> |
|---|
| 276 | <cfargument name="question" type="string" required="true" hint="The Question itself."> |
|---|
| 277 | <cfargument name="rank" type="numeric" required="true" hint="Rank of the question in the survey."> |
|---|
| 278 | <cfargument name="required" type="boolean" required="true" hint="Is the question required?"> |
|---|
| 279 | <cfargument name="surveyidfk" type="string" required="true" hint="Survey we are adding to."> |
|---|
| 280 | <cfargument name="questionTypeidfk" type="string" required="true" hint="Type of question."> |
|---|
| 281 | <cfargument name="answers" type="array" required="false" hint="Array of answer structs"> |
|---|
| 282 | <cfset var check = ""> |
|---|
| 283 | <cfif not validData(arguments)> |
|---|
| 284 | <cfset variables.utils.throw("QuestionCFC","This question data is not valid.")> |
|---|
| 285 | </cfif> |
|---|
| 286 | |
|---|
| 287 | <!--- first see if this rank exists already ---> |
|---|
| 288 | <cfquery name="check" datasource="#variables.dsn#"> |
|---|
| 289 | select id |
|---|
| 290 | from #variables.tableprefix#questions |
|---|
| 291 | where rank = <cfqueryparam value="#arguments.rank#" cfsqltype="CF_SQL_INTEGER"> |
|---|
| 292 | and id <> <cfqueryparam value="#arguments.ID#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 293 | and surveyidfk = <cfqueryparam value="#arguments.surveyidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 294 | </cfquery> |
|---|
| 295 | |
|---|
| 296 | <cfif check.recordCount> |
|---|
| 297 | <cfthrow type="Question" message="Another question with this rank exists already."> |
|---|
| 298 | </cfif> |
|---|
| 299 | |
|---|
| 300 | <cfquery datasource="#variables.dsn#"> |
|---|
| 301 | update #variables.tableprefix#questions |
|---|
| 302 | set |
|---|
| 303 | question = <cfqueryparam value="#arguments.question#" cfsqltype="CF_SQL_VARCHAR" maxlength="255">, |
|---|
| 304 | rank = <cfqueryparam value="#arguments.rank#" cfsqltype="CF_SQL_INTEGER">, |
|---|
| 305 | required = <cfqueryparam value="#arguments.required#" cfsqltype="#variables.utils.getQueryParamType(variables.dbtype,"CF_SQL_BIT")#">, |
|---|
| 306 | surveyidfk = <cfqueryparam value="#arguments.surveyidfk#" cfsqltype="CF_SQL_VARCHAR" maxlength="35">, |
|---|
| 307 | questionTypeidfk = <cfqueryparam value="#arguments.questionTypeIDFK#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 308 | where id = <cfqueryparam value="#arguments.ID#" cfsqltype="CF_SQL_VARCHAR" maxlength="35"> |
|---|
| 309 | </cfquery> |
|---|
| 310 | |
|---|
| 311 | <cfif isDefined("arguments.answers") and arrayLen(arguments.answers)> |
|---|
| 312 | <cfset updateAnswers(arguments.id,answers)> |
|---|
| 313 | </cfif> |
|---|
| 314 | |
|---|
| 315 | </cffunction> |
|---|
| 316 | |
|---|
| 317 | <cffunction name="validData" access="public" returnType="boolean" output="false" |
|---|
| 318 | hint="Checks to see if the question is valid."> |
|---|
| 319 | <cfargument name="data" type="struct" required="true" hint="Data to validate."> |
|---|
| 320 | <cfset var s = ""> |
|---|
| 321 | <cfset var qt = ""> |
|---|
| 322 | <cfif arguments.data.question is "" or arguments.data.surveyidfk is "" or arguments.data.questionTypeIDFK is ""> |
|---|
| 323 | <cfreturn false> |
|---|
| 324 | </cfif> |
|---|
| 325 | |
|---|
| 326 | <cftry> |
|---|
| 327 | <cfset s = variables.survey.getSurvey(arguments.data.surveyidfk)> |
|---|
| 328 | <cfset qt = variables.questiontype.getQuestionType(arguments.data.questionTypeIDFK)> |
|---|
| 329 | <cfcatch> |
|---|
| 330 | <!--- invalid survey or qt, return false ---> |
|---|
| 331 | <cfreturn false> |
|---|
| 332 | </cfcatch> |
|---|
| 333 | </cftry> |
|---|
| 334 | |
|---|
| 335 | <cfreturn true> |
|---|
| 336 | |
|---|
| 337 | </cffunction> |
|---|
| 338 | |
|---|
| 339 | |
|---|
| 340 | </cfcomponent> |
|---|