PageRenderTime 54ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/application/controllers/admin/checkintegrity.php

https://bitbucket.org/sammousa/valuematchbv-ls2
PHP | 833 lines | 661 code | 88 blank | 84 comment | 84 complexity | 8dc4ba3d11f20268a6e442f2179a163a 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. * CheckIntegrity Controller
  17. *
  18. * This controller performs database repair functions.
  19. *
  20. * @package LimeSurvey
  21. * @subpackage Backend
  22. */
  23. class CheckIntegrity extends Survey_Common_Action
  24. {
  25. public function __construct($controller, $id)
  26. {
  27. parent::__construct($controller, $id);
  28. if (Yii::app()->session['USER_RIGHT_CONFIGURATOR'] != 1) {
  29. die();
  30. }
  31. Yii::app()->loadHelper('database');
  32. Yii::app()->loadHelper('surveytranslator');
  33. }
  34. public function index()
  35. {
  36. $aData = $this->_checkintegrity();
  37. $this->_renderWrappedTemplate('checkintegrity', 'check_view', $aData);
  38. }
  39. public function fixredundancy()
  40. {
  41. $clang = Yii::app()->lang;
  42. $oldsmultidelete=Yii::app()->request->getPost('oldsmultidelete', array());
  43. $aData['messages'] = array();
  44. if (Yii::app()->session['USER_RIGHT_CONFIGURATOR'] == 1 && Yii::app()->request->getPost('ok') == 'Y') {
  45. $aDelete = $this->_checkintegrity();
  46. if (isset($aDelete['redundanttokentables'])) {
  47. foreach ($aDelete['redundanttokentables'] as $aTokenTable)
  48. {
  49. if(in_array($aTokenTable['table'],$oldsmultidelete))
  50. {
  51. Yii::app()->db->createCommand()->dropTable($aTokenTable['table']);
  52. $aData['messages'][] = sprintf($clang->gT('Deleting token table: %s'),$aTokenTable['table']);
  53. }
  54. }
  55. }
  56. if (isset($aDelete['redundantsurveytables'])) {
  57. foreach ($aDelete['redundantsurveytables'] as $aSurveyTable)
  58. {
  59. if(in_array($aSurveyTable['table'],$oldsmultidelete))
  60. {
  61. Yii::app()->db->createCommand()->dropTable($aSurveyTable['table']);
  62. $aData['messages'][] = sprintf($clang->gT('Deleting survey table: %s'),$aSurveyTable['table']);
  63. }
  64. }
  65. }
  66. if(count($aData['messages'])==0)
  67. {
  68. $aData['messages'][] = $clang->gT('No old survey or token table selected.');
  69. }
  70. $this->_renderWrappedTemplate('checkintegrity', 'fix_view', $aData);
  71. }
  72. }
  73. public function fixintegrity()
  74. {
  75. $aData = array();
  76. $clang = Yii::app()->lang;
  77. if (Yii::app()->session['USER_RIGHT_CONFIGURATOR'] == 1 && Yii::app()->request->getPost('ok') == 'Y') {
  78. $aDelete = $this->_checkintegrity();
  79. // TMSW Conditions->Relevance: Update this to process relevance instead
  80. if (isset($aDelete['conditions'])) {
  81. $aData = $this->_deleteConditions($aDelete['conditions'], $aData, $clang);
  82. }
  83. if (isset($aDelete['questionattributes'])) {
  84. $aData = $this->_deleteQuestionAttributes($aDelete['questionattributes'], $aData, $clang);
  85. }
  86. if ($aDelete['defaultvalues']) {
  87. $aData = $this->_deleteDefaultValues($aData, $clang);
  88. }
  89. if ($aDelete['quotas']) {
  90. $aData = $this->_deleteQuotas($aData, $clang);
  91. }
  92. if ($aDelete['quotals']) {
  93. $this->_deleteQuotaLanguageSettings();
  94. }
  95. if ($aDelete['quotamembers']) {
  96. $aData = $this->_deleteQuotaMembers($aData, $clang);
  97. }
  98. if (isset($aDelete['assessments'])) {
  99. $aData = $this->_deleteAssessments($aDelete['assessments'], $aData, $clang);
  100. }
  101. if (isset($aDelete['answers'])) {
  102. $aData = $this->_deleteAnswers($aDelete['answers'], $aData, $clang);
  103. }
  104. if (isset($aDelete['surveys'])) {
  105. $aData = $this->_deleteSurveys($aDelete['surveys'], $aData, $clang);
  106. }
  107. if (isset($aDelete['surveylanguagesettings'])) {
  108. $aData = $this->_deleteSurveyLanguageSettings($aDelete['surveylanguagesettings'], $aData, $clang);
  109. }
  110. if (isset($aDelete['questions'])) {
  111. $aData = $this->_deleteQuestions($aDelete['questions'], $aData, $clang);
  112. }
  113. if (isset($aDelete['groups'])) {
  114. $aData = $this->_deleteGroups($aDelete['groups'], $aData, $clang);
  115. }
  116. if (isset($aDelete['orphansurveytables'])) {
  117. $aData = $this->_dropOrphanSurveyTables($aDelete['orphansurveytables'], $aData, $clang);
  118. }
  119. if (isset($aDelete['orphantokentables'])) {
  120. $aData = $this->_deleteOrphanTokenTables($aDelete['orphantokentables'], $aData, $clang);
  121. }
  122. $this->_renderWrappedTemplate('checkintegrity', 'fix_view', $aData);
  123. }
  124. }
  125. private function _deleteOrphanTokenTables(array $tokenTables, array $aData, Limesurvey_lang $clang)
  126. {
  127. foreach ($tokenTables as $aTokenTable)
  128. {
  129. Yii::app()->db->createCommand()->dropTable($aTokenTable);
  130. $aData['messages'][] = $clang->gT('Deleting orphan token table:') . ' ' . $aTokenTable;
  131. }
  132. return $aData;
  133. }
  134. private function _dropOrphanSurveyTables(array $surveyTables, array $aData, Limesurvey_lang $clang)
  135. {
  136. foreach ($surveyTables as $aSurveyTable)
  137. {
  138. Yii::app()->db->createCommand()->dropTable($aSurveyTable);
  139. $aData['messages'][] = $clang->gT('Deleting orphan survey table:') . ' ' . $aSurveyTable;
  140. }
  141. return $aData;
  142. }
  143. private function _deleteGroups(array $groups, array $aData, Limesurvey_lang $clang)
  144. {
  145. foreach ($groups as $group) $gids[] = $group['gid'];
  146. $criteria = new CDbCriteria;
  147. $criteria->addInCondition('gid', $gids);
  148. Groups::model()->deleteAll($criteria);
  149. if (Groups::model()->hasErrors()) safeDie(Groups::model()->getError());
  150. $aData['messages'][] = sprintf($clang->gT('Deleting groups: %u groups deleted'), count($groups));
  151. return $aData;
  152. }
  153. private function _deleteQuestions(array $questions, array $aData, Limesurvey_lang $clang)
  154. {
  155. foreach ($questions as $question) $qids[] = $question['qid'];
  156. $criteria = new CDbCriteria;
  157. $criteria->addInCondition('qid', $qids);
  158. Questions::model()->deleteAll($criteria);
  159. if (Questions::model()->hasErrors()) safeDie(Questions::model()->getError());
  160. $aData['messages'][] = sprintf($clang->gT('Deleting questions: %u questions deleted'), count($questions));
  161. return array($criteria, $aData);
  162. }
  163. private function _deleteSurveyLanguageSettings(array $surveyLanguageSettings, array $aData, Limesurvey_lang $clang)
  164. {
  165. foreach ($surveyLanguageSettings as $surveylanguagesetting) $surveyls_survey_ids[] = $surveylanguagesetting['slid'];
  166. $criteria = new CDbCriteria;
  167. $criteria->compare('surveyls_survey_id', $surveyls_survey_ids);
  168. Surveys_languagesettings::model()->deleteAll($criteria);
  169. if (Surveys_languagesettings::model()->hasErrors()) safeDie(Surveys_languagesettings::model()->getError());
  170. $aData['messages'][] = sprintf($clang->gT('Deleting survey languagesettings: %u survey languagesettings deleted'), count($surveyLanguageSettings));
  171. return array($criteria, $aData);
  172. }
  173. private function _deleteSurveys(array $surveys, array $aData, Limesurvey_lang $clang)
  174. {
  175. foreach ($surveys as $survey)
  176. {
  177. Survey::model()->deleteByPk($survey['sid']);
  178. }
  179. if (Survey::model()->hasErrors()) safeDie(Survey::model()->getError());
  180. $aData['messages'][] = sprintf($clang->gT('Deleting surveys: %u surveys deleted'), count($surveys));
  181. return $aData;
  182. }
  183. private function _deleteAnswers(array $answers, array $aData, Limesurvey_lang $clang)
  184. {
  185. foreach ($answers as $aAnswer) {
  186. Answers::model()->deleteAll('qid=:qid AND code=:code',array(':qid'=>$aAnswer['qid'],':code'=>$aAnswer['code']));
  187. if (Answers::model()->hasErrors()) safeDie(Answers::model()->getError());
  188. }
  189. $aData['messages'][] = sprintf($clang->gT('Deleting answers: %u answers deleted'), count($answers));
  190. return $aData;
  191. }
  192. private function _deleteAssessments(array $assessments, array $aData, Limesurvey_lang $clang)
  193. {
  194. foreach ($assessments as $assessment) $assessments_ids[] = $assessment['id'];
  195. $assessments_ids = array();
  196. Assessment::model()->deleteByPk('id',$assessments_ids);
  197. if (Assessment::model()->hasErrors()) safeDie(Assessment::model()->getError());
  198. $aData['messages'][] = sprintf($clang->gT('Deleting assessments: %u assessment entries deleted'), count($assessments));
  199. return $aData;
  200. }
  201. private function _deleteQuotaMembers(array $aData, Limesurvey_lang $clang)
  202. {
  203. $quota_ids = array();
  204. $quotas = Quota::model()->findAll();
  205. foreach ($quotas as $quota) $quota_ids[] = $quota['id'];
  206. $criteria = new CDbCriteria;
  207. $criteria->addNotInCondition('quota_id', $quota_ids);
  208. $qids = array();
  209. $questions = Questions::model()->findAll();
  210. foreach ($questions as $question) $qids[] = $question['qid'];
  211. $criteria->addNotInCondition('qid', $qids, 'OR');
  212. $sids = array();
  213. $surveys = Survey::model()->findAll();
  214. foreach ($surveys as $survey) $sids[] = $survey['sid'];
  215. $criteria->addNotInCondition('sid', $sids, 'OR');
  216. Quota_members::model()->deleteAll($criteria);
  217. if (Quota_languagesettings::model()->hasErrors()) safeDie(Quota_languagesettings::model()->getError());
  218. $aData['messages'][] = $clang->gT('Deleting orphaned quota members.');
  219. return $aData;
  220. }
  221. private function _deleteQuotaLanguageSettings()
  222. {
  223. $quotas = Quota::model()->findAll();
  224. foreach ($quotas as $quota) $quota_ids[] = $quota['id'];
  225. $criteria = new CDbCriteria;
  226. $criteria->addNotInCondition('quotals_quota_id', $quota_ids);
  227. Quota_languagesettings::model()->deleteAll($criteria);
  228. if (Quota_languagesettings::model()->hasErrors()) safeDie(Quota_languagesettings::model()->getError());
  229. }
  230. private function _deleteQuotas(array $aData, Limesurvey_lang $clang)
  231. {
  232. $sids = array();
  233. $surveys = Survey::model()->findAll();
  234. foreach ($surveys as $survey) $sids[] = $survey['sid'];
  235. $criteria = new CDbCriteria;
  236. $criteria->addNotInCondition('sid', $sids);
  237. Quota::model()->deleteAll($criteria);
  238. if (Quota::model()->hasErrors()) safeDie(Quota::model()->getError());
  239. $aData['messages'][] = $clang->gT('Deleting orphaned quotas.');
  240. return $aData;
  241. }
  242. private function _deleteDefaultValues(array $aData, Limesurvey_lang $clang)
  243. {
  244. $qids = array();
  245. $questions = Questions::model()->findAll();
  246. foreach ($questions as $question) $qids[] = $question['qid'];
  247. $criteria = new CDbCriteria;
  248. $criteria->addNotInCondition('qid', $qids);
  249. Defaultvalues::model()->deleteAll($criteria);
  250. if (Defaultvalues::model()->hasErrors()) safeDie(Defaultvalues::model()->getError());
  251. $aData['messages'][] = $clang->gT('Deleting orphaned default values.');
  252. return $aData;
  253. }
  254. private function _deleteQuestionAttributes(array $questionAttributes, array $aData, Limesurvey_lang $clang)
  255. {
  256. $qids = array();
  257. foreach ($questionAttributes as $questionattribute) $qids[] = $questionattribute['qid'];
  258. $criteria = new CDbCriteria;
  259. $criteria->addInCondition('qid', $qids);
  260. Question_attributes::model()->deleteAll($criteria);
  261. if (Question_attributes::model()->hasErrors()) safeDie(Question_attributes::model()->getError());
  262. $aData['messages'][] = sprintf($clang->gT('Deleting question attributes: %u attributes deleted'), count($questionAttributes));
  263. return $aData;
  264. }
  265. private function _deleteConditions(array $conditions, array $aData, Limesurvey_lang $clang)
  266. {
  267. $cids = array();
  268. foreach ($conditions as $condition) $cids[] = $condition['cid'];
  269. Conditions::model()->deleteByPk($cids);
  270. if (Conditions::model()->hasErrors()) safeDie(Conditions::model()->getError());
  271. $aData['messages'][] = sprintf($clang->gT('Deleting conditions: %u conditions deleted'), count($condition));
  272. return $aData;
  273. }
  274. /**
  275. * This function checks the LimeSurvey database for logical consistency and returns an according array
  276. * containing all issues in the particular tables.
  277. * @returns Array with all found issues.
  278. */
  279. protected function _checkintegrity()
  280. {
  281. $clang = Yii::app()->lang;
  282. /*** Plainly delete survey permissions if the survey or user does not exist ***/
  283. $users = User::model()->findAll();
  284. $uids = array();
  285. foreach ($users as $user) $uids[] = $user['uid'];
  286. $criteria = new CDbCriteria;
  287. $criteria->addNotInCondition('uid', $uids, 'OR');
  288. $surveys = Survey::model()->findAll();
  289. $sids = array();
  290. foreach ($surveys as $survey) $sids[] = $survey['sid'];
  291. $criteria->addNotInCondition('sid', $sids, 'OR');
  292. Survey_permissions::model()->deleteAll($criteria);
  293. // Deactivate surveys that have a missing response table
  294. foreach ($surveys as $survey)
  295. {
  296. if ($survey['active']=='Y' && !tableExists("{{survey_{$survey['sid']}}}"))
  297. {
  298. Survey::model()->updateByPk($survey['sid'],array('active'=>'N'));
  299. }
  300. }
  301. // Fix subquestions
  302. fixSubquestions();
  303. /*** Check for active survey tables with missing survey entry and rename them ***/
  304. $sDBPrefix = Yii::app()->db->tablePrefix;
  305. $sQuery = dbSelectTablesLike('{{survey}}\_%');
  306. $aResult = dbQueryOrFalse($sQuery) or safeDie("Couldn't get list of conditions from database<br />{$sQuery}<br />");
  307. foreach ($aResult->readAll() as $aRow)
  308. {
  309. $sTableName = substr(reset($aRow), strlen($sDBPrefix));
  310. if ($sTableName == 'survey_permissions' || $sTableName == 'survey_links' || $sTableName == 'survey_url_parameters') continue;
  311. $aTableName=explode('_',$sTableName);
  312. if (isset($aTableName[1]) && ctype_digit($aTableName[1]))
  313. {
  314. $iSurveyID = $aTableName[1];
  315. if (!in_array($iSurveyID, $sids)) {
  316. $sDate = date('YmdHis') . rand(1, 1000);
  317. $sOldTable = "survey_{$iSurveyID}";
  318. $sNewTable = "old_survey_{$iSurveyID}_{$sDate}";
  319. try {
  320. $deactivateresult = Yii::app()->db->createCommand()->renameTable("{{{$sOldTable}}}", "{{{$sNewTable}}}");
  321. } catch (CDbException $e) {
  322. die ('Couldn\'t make backup of the survey table. Please try again. The database reported the following error:<br />' . htmlspecialchars($e) . '<br />');
  323. }
  324. }
  325. }
  326. }
  327. /*** Check for active token tables with missing survey entry ***/
  328. $aResult = dbQueryOrFalse(dbSelectTablesLike('{{tokens}}\_%')) or safeDie("Couldn't get list of conditions from database<br />{$sQuery}<br />");
  329. foreach ($aResult->readAll() as $aRow)
  330. {
  331. $sTableName = substr(reset($aRow), strlen($sDBPrefix));
  332. $iSurveyID = substr($sTableName, strpos($sTableName, '_') + 1);
  333. if (!in_array($iSurveyID, $sids)) {
  334. $sDate = date('YmdHis') . rand(1, 1000);
  335. $sOldTable = "tokens_{$iSurveyID}";
  336. $sNewTable = "old_tokens_{$iSurveyID}_{$sDate}";
  337. try {
  338. $deactivateresult = Yii::app()->db->createCommand()->renameTable("{{{$sOldTable}}}", "{{{$sNewTable}}}");
  339. } catch (CDbException $e) {
  340. die ('Couldn\'t make backup of the survey table. Please try again. The database reported the following error:<br />' . htmlspecialchars($e) . '<br />');
  341. }
  342. }
  343. }
  344. /**********************************************************************/
  345. /* Check conditions */
  346. /**********************************************************************/
  347. // TMSW Conditions->Relevance: Replace this with analysis of relevance
  348. $conditions = Conditions::model()->findAll();
  349. if (Conditions::model()->hasErrors()) safeDie(Conditions::model()->getError());
  350. $okQuestion = array();
  351. foreach ($conditions as $condition)
  352. {
  353. if ($condition['cqid'] != 0) { // skip case with cqid=0 for codnitions on {TOKEN:EMAIL} for instance
  354. if (!array_key_exists($condition['cqid'], $okQuestion)) {
  355. $iRowCount = Questions::model()->countByAttributes(array('qid' => $condition['cqid']));
  356. if (Questions::model()->hasErrors()) safeDie(Questions::model()->getError());
  357. if (!$iRowCount) {
  358. $aDelete['conditions'][] = array('cid' => $condition['cid'], 'reason' => $clang->gT('No matching CQID'));
  359. } else {
  360. $okQuestion[$condition['cqid']] = $condition['cqid'];
  361. }
  362. }
  363. }
  364. if ($condition['cfieldname']) //Only do this if there actually is a 'cfieldname'
  365. {
  366. if (preg_match('/^\+{0,1}[0-9]+X[0-9]+X*$/', $condition['cfieldname'])) { // only if cfieldname isn't Tag such as {TOKEN:EMAIL} or any other token
  367. list ($surveyid, $gid, $rest) = explode('X', $condition['cfieldname']);
  368. $iRowCount = count(Groups::model()->findAllByAttributes(array('gid'=>$gid)));
  369. if (Groups::model()->hasErrors()) safeDie(Groups::model()->getError());
  370. if (!$iRowCount) $aDelete['conditions'][] = array('cid' => $condition['cid'], 'reason' => $clang->gT('No matching CFIELDNAME group!') . " ($gid) ({$condition['cfieldname']})");
  371. }
  372. }
  373. elseif (!$condition['cfieldname'])
  374. {
  375. $aDelete['conditions'][] = array('cid' => $condition['cid'], 'reason' => $clang->gT('No CFIELDNAME field set!') . " ({$condition['cfieldname']})");
  376. }
  377. }
  378. /**********************************************************************/
  379. /* Check question attributes */
  380. /**********************************************************************/
  381. $question_attributes = Question_attributes::model()->findAllBySql('select qid from {{question_attributes}} where qid not in (select qid from {{questions}})');
  382. if (Question_attributes::model()->hasErrors()) safeDie(Question_attributes::model()->getError());
  383. foreach ($question_attributes as $question_attribute)
  384. {
  385. $aDelete['questionattributes'][] = array('qid' => $question_attribute['qid']);
  386. } // foreach
  387. /**********************************************************************/
  388. /* Check default values */
  389. /**********************************************************************/
  390. $questions = Questions::model()->findAll();
  391. if (Questions::model()->hasErrors()) safeDie(Questions::model()->getError());
  392. $qids = array();
  393. foreach ($questions as $question) $qids[] = $question['qid'];
  394. $criteria = new CDbCriteria;
  395. $criteria->addNotInCondition('qid', $qids);
  396. $aDelete['defaultvalues'] = count(Defaultvalues::model()->findAll($criteria));
  397. if (Defaultvalues::model()->hasErrors()) safeDie(Defaultvalues::model()->getError());
  398. /**********************************************************************/
  399. /* Check quotas */
  400. /**********************************************************************/
  401. $surveys = Survey::model()->findAll();
  402. if (Survey::model()->hasErrors()) safeDie(Survey::model()->getError());
  403. $sids = array();
  404. foreach ($surveys as $survey) $sids[] = $survey['sid'];
  405. $criteria = new CDbCriteria;
  406. $criteria->addNotInCondition('sid', $sids);
  407. $aDelete['quotas'] = count(Quota::model()->findAll($criteria));
  408. if (Quota::model()->hasErrors()) safeDie(Quota::model()->getError());
  409. /**********************************************************************/
  410. /* Check quota languagesettings */
  411. /**********************************************************************/
  412. $quotas = Quota::model()->findAll();
  413. if (Quota::model()->hasErrors()) safeDie(Quota::model()->getError());
  414. $ids = array();
  415. foreach ($quotas as $quota) $ids[] = $quota['id'];
  416. $criteria = new CDbCriteria;
  417. $criteria->addNotInCondition('quotals_quota_id', $ids);
  418. $aDelete['quotals'] = count(Quota_languagesettings::model()->findAll($criteria));
  419. if (Quota_languagesettings::model()->hasErrors()) safeDie(Quota_languagesettings::model()->getError());
  420. /**********************************************************************/
  421. /* Check quota members */
  422. /**********************************************************************/
  423. $quotas = Quota::model()->findAll();
  424. $quota_ids = array();
  425. foreach ($quotas as $quota) $quota_ids[] = $quota['id'];
  426. $criteria = new CDbCriteria;
  427. $criteria->addNotInCondition('quota_id', $quota_ids);
  428. $questions = Questions::model()->findAll();
  429. $qids = array();
  430. foreach ($questions as $question) $qids[] = $question['qid'];
  431. $criteria->addNotInCondition('qid', $qids, 'OR');
  432. $surveys = Survey::model()->findAll();
  433. $sids = array();
  434. foreach ($surveys as $survey) $sids[] = $survey['sid'];
  435. $criteria->addNotInCondition('sid', $sids, 'OR');
  436. $aDelete['quotamembers'] = count(Quota_members::model()->findAll($criteria));
  437. if (Quota_members::model()->hasErrors()) safeDie(Quota_members::model()->getError());
  438. /**********************************************************************/
  439. /* Check assessments */
  440. /**********************************************************************/
  441. $criteria = new CDbCriteria;
  442. $criteria->compare('scope', 'T');
  443. $assessments = Assessment::model()->findAll($criteria);
  444. if (Assessment::model()->hasErrors()) safeDie(Assessment::model()->getError());
  445. foreach ($assessments as $assessment)
  446. {
  447. $iAssessmentCount = count(Survey::model()->findAllByPk($assessment['sid']));
  448. if (Survey::model()->hasErrors()) safeDie(Survey::model()->getError());
  449. if (!$iAssessmentCount) {
  450. $aDelete['assessments'][] = array('id' => $assessment['id'], 'assessment' => $assessment['name'], 'reason' => $clang->gT('No matching survey'));
  451. }
  452. }
  453. $criteria = new CDbCriteria;
  454. $criteria->compare('scope', 'G');
  455. $assessments = Assessment::model()->findAll($criteria);
  456. if (Assessment::model()->hasErrors()) safeDie(Assessment::model()->getError());
  457. foreach ($assessments as $assessment)
  458. {
  459. $iAssessmentCount = count(Groups::model()->findAllByPk(array('gid'=>$assessment['gid'], 'language'=>$assessment['language'])));
  460. if (Groups::model()->hasErrors()) safeDie(Groups::model()->getError());
  461. if (!$iAssessmentCount) {
  462. $aDelete['assessments'][] = array('id' => $assessment['id'], 'assessment' => $assessment['name'], 'reason' => $clang->gT('No matching group'));
  463. }
  464. }
  465. /**********************************************************************/
  466. /* Check answers */
  467. /**********************************************************************/
  468. $answers = Answers::model()->findAll();
  469. if (Answers::model()->hasErrors()) safeDie(Answers::model()->getError());
  470. $okQuestion = array();
  471. foreach ($answers as $answer)
  472. {
  473. if (!array_key_exists($answer['qid'], $okQuestion)) {
  474. $iAnswerCount = Questions::model()->countByAttributes(array('qid' => $answer['qid']));
  475. if (Questions::model()->hasErrors()) safeDie(Questions::model()->getError());
  476. if (!$iAnswerCount) {
  477. $aDelete['answers'][] = array('qid' => $answer['qid'], 'code' => $answer['code'], 'reason' => $clang->gT('No matching question'));
  478. } else {
  479. $okQuestion[$answer['qid']] = $answer['qid'];
  480. }
  481. }
  482. }
  483. /***************************************************************************/
  484. /* Check survey languagesettings and restore them if they don't exist */
  485. /***************************************************************************/
  486. $surveys = Survey::model()->findAll();
  487. foreach ($surveys as $survey)
  488. {
  489. $aLanguages=$survey->additionalLanguages;
  490. $aLanguages[]=$survey->language;
  491. foreach ($aLanguages as $langname)
  492. {
  493. if ($langname)
  494. {
  495. $oLanguageSettings = Surveys_languagesettings::model()->find('surveyls_survey_id=:surveyid AND surveyls_language=:langname', array(':surveyid'=>$survey->sid,':langname'=>$langname));
  496. if(!$oLanguageSettings)
  497. {
  498. $oLanguageSettings= new Surveys_languagesettings;
  499. $languagedetails=getLanguageDetails($langname);
  500. $insertdata = array(
  501. 'surveyls_survey_id' => $survey->sid,
  502. 'surveyls_language' => $langname,
  503. 'surveyls_title' => '',
  504. 'surveyls_dateformat' => $languagedetails['dateformat']
  505. );
  506. foreach ($insertdata as $k => $v)
  507. $oLanguageSettings->$k = $v;
  508. $usresult=$oLanguageSettings->save();
  509. }
  510. }
  511. }
  512. }
  513. /**********************************************************************/
  514. /* Check survey language settings */
  515. /**********************************************************************/
  516. $surveys = Survey::model()->findAll();
  517. if (Survey::model()->hasErrors()) safeDie(Survey::model()->getError());
  518. $sids = array();
  519. foreach ($surveys as $survey) $sids[] = $survey['sid'];
  520. $criteria = new CDbCriteria;
  521. $criteria->addNotInCondition('surveyls_survey_id', $sids);
  522. $surveys_languagesettings = Surveys_languagesettings::model()->findAll($criteria);
  523. if (Surveys_languagesettings::model()->hasErrors()) safeDie(Surveys_languagesettings::model()->getError());
  524. foreach ($surveys_languagesettings as $surveys_languagesetting)
  525. {
  526. $aDelete['surveylanguagesettings'][] = array('slid' => $surveys_languagesetting['surveyls_survey_id'], 'reason' => $clang->gT('The related survey is missing.'));
  527. }
  528. /**********************************************************************/
  529. /* Check questions */
  530. /**********************************************************************/
  531. $questions = Questions::model()->findAll();
  532. if (Questions::model()->hasErrors()) safeDie(Questions::model()->getError());
  533. $groups = Groups::model()->findAll();
  534. if (Groups::model()->hasErrors()) safeDie(Groups::model()->getError());
  535. $gids = array();
  536. foreach ($groups as $group) $gids[] = $group['gid'];
  537. foreach ($questions as $question)
  538. {
  539. //Make sure the group exists
  540. if (!in_array($question['gid'], $gids)) {
  541. $aDelete['questions'][] = array('qid' => $question['qid'], 'reason' => $clang->gT('No matching group') . " ({$question['gid']})");
  542. }
  543. //Make sure survey exists
  544. if (!in_array($question['sid'], $sids)) {
  545. $aDelete['questions'][] = array('qid' => $question['qid'], 'reason' => $clang->gT('There is no matching survey.') . " ({$question['sid']})");
  546. }
  547. }
  548. /**********************************************************************/
  549. /* Check groups */
  550. /**********************************************************************/
  551. $surveys = Survey::model()->findAll();
  552. if (Survey::model()->hasErrors()) safeDie(Survey::model()->getError());
  553. $sids = array();
  554. foreach ($surveys as $survey) $sids[] = $survey['sid'];
  555. $criteria = new CDbCriteria;
  556. $criteria->addNotInCondition('sid', $sids);
  557. $groups = Groups::model()->findAll($criteria);
  558. foreach ($groups as $group)
  559. {
  560. $aDelete['groups'][] = array('gid' => $group['gid'], 'reason' => $clang->gT('There is no matching survey.') . ' SID:' . $group['sid']);
  561. }
  562. /**********************************************************************/
  563. /* Check old survey tables */
  564. /**********************************************************************/
  565. //1: Get list of 'old_survey' tables and extract the survey id
  566. //2: Check if that survey id still exists
  567. //3: If it doesn't offer it for deletion
  568. $sQuery = dbSelectTablesLike('{{old_survey}}%');
  569. $aResult = dbQueryOrFalse($sQuery) or safeDie("Couldn't get list of conditions from database<br />$sQuery<br />");
  570. $aTables = $aResult->readAll();
  571. $aOldSIDs = array();
  572. $aSIDs = array();
  573. foreach ($aTables as $sTable)
  574. {
  575. $sTable = reset($sTable);
  576. list($sOldText, $SurveyText, $iSurveyID, $sDate) = explode('_', substr($sTable, strlen($sDBPrefix)));
  577. $aOldSIDs[] = $iSurveyID;
  578. $aFullOldSIDs[$iSurveyID][] = $sTable;
  579. }
  580. $aOldSIDs = array_unique($aOldSIDs);
  581. //$sQuery = 'SELECT sid FROM {{surveys}} ORDER BY sid';
  582. //$oResult = dbExecuteAssoc($sQuery) or safeDie('Couldn\'t get unique survey ids');
  583. $surveys = Survey::model()->findAll();
  584. if (Survey::model()->hasErrors()) safeDie(Survey::model()->getError());
  585. $aSIDs = array();
  586. foreach ($surveys as $survey)
  587. {
  588. $aSIDs[] = $survey['sid'];
  589. }
  590. foreach ($aOldSIDs as $iOldSID)
  591. {
  592. if (!in_array($iOldSID, $aSIDs)) {
  593. foreach ($aFullOldSIDs[$iOldSID] as $sTableName)
  594. {
  595. $aDelete['orphansurveytables'][] = $sTableName;
  596. }
  597. } else {
  598. foreach ($aFullOldSIDs[$iOldSID] as $sTableName)
  599. {
  600. $aTableParts = explode('_', substr($sTableName, strlen($sDBPrefix)));
  601. if (count($aTableParts) == 4) {
  602. $sOldText = $aTableParts[0];
  603. $SurveyText = $aTableParts[1];
  604. $iSurveyID = $aTableParts[2];
  605. $sDateTime = $aTableParts[3];
  606. $sType = $clang->gT('responses');
  607. } elseif (count($aTableParts) == 5) {
  608. //This is a timings table (
  609. $sOldText = $aTableParts[0];
  610. $SurveyText = $aTableParts[1];
  611. $iSurveyID = $aTableParts[2];
  612. $sDateTime = $aTableParts[4];
  613. $sType = $clang->gT('timings');
  614. }
  615. $iYear = substr($sDateTime, 0, 4);
  616. $iMonth = substr($sDateTime, 4, 2);
  617. $iDay = substr($sDateTime, 6, 2);
  618. $iHour = substr($sDateTime, 8, 2);
  619. $iMinute = substr($sDateTime, 10, 2);
  620. $sDate = date('d M Y H:i', mktime($iHour, $iMinute, 0, $iMonth, $iDay, $iYear));
  621. $sQuery = 'SELECT count(*) as recordcount FROM ' . $sTableName;
  622. $aFirstRow = Yii::app()->db->createCommand($sQuery)->queryRow();
  623. if ($aFirstRow['recordcount']==0) { // empty table - so add it to immediate deletion
  624. $aDelete['orphansurveytables'][] = $sTableName;
  625. } else {
  626. $aOldSurveyTableAsk[] = array('table' => $sTableName, 'details' => sprintf($clang->gT('Survey ID %d saved at %s containing %d record(s) (%s)'), $iSurveyID, $sDate, $aFirstRow['recordcount'], $sType));
  627. }
  628. }
  629. }
  630. }
  631. /**********************************************************************/
  632. /* CHECK OLD TOKEN TABLES */
  633. /**********************************************************************/
  634. //1: Get list of 'old_token' tables and extract the survey id
  635. //2: Check if that survey id still exists
  636. //3: If it doesn't offer it for deletion
  637. $aResult = dbQueryOrFalse(dbSelectTablesLike('{{old_token}}%')) or safeDie("Couldn't get list of conditions from database<br />$sQuery<br />");
  638. $aTables = $aResult->readAll();
  639. $aOldTokenSIDs = array();
  640. $aTokenSIDs = array();
  641. $aFullOldTokenSIDs = array();
  642. foreach ($aTables as $sTable)
  643. {
  644. $sTable = reset($sTable);
  645. list($sOldText, $SurveyText, $iSurveyID, $sDateTime) = explode('_', substr($sTable, strlen($sDBPrefix)));
  646. $aTokenSIDs[] = $iSurveyID;
  647. $aFullOldTokenSIDs[$iSurveyID][] = $sTable;
  648. }
  649. $aOldTokenSIDs = array_unique($aTokenSIDs);
  650. $surveys = Survey::model()->findAll();
  651. if (Survey::model()->hasErrors()) safeDie(Survey::model()->getError());
  652. $aSIDs = array();
  653. foreach ($surveys as $survey)
  654. {
  655. $aSIDs[] = $survey['sid'];
  656. }
  657. foreach ($aOldTokenSIDs as $iOldTokenSID)
  658. {
  659. if (!in_array($iOldTokenSID, $aOldTokenSIDs)) {
  660. foreach ($aFullOldTokenSIDs[$iOldTokenSID] as $sTableName)
  661. {
  662. $aDelete['orphantokentables'][] = $sTableName;
  663. }
  664. } else {
  665. foreach ($aFullOldTokenSIDs[$iOldTokenSID] as $sTableName)
  666. {
  667. list($sOldText, $sTokensText, $iSurveyID, $sDateTime) = explode('_', substr($sTableName, strlen($sDBPrefix)));
  668. $iYear = substr($sDateTime, 0, 4);
  669. $iMonth = substr($sDateTime, 4, 2);
  670. $iDay = substr($sDateTime, 6, 2);
  671. $iHour = substr($sDateTime, 8, 2);
  672. $iMinute = substr($sDateTime, 10, 2);
  673. $sDate = date('D, d M Y h:i a', mktime($iHour, $iMinute, 0, $iMonth, $iDay, $iYear));
  674. $sQuery = 'SELECT count(*) as recordcount FROM ' . $sTableName;
  675. $aFirstRow = Yii::app()->db->createCommand($sQuery)->queryRow();
  676. if ($aFirstRow['recordcount']==0) { // empty table - so add it to immediate deletion
  677. $aDelete['orphantokentables'][] = $sTableName;
  678. }
  679. else
  680. {
  681. $aOldTokenTableAsk[] = array('table' => $sTableName, 'details' => sprintf($clang->gT('Survey ID %d saved at %s containing %d record(s)'), $iSurveyID, $sDate, $aFirstRow['recordcount']));
  682. }
  683. }
  684. }
  685. }
  686. if ($aDelete['defaultvalues'] == 0 && $aDelete['quotamembers'] == 0 &&
  687. $aDelete['quotas'] == 0 && $aDelete['quotals'] == 0 && count($aDelete) == 4
  688. ) {
  689. $aDelete['integrityok'] = true;
  690. } else {
  691. $aDelete['integrityok'] = false;
  692. }
  693. if (!isset($aOldTokenTableAsk) && !isset($aOldSurveyTableAsk)) {
  694. $aDelete['redundancyok'] = true;
  695. } else {
  696. $aDelete['redundancyok'] = false;
  697. $aDelete['redundanttokentables'] = array();
  698. $aDelete['redundantsurveytables'] = array();
  699. if (isset($aOldTokenTableAsk)) {
  700. $aDelete['redundanttokentables'] = $aOldTokenTableAsk;
  701. }
  702. if (isset($aOldSurveyTableAsk)) {
  703. $aDelete['redundantsurveytables'] = $aOldSurveyTableAsk;
  704. }
  705. }
  706. /**********************************************************************/
  707. /* CHECK CPDB SURVEY_LINKS TABLE FOR REDUNDENT TOKEN TABLES */
  708. /**********************************************************************/
  709. //1: Get distinct list of survey_link survey ids, check if tokens
  710. // table still exists for each one, and remove if not
  711. /* TODO */
  712. /**********************************************************************/
  713. /* CHECK CPDB SURVEY_LINKS TABLE FOR REDUNDENT TOKEN ENTRIES */
  714. /**********************************************************************/
  715. //1: For each survey_link, see if the matching entry still exists in
  716. // the token table and remove if it doesn't.
  717. /* TODO */
  718. return $aDelete;
  719. }
  720. /**
  721. * Renders template(s) wrapped in header and footer
  722. *
  723. * @param string $sAction Current action, the folder to fetch views from
  724. * @param string|array $aViewUrls View url(s)
  725. * @param array $aData Data to be passed on. Optional.
  726. */
  727. protected function _renderWrappedTemplate($sAction = 'checkintegrity', $aViewUrls = array(), $aData = array())
  728. {
  729. parent::_renderWrappedTemplate($sAction, $aViewUrls, $aData);
  730. }
  731. }