PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/application/controllers/Statistics_userController.php

https://bitbucket.org/machaven/limesurvey
PHP | 467 lines | 277 code | 73 blank | 117 comment | 31 complexity | aaedd59c02d0c31fe85e5241eeded409 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, GPL-3.0, LGPL-3.0
  1. <?php
  2. /*
  3. * LimeSurvey
  4. * Copyright (C) 2007-2011 The LimeSurvey Project Team / Carsten Schmitz
  5. * All rights reserved.
  6. * License: GNU/GPL License v2 or later, see LICENSE.php
  7. * LimeSurvey is free software. This version may have been modified pursuant
  8. * to the GNU General Public License, and as distributed it includes or
  9. * is derivative of works licensed under the GNU General Public License or
  10. * other free or open source software licenses.
  11. * See COPYRIGHT.php for copyright notices and details.
  12. *
  13. * $Id$
  14. */
  15. /*
  16. * Created 12-2008 by Maziminke (maziminke@web.de)
  17. *
  18. * This file handles the "Show results to users" option:
  19. * Survey Settings -> Presentation & navigation -> "Public statistics?"
  20. *
  21. * The admin can set a question attribute "public_statistics" for each question
  22. * to determine whether the results of a certain question should be shown to the user
  23. * after he/she has submitted the survey.
  24. *
  25. * See http://docs.limesurvey.org/tiki-index.php?page=Question+attributes#public_statistics
  26. */
  27. class Statistics_userController extends LSYii_Controller {
  28. public function _remap($method, $params = array())
  29. {
  30. array_unshift($params, $method);
  31. return call_user_func_array(array($this, "action"), $params);
  32. }
  33. function actionAction($surveyid,$language)
  34. {
  35. $iSurveyID=(int)$surveyid;
  36. //$postlang = returnglobal('lang');
  37. Yii::import('application.libraries.admin.progressbar',true);
  38. Yii::app()->loadHelper("admin/statistics");
  39. Yii::app()->loadHelper('database');
  40. Yii::app()->loadHelper('surveytranslator');
  41. $data = array();
  42. //XXX enable/disable this for testing
  43. //$publicgraphs = 1;
  44. //$showaggregateddata = 1;
  45. /*
  46. * List of important settings:
  47. * - publicstatistics: General survey setting which determines if public statistics for this survey
  48. * should be shown at all.
  49. *
  50. * - publicgraphs: General survey setting which determines if public statistics for this survey
  51. * should include graphs or only show a tabular overview.
  52. *
  53. * - public_statistics: Question attribute which has to be applied to each question so that
  54. * its statistics will be shown to the user. If not set no statistics for this question will be shown.
  55. *
  56. * - filterout_incomplete_answers: Setting taken from config-defaults.php which determines if
  57. * not completed answers will be filtered.
  58. */
  59. if(!isset($iSurveyID))
  60. {
  61. $iSurveyID=returnGlobal('sid');
  62. }
  63. else
  64. {
  65. $iSurveyID = (int) $iSurveyID;
  66. }
  67. if (!$iSurveyID)
  68. {
  69. //This next line ensures that the $iSurveyID value is never anything but a number.
  70. safeDie('You have to provide a valid survey ID.');
  71. }
  72. if ($iSurveyID)
  73. {
  74. $actresult = Survey::model()->findAll('sid = :sid AND active = :active', array(':sid' => $iSurveyID, ':active' => 'Y')); //Checked
  75. if (count($actresult) == 0)
  76. {
  77. safeDie('You have to provide a valid survey ID.');
  78. }
  79. else
  80. {
  81. $surveyinfo = getSurveyInfo($iSurveyID);
  82. // CHANGE JSW_NZ - let's get the survey title for display
  83. $thisSurveyTitle = $surveyinfo["name"];
  84. // CHANGE JSW_NZ - let's get css from individual template.css - so define path
  85. $thisSurveyCssPath = getTemplateURL($surveyinfo["template"]);
  86. if ($surveyinfo['publicstatistics']!='Y')
  87. {
  88. safeDie('The public statistics for this survey are deactivated.');
  89. }
  90. //check if graphs should be shown for this survey
  91. if ($surveyinfo['publicgraphs']=='Y')
  92. {
  93. $publicgraphs = 1;
  94. }
  95. else
  96. {
  97. $publicgraphs = 0;
  98. }
  99. }
  100. }
  101. //we collect all the output within this variable
  102. $statisticsoutput ='';
  103. //for creating graphs we need some more scripts which are included here
  104. //True -> include
  105. //False -> forget about charts
  106. if (isset($publicgraphs) && $publicgraphs == 1)
  107. {
  108. require_once(APPPATH.'third_party/pchart/pchart/pChart.class');
  109. require_once(APPPATH.'third_party/pchart/pchart/pData.class');
  110. require_once(APPPATH.'third_party/pchart/pchart/pCache.class');
  111. $MyCache = new pCache(Yii::app()->getConfig("tempdir").'/');
  112. //$currentuser is created as prefix for pchart files
  113. if (isset($_SERVER['REDIRECT_REMOTE_USER']))
  114. {
  115. $currentuser=$_SERVER['REDIRECT_REMOTE_USER'];
  116. }
  117. else if (session_id())
  118. {
  119. $currentuser=substr(session_id(), 0, 15);
  120. }
  121. else
  122. {
  123. $currentuser="standard";
  124. }
  125. }
  126. // Set language for questions and labels to base language of this survey
  127. if (isset($postlang) && $postlang != null )
  128. $language = $postlang;
  129. else
  130. $language = Survey::model()->findByPk($iSurveyID)->language;
  131. //set survey language for translations
  132. $clang = SetSurveyLanguage($iSurveyID, $language);
  133. //Create header (fixes bug #3097)
  134. $surveylanguage= $language;
  135. sendCacheHeaders();
  136. $condition = false;
  137. $header= "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
  138. . "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"".$surveylanguage."\" lang=\"".$surveylanguage."\"";
  139. if (getLanguageRTL($surveylanguage))
  140. {
  141. $condition = true;
  142. $header.=" dir=\"rtl\" ";
  143. }
  144. $sitename = Yii::app()->getConfig("sitename");
  145. $data['surveylanguage'] = $surveylanguage;
  146. $data['sitename'] = $sitename;
  147. $data['condition'] = $condition;
  148. $data['thisSurveyCssPath'] = $thisSurveyCssPath;
  149. /*
  150. * only show questions where question attribute "public_statistics" is set to "1"
  151. */
  152. $query = "SELECT q.* , group_name, group_order FROM {{questions}} q, {{groups}} g, {{question_attributes}} qa
  153. WHERE g.gid = q.gid AND g.language = :lang1 AND q.language = :lang2 AND q.sid = :surveyid AND q.qid = qa.qid AND q.parent_qid = 0 AND qa.attribute = 'public_statistics'";
  154. $databasetype = Yii::app()->db->getDriverName();
  155. if ($databasetype=='mssql' || $databasetype=="sqlsrv")
  156. {
  157. $query .=" AND CAST(CAST(qa.value as varchar) as int)='1'\n";
  158. }
  159. else
  160. {
  161. $query .=" AND qa.value='1'\n";
  162. }
  163. //execute query
  164. $result = Yii::app()->db->createCommand($query)->bindParam(":lang1", $language, PDO::PARAM_STR)->bindParam(":lang2", $language, PDO::PARAM_STR)->bindParam(":surveyid", $iSurveyID, PDO::PARAM_INT)->queryAll();
  165. //store all the data in $rows
  166. $rows = $result;
  167. //SORT IN NATURAL ORDER!
  168. usort($rows, 'groupOrderThenQuestionOrder');
  169. //put the question information into the filter array
  170. foreach ($rows as $row)
  171. {
  172. //store some column names in $filters array
  173. $filters[]=array($row['qid'],
  174. $row['gid'],
  175. $row['type'],
  176. $row['title'],
  177. $row['group_name'],
  178. flattenText($row['question']));
  179. }
  180. //number of records for this survey
  181. $totalrecords = 0;
  182. //count number of answers
  183. $query = "SELECT count(*) FROM {{survey_".intval($iSurveyID)."}}";
  184. //if incompleted answers should be filtert submitdate has to be not null
  185. //this setting is taken from config-defaults.php
  186. if (Yii::app()->getConfig("filterout_incomplete_answers") == true)
  187. {
  188. $query .= " WHERE {{survey_".intval($iSurveyID)."}}.submitdate is not null";
  189. }
  190. $result = Yii::app()->db->createCommand($query)->queryAll();
  191. //$totalrecords = total number of answers
  192. foreach($result as $row)
  193. {
  194. $totalrecords = reset($row);
  195. }
  196. //this is the array which we need later...
  197. $summary = array();
  198. //...while this is the array from copy/paste which we don't want to replace because this is a nasty source of error
  199. $allfields = array();
  200. //---------- CREATE SGQA OF ALL QUESTIONS WHICH USE "PUBLIC_STATISTICS" ----------
  201. /*
  202. * let's go through the filter array which contains
  203. * ['qid'],
  204. ['gid'],
  205. ['type'],
  206. ['title'],
  207. ['group_name'],
  208. ['question'];
  209. */
  210. $currentgroup='';
  211. // use to check if there are any question with public statistics
  212. if(isset($filters)){
  213. foreach ($filters as $flt)
  214. {
  215. //SGQ identifier
  216. $myfield = "{$iSurveyID}X{$flt[1]}X{$flt[0]}";
  217. //let's switch through the question type for each question
  218. switch ($flt[2])
  219. {
  220. case "K": // Multiple Numerical
  221. case "Q": // Multiple Short Text
  222. //get answers
  223. $query = "SELECT title as code, question as answer FROM {{questions}} WHERE parent_qid=:flt_0 AND language = :lang ORDER BY question_order";
  224. $result = Yii::app()->db->createCommand($query)->bindParam(":flt_0", $flt[0], PDO::PARAM_INT)->bindParam(":lang", $language, PDO::PARAM_STR)->queryAll();
  225. //go through all the (multiple) answers
  226. foreach($result as $row)
  227. {
  228. $myfield2=$flt[2].$myfield.reset($row);
  229. $allfields[] = $myfield2;
  230. }
  231. break;
  232. case "A": // ARRAY OF 5 POINT CHOICE QUESTIONS
  233. case "B": // ARRAY OF 10 POINT CHOICE QUESTIONS
  234. case "C": // ARRAY OF YES\No\$clang->gT("Uncertain") QUESTIONS
  235. case "E": // ARRAY OF Increase/Same/Decrease QUESTIONS
  236. case "F": // FlEXIBLE ARRAY
  237. case "H": // ARRAY (By Column)
  238. //get answers
  239. $query = "SELECT title as code, question as answer FROM {{questions}} WHERE parent_qid=:flt_0 AND language = :lang ORDER BY question_order";
  240. $result = Yii::app()->db->createCommand($query)->bindParam(":flt_0", $flt[0], PDO::PARAM_INT)->bindParam(":lang", $language, PDO::PARAM_STR)->queryAll();
  241. //go through all the (multiple) answers
  242. foreach($result as $row)
  243. {
  244. $myfield2 = $myfield.reset($row);
  245. $allfields[]=$myfield2;
  246. }
  247. break;
  248. // all "free text" types (T, U, S) get the same prefix ("T")
  249. case "T": // Long free text
  250. case "U": // Huge free text
  251. case "S": // Short free text
  252. $myfield="T$myfield";
  253. $allfields[] = $myfield;
  254. break;
  255. case ";": //ARRAY (Multi Flex) (Text)
  256. case ":": //ARRAY (Multi Flex) (Numbers)
  257. $query = "SELECT title, question FROM {{questions}} WHERE parent_qid=:flt_0 AND language=:lang AND scale_id = 0 ORDER BY question_order";
  258. $result = Yii::app()->db->createCommand($query)->bindParam(":flt_0", $flt[0], PDO::PARAM_INT)->bindParam(":lang", $language, PDO::PARAM_STR)->queryAll();
  259. foreach($result as $row)
  260. {
  261. $fquery = "SELECT * FROM {{questions}} WHERE parent_qid = :flt_0 AND language = :lang AND scale_id = 1 ORDER BY question_order, title";
  262. $fresult = Yii::app()->db->createCommand($query)->bindParam(":flt_0", $flt[0], PDO::PARAM_INT)->bindParam(":lang", $language, PDO::PARAM_STR)->queryAll();
  263. foreach($fresult as $frow)
  264. {
  265. $myfield2 = $myfield . reset($row) . "_" . $frow['title'];
  266. $allfields[]=$myfield2;
  267. }
  268. }
  269. break;
  270. case "R": //RANKING
  271. //get some answers
  272. $query = "SELECT code, answer FROM {{answers}} WHERE qid = :flt_0 AND language = :lang ORDER BY sortorder, answer";
  273. $result = Yii::app()->db->createCommand($query)->bindParam(":flt_0", $flt[0], PDO::PARAM_INT)->bindParam(":lang", $language, PDO::PARAM_STR)->queryAll();
  274. //get number of answers
  275. $count = count($result);
  276. //loop through all answers. if there are 3 items to rate there will be 3 statistics
  277. for ($i=1; $i<=$count; $i++)
  278. {
  279. $myfield2 = "R" . $myfield . $i . "-" . strlen($i);
  280. $allfields[]=$myfield2;
  281. }
  282. break;
  283. //Boilerplate questions are only used to put some text between other questions -> no analysis needed
  284. case "X": //This is a boilerplate question and it has no business in this script
  285. break;
  286. case "1": // MULTI SCALE
  287. //get answers
  288. $query = "SELECT title, question FROM {{questions}} WHERE parent_qid = :flt_0 AND language = :lang ORDER BY question_order";
  289. $result = Yii::app()->db->createCommand($query)->bindParam(":flt_0", $flt[0], PDO::PARAM_INT)->bindParam(":lang", $language, PDO::PARAM_STR)->queryAll();
  290. //loop through answers
  291. foreach($result as $row)
  292. {
  293. //----------------- LABEL 1 ---------------------
  294. $myfield2 = $myfield . $row['title']."#0";
  295. $allfields[]=$myfield2;
  296. //----------------- LABEL 2 ---------------------
  297. $myfield2 = $myfield . $row['title']."#1";
  298. $allfields[]=$myfield2;
  299. } //end WHILE -> loop through all answers
  300. break;
  301. case "P": //P - Multiple choice with comments
  302. case "M": //M - Multiple choice
  303. case "N": //N - Numerical input
  304. case "D": //D - Date
  305. $myfield2 = $flt[2].$myfield;
  306. $allfields[]=$myfield2;
  307. break;
  308. default: //Default settings
  309. $allfields[] = $myfield;
  310. break;
  311. } //end switch -> check question types and create filter forms
  312. }
  313. //end foreach -> loop through all questions with "public_statistics" enabled
  314. }// end if -> for removing the error message in case there are no filters
  315. $summary = $allfields;
  316. //---------- CREATE STATISTICS ----------
  317. //some progress bar stuff
  318. // Create progress bar which is shown while creating the results
  319. $prb = new ProgressBar();
  320. $prb->pedding = 2; // Bar Pedding
  321. $prb->brd_color = "#404040 #dfdfdf #dfdfdf #404040"; // Bar Border Color
  322. $prb->setFrame(); // set ProgressBar Frame
  323. $prb->frame['left'] = 50; // Frame position from left
  324. $prb->frame['top'] = 80; // Frame position from top
  325. $prb->addLabel('text','txt1',$clang->gT("Please wait ...")); // add Text as Label 'txt1' and value 'Please wait'
  326. $prb->addLabel('percent','pct1'); // add Percent as Label 'pct1'
  327. $prb->addButton('btn1',$clang->gT('Go back'),'?action=statistics&amp;sid='.$iSurveyID); // add Button as Label 'btn1' and action '?restart=1'
  328. //progress bar starts with 35%
  329. $process_status = 35;
  330. $prb->show(); // show the ProgressBar
  331. // 1: Get list of questions with answers chosen
  332. //"Getting Questions and Answers ..." is shown above the bar
  333. $prb->setLabelValue('txt1',$clang->gT('Getting questions and answers ...'));
  334. $prb->moveStep(5);
  335. // creates array of post variable names
  336. for (reset($_POST); $key=key($_POST); next($_POST))
  337. {
  338. $postvars[]=$key;
  339. }
  340. $data['thisSurveyTitle'] = $thisSurveyTitle;
  341. $data['totalrecords'] = $totalrecords;
  342. $data['clang'] = $clang;
  343. $data['summary'] = $summary;
  344. //show some main data at the beginnung
  345. // CHANGE JSW_NZ - let's allow html formatted questions to show
  346. //push progress bar from 35 to 40
  347. $process_status = 40;
  348. //Show Summary results
  349. if (isset($summary) && $summary)
  350. {
  351. //"Generating Summaries ..." is shown above the progress bar
  352. $prb->setLabelValue('txt1',$clang->gT('Generating summaries ...'));
  353. $prb->moveStep($process_status);
  354. //let's run through the survey // Fixed bug 3053 with array_unique
  355. $runthrough=array_unique($summary);
  356. //loop through all selected questions
  357. foreach ($runthrough as $rt)
  358. {
  359. //update progress bar
  360. if ($process_status < 100) $process_status++;
  361. $prb->moveStep($process_status);
  362. } // end foreach -> loop through all questions
  363. $helper = new statistics_helper();
  364. $statisticsoutput .= $helper->generate_statistics($iSurveyID, $summary, $summary, $publicgraphs, 'html', null,$language,false);
  365. } //end if -> show summary results
  366. $data['statisticsoutput']=$statisticsoutput;
  367. //done! set progress bar to 100%
  368. if (isset($prb))
  369. {
  370. $prb->setLabelValue('txt1',$clang->gT('Completed'));
  371. $prb->moveStep(100);
  372. $prb->hide();
  373. }
  374. // Get the survey inforamtion
  375. $thissurvey = getSurveyInfo($surveyid,$language);
  376. //SET THE TEMPLATE DIRECTORY
  377. if (!isset($thissurvey['templatedir']) || !$thissurvey['templatedir'])
  378. {
  379. $data['sTemplatePath'] = validateTemplateDir("default");
  380. }
  381. else
  382. {
  383. $data['sTemplatePath'] = validateTemplateDir($thissurvey['templatedir']);
  384. }
  385. $redata = compact(array_keys(get_defined_vars()));
  386. $data['redata'] = $redata;
  387. header_includes('statistics_user.js');
  388. $this->render('/statistics_user_view',$data);
  389. //output footer
  390. echo getFooter();
  391. //Delete all Session Data
  392. Yii::app()->session['finished'] = true;
  393. }
  394. }