5 * Copyright 2004, Sung Kim/GForge, LLC
6 * Copyright 2009, Roland Mas
7 * Copyright (C) 2012 Alain Peyrat - Alcatel-Lucent
8 * http://fusionforge.org
10 * This file is part of FusionForge. FusionForge is free software;
11 * you can redistribute it and/or modify it under the terms of the
12 * GNU General Public License as published by the Free Software
13 * Foundation; either version 2 of the Licence, or (at your option)
16 * FusionForge is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 require_once $gfcommon.'include/Error.class.php';
27 require_once $gfcommon.'survey/SurveyQuestionFactory.class.php';
29 class Survey extends FFError {
32 * Associative array of data from db.
34 * @var array $data_array.
39 * Questions array in this survey
41 * @var array $question_array.
43 var $all_question_array;
56 * @param bool $survey_id
58 * @internal param \The $object Group object to which this survey is associated.
59 * @internal param \The $int survey_id.
60 * @internal param \The $array associative array of data.
63 function __construct(&$Group, $survey_id = false, $arr = false) {
65 if (!$Group || !is_object($Group)) {
66 $this->setError(_('No Valid Group Object'));
69 if ($Group->isError()) {
70 $this->setError('Survey: '.$Group->getErrorMessage());
73 $this->Group =& $Group;
76 if (!$arr || !is_array($arr)) {
77 if (!$this->fetchData($survey_id)) {
81 $this->data_array =& $arr;
82 if ($this->data_array['group_id'] != $this->Group->getID()) {
83 $this->setError(_('group_id in db result does not match Group Object'));
84 $this->data_array = null;
92 * create - use this function to create a survey
94 * @param string $survey_title The survey title
95 * @param array $add_questions The question numbers to be added
96 * @param int $is_active 1: Active, 0: Inactive
97 * @param int $is_result_public
98 * @param Allow|int $double_vote
99 * @internal param \The $string survey title
100 * @internal param array $int The question numbers to be added
101 * @internal param $is_active 1: Active, 0: Inactive
103 * @internal param $is_result_public 0: Admins Only, 1: Group Members, 2: FusionForge user, 3:voted user 4:Every body
104 * @internal param \Allow $double_vote double vote if it is 1
105 * @return boolean success.
107 function create($survey_title, $add_questions, $is_active = 0, $is_public = 1, $is_result_public = 0, $double_vote = 0) {
108 if (!$survey_title) {
109 $this->setError(_('Update Failed: Survey Title Required'));
111 /* We need at least one survey question at this point */
112 } elseif (!$add_questions || !is_array($add_questions) || count($add_questions)<1) {
113 $this->setError(_('Update Failed: Survey Questions Required'));
117 $group_id = $this->Group->GetID();
119 /* Make old style survey string from array: 1, 2, 3, ..., n */
120 $survey_questions = $this->_makeQuestionString($add_questions);
122 $result = db_query_params('INSERT INTO surveys (survey_title,group_id,survey_questions,is_active) VALUES ($1,$2,$3,$4)',
123 array(htmlspecialchars($survey_title),
129 $this->setError(_('Insert Error').db_error());
133 /* Load question to data array */
134 $survey_id=db_insertid($result,'surveys','survey_id');
135 return $this->fetchData($survey_id);
139 * update - use this function to update a survey
141 * @param string $survey_title The survey title
142 * @param array $add_questions The question numbers to be added
143 * @param array $del_questions The question numbers to be deleted
144 * @param int $is_active 1: Active, 0: Inactive
145 * @param int $is_result_public
146 * @param Allow|int $double_vote
147 * @internal param \The $string survey title
148 * @internal param array $int The question numbers to be added
149 * @internal param array $int The question numbers to be deleted
150 * @internal param $is_active 1: Active, 0: Inactive
151 * @internal param $is_result_public 0: Admins Only, 1: Group Members, 2: FusionForge user, 3:voted user 4:Every body
152 * @internal param \Allow $double_vote double vote if it is 1
153 * @return boolean success.
155 function update($survey_title, &$add_questions, &$del_questions, $is_active = 0, $is_public = 1, $is_result_public = 0, $double_vote = 0) {
156 if (!$survey_title) {
157 $this->setError(_('Update Failed: Survey Title Required'));
159 /* We need at least one survey question at this point */
162 $group_id = $this->Group->GetID();
163 $survey_id = $this->getID();
165 /* Ths Survey is not ready to update */
167 $this->setError(_('The Survey data is not filled'));
171 $survey_questions = $this->_updateQuestionString($add_questions, $del_questions);
172 $result = db_query_params('UPDATE surveys SET survey_title=$1, survey_questions=$2, is_active=$3 WHERE survey_id=$4 AND group_id=$5',
173 array (htmlspecialchars($survey_title),
179 if (db_affected_rows($result) < 1) {
180 $this->setError(_('Update failed').db_error());
183 /* Update internal data */
184 return $this->fetchData($survey_id);
188 * updateOrder - use this function to update question order
190 * @param int $question_number Question number
191 * @param bool $is_up decide up or down. it is up if it is true
192 * @return bool success.
194 function updateOrder($question_number, $is_up = true) {
195 $group_id = $this->Group->GetID();
196 $survey_id = $this->getID();
198 /* Ths Survey is not ready to update */
200 $this->setError(_('The Survey data is not filled'));
211 $survey_questions = $this->_updateQuestionStringOrder($question_number, $delta);
212 $result = db_query_params('UPDATE surveys SET survey_questions=$1 WHERE survey_id=$2 AND group_id=$3',
213 array ($survey_questions,
217 if (db_affected_rows($result) < 1) {
218 $this->setError(_('Update failed').db_error());
222 /* Update internal data */
223 return $this->fetchData($survey_id);
227 * delete - use this function to delete this survey
228 * (We don't support delete yet)
230 * @return boolean success.
233 $group_id = $this->Group->GetID();
234 $survey_id = $this->getID();
236 $res = db_query_params('DELETE FROM surveys where survey_id=$1 AND group_id=$2',
237 array($survey_id, $group_id)
239 if (!$res || db_affected_rows($res) < 1) {
240 $this->setError(_('Delete failed').db_error());
244 /* Delete internal data */
245 $this->data_array = null;
250 * fetchData - re-fetch the data for this survey from the database.
252 * @param int $survey_id The survey_id.
253 * @return boolean success.
255 function fetchData($survey_id) {
256 $group_id = $this->Group->GetID();
258 $res = db_query_params('SELECT * FROM surveys where survey_id=$1 AND group_id=$2',
259 array($survey_id, $group_id)) ;
261 if (!$res || db_numrows($res) < 1) {
262 $this->setError(_('No Survey is found').db_error());
265 $this->data_array = db_fetch_array($res);
266 db_free_result($res);
271 * getGroup - get the Group object this Survey is associated with.
273 * @return object The Group object.
275 function &getGroup() {
280 * getID - Get the id of this Survey
282 * @return int The question_id
285 return $this->data_array['survey_id'];
289 * isActive - return if it is active
291 * @return int is active
293 function isActive() {
294 return $this->data_array['is_active'];
298 * getTitle - Get the Survey title
300 * @return string the survey title
302 function getTitle() {
303 return $this->data_array['survey_title'];
307 * getQuestionString - Get the question string
309 * @return string the question
311 function getQuestionString() {
312 return $this->data_array['survey_questions'];
316 * getNumberOfQuestion - Get the number of questions
318 * @return int the number questions
320 function getNumberOfQuestions() {
321 return count($this->getQuestionArray());
325 * getNumberOfVotes - Get the number of votes
327 * @return int the number votes
329 function getNumberOfVotes() {
330 $group_id = $this->Group->GetID();
331 $survey_id = $this->getID();
333 $res = db_query_params ('SELECT 1 FROM survey_responses WHERE survey_id=$1 AND group_id=$2 GROUP BY user_id',
336 $ret = db_numrows($res);
337 db_free_result($res);
343 * isUserVote - Figure out the user voted or not
345 * @param int $user_id
346 * @return true or false
348 function isUserVote($user_id) {
349 $group_id = $this->Group->GetID();
350 $survey_id = $this->getID();
352 $res = db_query_params ('SELECT 1 FROM survey_responses where survey_id=$1 AND group_id=$2 AND user_id=$3',
356 $ret = db_numrows($res);
357 db_free_result($res);
363 * getQuestionArray - Get the question string numbers in array
365 * @return string the question
367 function &getQuestionArray() {
369 $questions = $this->getQuestionString();
374 $arr_from_str = explode(',', $questions);
376 /* Remove non existed questions */
377 for ($i=0; $i<count($arr_from_str); $i++) {
378 if ($this->_isValidQuestionID($arr_from_str[$i])) {
379 $ret_arr[] = $arr_from_str[$i];
387 * getQuestionInstances - Get the SurveyQuestion array belongs to this Survey by order
389 * @return string the question
391 function &getQuestionInstances() {
394 if (!$this->all_question_array || !is_array($this->all_question_array)) {
395 $this->_fillSurveyQuestions();
398 $arr = & $this->getQuestionArray();
400 for ($i=0; $i<count($arr); $i++) {
401 for ($j=0; $j<count($this->all_question_array); $j++) {
402 /* If it is, copy into new array in order */
403 if ($this->all_question_array[$j]->getID()==$arr[$i]) {
404 $ret[] = $this->all_question_array[$j];
414 * getAddableQuestionInstances - Get the addable SurveyQuestion from all questions
416 * @return string the question
418 function &getAddableQuestionInstances() {
421 if (!$this->all_question_array || !is_array($this->all_question_array)) {
422 $this->_fillSurveyQuestions();
425 $arr = & $this->getQuestionArray();
427 /* Copy questions only if it is not in question string */
428 for ($i=0; $i<count($this->all_question_array); $i++) {
429 if (array_search($this->all_question_array[$i]->getID(), $arr) == false &&
430 $this->all_question_array[$i]->getID()!=$arr[0]) {
431 $ret[] = $this->all_question_array[$i];
435 $ret = $this->all_question_array;
441 /***************************************************************
442 * private question string deal methods
443 * TODO: Add a joint table for surveys and survey_questions.
444 * Deal with DBMS not comma separated string
445 ***************************************************************/
448 * _fillSurveyQuestions - Get all Survey Questions using SurveyQuestionFactory
450 * @return boolean success
452 function _fillSurveyQuestions() {
453 $sqf = new SurveyQuestionFactory($this->getGroup());
454 $this->all_question_array = & $sqf->getSurveyQuestions();
458 * _isValidQuestionID - Check it is correct question id
460 * @param int $question_id question id
461 * @return boolean true if it is valid question id
463 function _isValidQuestionID($question_id) {
464 if (!$this->all_question_array || !is_array($this->all_question_array)) {
465 $this->_fillSurveyQuestions();
468 for ($i=0; $i<count($this->all_question_array); $i++) {
469 if ($question_id == $this->all_question_array[$i]->getID()) {
477 * _makeQuestionString - Make comma separated question number string
479 * @param int $arr array Array of question number
480 * @return string question_strong (example: 1, 2, 3, 7);
482 function _makeQuestionString($arr) {
484 /* No questions to add */
485 if (!$arr || !is_array($arr) || count($arr)<1) {
488 return join(',', $arr);
492 * _updateQuestionString - Update comma separated question number string
494 * @param int array Array of questions to add
495 * @param int array Array of questions to delete
496 * @return string question_strong (example: 1, 2, 3, 7);
498 function _updateQuestionString(&$arr_to_add, &$arr_to_del) {
499 /* Get array of current question string */
500 $arr = & $this->getQuestionArray();
502 /* questions to add */
506 if ($arr_to_add && is_array($arr_to_add) && count($arr_to_add)>0) {
507 for ($i = 0; $i < count($arr_to_add); $i++) {
508 /* Avoid double question */
509 if ($arr_to_add[$i] && array_search($arr_to_add[$i], $arr) == false && $arr_to_add[$i]!=$arr[0]) {
510 $arr[] = $arr_to_add[$i];
516 /* questions to delete */
517 if ($arr_to_del && is_array($arr_to_del) && count($arr_to_del)>0) {
519 for ($i = 0; $i < count($arr); $i++) {
520 /* If the value is no in the delete array, copy it into new array */
521 if ($arr[$i] && array_search($arr[$i], $arr_to_del)==false && $arr_to_del[0]!=$arr[$i]) {
522 $new_arr[] = $arr[$i];
525 /* copy new_arr to arr */
529 /* convert array to String */
530 return $this->_makeQuestionString($arr);
534 * _updateArrayOrder - Update array order
536 * @param int $question_number
537 * @param int $delta increment or decrement (must be 1 or -1)
538 * @return string question_strong (example: 1, 2, 3, 7);
540 function _updateQuestionStringOrder($question_number, $delta) {
541 /* Get array of current question string */
542 $arr = & $this->getQuestionArray();
544 /* We are expecting array */
545 if (!$arr || !is_array($arr)) {
546 return $this->getQuestionString();
549 $index = array_search($question_number, $arr);
551 /* The question number is not in the array
552 * We have nothing to change
554 if ($index==false && $question_number!=$arr[0]) {
555 return $this->getQuestionString();
558 $new_index = $index + $delta;
560 /* Out of boundary */
561 if ($new_index < 0 || $new_index >= count($arr)) {
562 return $this->getQuestionString();
567 $arr[$index] = $arr[$new_index];
568 $arr[$new_index] = $tmp;
570 /* convert array to String */
571 return $this->_makeQuestionString($arr);
577 // c-file-style: "bsd"