diff --git a/.gitignore b/.gitignore index ff6d1c423a7..b279f5efd74 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /upload/surveys/* /styles/gringegreen/images/Thumbs.db /upload/templates/* + +/tmp/runtime/HTML \ No newline at end of file diff --git a/application/cache/.htaccess b/application/cache/.htaccess deleted file mode 100644 index 3418e55a683..00000000000 --- a/application/cache/.htaccess +++ /dev/null @@ -1 +0,0 @@ -deny from all \ No newline at end of file diff --git a/application/config/config-defaults.php b/application/config/config-defaults.php index bcb65a649f3..e3d57db5f75 100644 --- a/application/config/config-defaults.php +++ b/application/config/config-defaults.php @@ -306,15 +306,13 @@ /** * PDF Export Settings -* This feature configures PDF export for Print Answers -* The PDF export is totally experimental. The output is mostly ugly. -* At this point no support can be given - if you want to help to fix it please get in touch with us +* This feature configures PDF export for Export Answers */ -//$config['pdfdefaultfont'] = 'freemono'; //Default font for the pdf Export -//$config['pdffontsize'] = 9; //Fontsize for normal text; Surveytitle is +4; grouptitle is +2 +$config['pdfdefaultfont'] = 'freemono'; //Default font for the pdf Export +$config['pdffontsize'] = 9; //Fontsize for normal text; Surveytitle is +4; grouptitle is +2 $config['notsupportlanguages'] = array('zh-Hant-TW','zh-Hant-HK','zh-Hans','ja','th'); -//$config['pdforientation'] = 'P'; // Set L for Landscape or P for portrait format +$config['pdforientation'] = 'P'; // Set L for Landscape or P for portrait format @@ -476,13 +474,19 @@ $config['restrictToLanguages'] = ''; /** -* This parameter enables/disables the XML-RPC interface -* Set 1 to enable and 0 to disable -* @var integer +* This parameter enables/disables the RPC interface +* Set to 'json' (for JSON-RPC) )or 'xml' (for XML-RPC) to enable and 'off' to disable +* @var string */ -$config['enableXMLRPCInterface'] = 0; +$config['RPCInterface'] = 'off'; +/** +* This parameter sets the default session expiration time in seconds +* Default is 8 hours +* @var integer +*/ +$config['iSessionExpirationTime'] = 28800; // === Advanced Setup // The following parameters need information from config.php diff --git a/application/config/email.php b/application/config/email.php index 0b1da80c001..2d856c88a63 100644 --- a/application/config/email.php +++ b/application/config/email.php @@ -29,7 +29,7 @@ $config['siteadminbounce'] = 'your-email@example.net'; // The default email address used for error notification of sent messages for the site administrator (Return-Path) $config['siteadminname'] = 'Your Name'; // The name of the site administrator -$config['emailmethod'] = 'sendmail'; // The following values can be used: +$config['emailmethod'] = 'mail'; // The following values can be used: $config['protocol'] = $config['emailmethod']; // mail - use internal PHP Mailer // sendmail - use Sendmail Mailer diff --git a/application/config/tcpdf.php b/application/config/tcpdf.php index 4d5844462a9..2154ffe687f 100644 --- a/application/config/tcpdf.php +++ b/application/config/tcpdf.php @@ -75,8 +75,8 @@ * ADD TRAILING SLASH! ***********************************************************/ - $tcpdf['image_directory'] = Yii::app()->getConfig('imagedir').DIRECTORY_SEPARATOR; - + //$tcpdf['image_directory'] = Yii::app()->getConfig('imagedir').DIRECTORY_SEPARATOR; + $tcpdf['image_directory'] = Yii::app()->getConfig('rootdir').DIRECTORY_SEPARATOR.'styles'.DIRECTORY_SEPARATOR.Yii::app()->getConfig('admintheme').DIRECTORY_SEPARATOR.'images'.DIRECTORY_SEPARATOR; /************************************************************ * TCPDF default (blank) image diff --git a/application/config/version.php b/application/config/version.php index d4da23178be..6ffe725fb8e 100644 --- a/application/config/version.php +++ b/application/config/version.php @@ -12,8 +12,8 @@ * */ -$config['versionnumber'] = "2.0RC2"; -$config['dbversionnumber'] = 158; +$config['versionnumber'] = "2.0RC7"; +$config['dbversionnumber'] = 162; $config['buildnumber'] = ''; $config['updatable'] = false; diff --git a/application/controllers/AdminController.php b/application/controllers/AdminController.php index 108e80bf970..9680a2d98e9 100644 --- a/application/controllers/AdminController.php +++ b/application/controllers/AdminController.php @@ -181,7 +181,6 @@ public function getActionClasses() return array( 'assessments' => 'assessments', 'authentication' => 'authentication', - 'browse' => 'browse', 'checkintegrity' => 'checkintegrity', 'conditions' => 'conditionsaction', 'database' => 'database', @@ -202,6 +201,7 @@ public function getActionClasses() 'questiongroup' => 'questiongroup', 'quotas' => 'quotas', 'remotecontrol' => 'remotecontrol', + 'responses' => 'responses', 'saved' => 'saved', 'statistics' => 'statistics', 'survey' => 'surveyadmin', diff --git a/application/controllers/InstallerController.php b/application/controllers/InstallerController.php index f3503846ec6..14cf63a5987 100644 --- a/application/controllers/InstallerController.php +++ b/application/controllers/InstallerController.php @@ -184,7 +184,7 @@ private function stepLicense() public function stepViewLicense() { $filename = dirname(BASEPATH) . '/docs/license.txt'; - header('Content-Type: text/plain;'); + header('Content-Type: text/plain; charset=UTF-8'); readfile($filename); exit; } @@ -294,7 +294,6 @@ private function stepDatabaseConfiguration() if ($bDBExists == true) { try { $this->connection->createCommand()->select()->from('{{surveys}}')->queryAll(); - $bTablesDoNotExist = false; } catch(Exception $e) { $bTablesDoNotExist = true; } @@ -703,6 +702,22 @@ function check_HTML_image($result) return sprintf('Found', Yii::app()->baseUrl, $label[$result]); } + + function is_writable_recursive($dir) + { + $folder = opendir($dir); + while($file = readdir( $folder )) + if($file != '.' && $file != '..' && + ( !is_writable( $dir."/".$file ) || + ( is_dir( $dir."/".$file ) && !is_writable_recursive( $dir."/".$file ) ) )) + { + closedir($folder); + return false; + } + closedir($folder); + return true; + } + /** * check for a specific PHPFunction, return HTML image * @@ -727,7 +742,7 @@ function check_PHPFunction($function, &$image) * @param string $keyError key for error data * @return bool result of check (that it is writeable which implies existance) */ - function check_PathWriteable($path, $type, &$data, $base, $keyError) + function check_PathWriteable($path, $type, &$data, $base, $keyError, $bRecursive=false) { $result = false; $data[$base.'Present'] = 'Not Found'; @@ -745,7 +760,7 @@ function check_PathWriteable($path, $type, &$data, $base, $keyError) if ($exists) { $data[$base.'Present'] = 'Found'; - if (is_writable($path)) + if ((!$bRecursive && is_writable($path)) || ($bRecursive && is_writable_recursive($path))) { $data[$base.'Writable'] = 'Writable'; $result = true; @@ -783,9 +798,9 @@ function check_FileWriteable($file, &$data, $base, $keyError) * @param string $keyError key for error data * @return bool result of check (that it is writeable which implies existance) */ - function check_DirectoryWriteable($directory, &$data, $base, $keyError) + function check_DirectoryWriteable($directory, &$data, $base, $keyError, $bRecursive=false) { - return check_PathWriteable($directory, 2, $data, $base, $keyError); + return check_PathWriteable($directory, 2, $data, $base, $keyError, $bRecursive); } // version check @@ -803,11 +818,11 @@ function check_DirectoryWriteable($directory, &$data, $base, $keyError) $bProceed = false; // templates directory check - if (!check_DirectoryWriteable(Yii::app()->getConfig('rootdir').'/templates/', $data, 'templatedir', 'tperror') ) + if (!check_DirectoryWriteable(Yii::app()->getConfig('tempdir').'/', $data, 'tmpdir', 'tperror',true) ) $bProceed = false; //upload directory check - if (!check_DirectoryWriteable(Yii::app()->getConfig('rootdir').'/upload/', $data, 'uploaddir', 'uerror') ) + if (!check_DirectoryWriteable(Yii::app()->getConfig('uploaddir').'/', $data, 'uploaddir', 'uerror',true) ) $bProceed = false; // ** optional settings check ** @@ -947,6 +962,7 @@ function _writeConfigFile() ."*/" ."\n" . "return array(" . "\n" ."\t" . "'basePath' => dirname(dirname(__FILE__))," . "\n" + ."\t" . "'runtimePath' => dirname(dirname(dirname(__FILE__))).DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'runtime'," . "\n" ."\t" . "'name' => 'LimeSurvey'," . "\n" ."\t" . "'defaultController' => 'survey'," . "\n" ."\t" . "" . "\n" @@ -969,8 +985,13 @@ function _writeConfigFile() $dbdata .="\t\t\t" . "'username' => '$sDatabaseUser'," . "\n" ."\t\t\t" . "'password' => '$sDatabasePwd'," . "\n" ."\t\t\t" . "'charset' => 'utf8'," . "\n" - ."\t\t\t" . "'tablePrefix' => '$sDatabasePrefix'," . "\n" - ."\t\t" . ")," . "\n" + ."\t\t\t" . "'tablePrefix' => '$sDatabasePrefix'," . "\n"; + + if (in_array($sDatabaseType, array('mssql', 'sqlsrv'))) { + $dbdata .="\t\t\t" ."'initSQLs'=>array('SET DATEFORMAT ymd;','SET QUOTED_IDENTIFIER ON;')," . "\n"; + } + + $dbdata .="\t\t" . ")," . "\n" ."\t\t" . "" . "\n" ."\t\t" . "// Uncomment the following line if you need table-based sessions". "\n" diff --git a/application/controllers/OptinController.php b/application/controllers/OptinController.php index f9fbe1c15ec..b9d2a8fb89d 100644 --- a/application/controllers/OptinController.php +++ b/application/controllers/OptinController.php @@ -93,7 +93,7 @@ function actionLocal($surveyid, $token, $langcode = '') //PRINT COMPLETED PAGE if (!$thissurvey['templatedir']) { - $thistpl=getTemplatePath($defaulttemplate); + $thistpl=getTemplatePath(Yii::app()->getConfig("defaulttemplate")); } else { diff --git a/application/controllers/OptoutController.php b/application/controllers/OptoutController.php index e63873edc20..e466fc6a9e6 100644 --- a/application/controllers/OptoutController.php +++ b/application/controllers/OptoutController.php @@ -23,22 +23,32 @@ */ class OptoutController extends LSYii_Controller { - function actionLocal($surveyid, $token, $langcode = '') + /* This function is run when opting out of an individual token table. The other function /optout/participants + * opts the user out of ALL survey invitations from the system + * + * + * */ + function actiontokens() { + $surveyid=Yii::app()->request->getQuery('surveyid'); + $langcode=Yii::app()->request->getQuery('langcode'); + $token=Yii::app()->request->getQuery('token'); + Yii::app()->loadHelper('database'); Yii::app()->loadHelper('sanitize'); $sLanguageCode = $langcode; + $iSurveyID = $surveyid; $sToken = $token; $sToken = sanitize_token($sToken); - if (!$iSurveyID) + if (!$iSurveyID) //IF there is no survey id, redirect back to the default public page { - $this->redirect($this->getController()->createUrl('/')); + $this->redirect(Yii::app()->getController()->createUrl('/')); } - $iSurveyID = (int)$iSurveyID; + $iSurveyID = (int)$iSurveyID; //Make sure it's an integer (protect from SQL injects) //Check that there is a SID - // Get passed language from form, so that we dont loose this! + // Get passed language from form, so that we dont lose this! if (!isset($sLanguageCode) || $sLanguageCode == "" || !$sLanguageCode) { $baselang = Survey::model()->findByPk($iSurveyID)->language; @@ -86,7 +96,107 @@ function actionLocal($surveyid, $token, $langcode = '') //PRINT COMPLETED PAGE if (!$thissurvey['templatedir']) { - $thistpl=getTemplatePath($defaulttemplate); + $thistpl=getTemplatePath(Yii::app()->getConfig("defaulttemplate")); + } + else + { + $thistpl=getTemplatePath($thissurvey['templatedir']); + } + + $this->_renderHtml($html,$thistpl); + } + + /* This function is run when opting out of the participants system. The other function /optout/token + * opts the user out of just a single token/survey invite list + * + * + * */ + function actionparticipants() + { + $surveyid=Yii::app()->request->getQuery('surveyid'); + $langcode=Yii::app()->request->getQuery('langcode'); + $token=Yii::app()->request->getQuery('token'); + + Yii::app()->loadHelper('database'); + Yii::app()->loadHelper('sanitize'); + $sLanguageCode = $langcode; + + $iSurveyID = $surveyid; + $sToken = $token; + $sToken = sanitize_token($sToken); + + if (!$iSurveyID) //IF there is no survey id, redirect back to the default public page + { + $this->redirect(Yii::app()->getController()->createUrl('/')); + } + $iSurveyID = (int)$iSurveyID; //Make sure it's an integer (protect from SQL injects) + //Check that there is a SID + // Get passed language from form, so that we dont lose this! + if (!isset($sLanguageCode) || $sLanguageCode == "" || !$sLanguageCode) + { + $baselang = Survey::model()->findByPk($iSurveyID)->language; + Yii::import('application.libraries.Limesurvey_lang', true); + $clang = new Limesurvey_lang($baselang); + } + else + { + $sLanguageCode = sanitize_languagecode($sLanguageCode); + Yii::import('application.libraries.Limesurvey_lang', true); + $clang = new Limesurvey_lang($sLanguageCode); + $baselang = $sLanguageCode; + } + + Yii::app()->lang = $clang; + + $thissurvey=getSurveyInfo($iSurveyID,$baselang); + + if ($thissurvey==false || !tableExists("{{tokens_{$iSurveyID}}}")){ + $html = $clang->gT('This survey does not seem to exist.'); + } + else + { + $row = Tokens_dynamic::getEmailStatus($iSurveyID, $sToken); + $datas = Tokens_dynamic::model($iSurveyID)->find('token = :token', array(":token"=>$sToken)); + + if ($row == false) + { + $html = $clang->gT('You are not a participant in this survey.'); + } + else + { + $usresult = $row['emailstatus']; + if ($usresult == 'OK') + { + $usresult = Tokens_dynamic::updateEmailStatus($iSurveyID, $sToken, 'OptOut'); + $html = $clang->gT('You have been successfully removed from this survey.'); + } + else + { + $html = $clang->gT('You have been already removed from this survey.'); + } + if(!empty($datas->participant_id) && $datas->participant_id != "") + { + //Participant also exists in central db + $cpdb = Participants::model()->find('participant_id = :participant_id', array(":participant_id"=>$datas->participant_id)); + if($cpdb->blacklisted=="Y") + { + $html .= "
"; + $html .= $clang->gt("You have already been removed from the central participants list for this site"); + } else + { + $cpdb->blacklisted='Y'; + $cpdb->save(); + $html .= "
"; + $html .= $clang->gT("You have been removed from the central participants list for this site"); + } + } + } + } + + //PRINT COMPLETED PAGE + if (!$thissurvey['templatedir']) + { + $thistpl=getTemplatePath(Yii::app()->getConfig("defaulttemplate")); } else { diff --git a/application/controllers/RegisterController.php b/application/controllers/RegisterController.php index 0dad4b36045..f54e5e1e2a6 100644 --- a/application/controllers/RegisterController.php +++ b/application/controllers/RegisterController.php @@ -29,9 +29,9 @@ function actionAJAXRegisterForm Yii::app()->loadHelper('database'); Yii::app()->loadHelper('replacements'); $redata = compact(array_keys(get_defined_vars())); - $thistpl = Yii::app()->getConfig("standardtemplaterootdir").'/default'; $surveyid = sanitize_int($surveyid); $row = Survey::model()->find('sid=:sid',array(':sid' => $surveyid)) or show_error("Can't find survey data"); + $thistpl=getTemplatePath(validateTemplateDir($row->template)); $data['sid'] = $surveyid; $data['startdate'] = $row->startdate; $data['enddate'] = $row->expires; diff --git a/application/controllers/admin/assessments.php b/application/controllers/admin/assessments.php index 40a584c2039..f8b9f3239c9 100644 --- a/application/controllers/admin/assessments.php +++ b/application/controllers/admin/assessments.php @@ -116,7 +116,7 @@ private function _showAssessments($iSurveyID, $action, $surveyLanguage, Limesurv private function _collectGroupData($iSurveyID) { - $aData = array(); + $aData = array(); $groups = Groups::model()->findAllByAttributes(array('sid' => $iSurveyID)); foreach ($groups as $group) { $groupId = $group->attributes['gid']; @@ -156,7 +156,7 @@ private function _add($iSurveyID) if ($first == false) { $aData['id'] = $assessmentId; } - $assessment = Assessment::insertRecords($aData); + $assessment = Assessment::model()->insertRecords($aData); if ($first == true) { $first = false; $assessmentId = $assessment->id; @@ -177,7 +177,7 @@ private function _update($iSurveyID) foreach ($languages as $language) { $aData = $this->_getAssessmentPostData($iSurveyID, $language); - Assessment::updateAssessment($aid, $language, $aData); + Assessment::model()->updateAssessment($aid, $language, $aData); } } } diff --git a/application/controllers/admin/authentication.php b/application/controllers/admin/authentication.php index 14d1edf9c52..f67a5737800 100644 --- a/application/controllers/admin/authentication.php +++ b/application/controllers/admin/authentication.php @@ -33,8 +33,7 @@ class Authentication extends Survey_Common_Action public function index() { $this->_redirectIfLoggedIn(); - $sIp = Yii::app()->request->getUserHostAddress(); - $bCanLogin = $this->_userCanLogin($sIp); + $bCanLogin = $this->_userCanLogin(); if ($bCanLogin && !is_array($bCanLogin)) { @@ -44,7 +43,7 @@ public function index() if (!isset($aData['errormsg'])) { - Failed_login_attempts::model()->deleteAttempts($sIp); + Failed_login_attempts::model()->deleteAttempts(); $this->getController()->_GetSessionUserRights(Yii::app()->session['loginID']); Yii::app()->session['just_logged_in'] = true; @@ -209,20 +208,14 @@ private function _redirectIfLoggedIn() /** * Check if a user can log in - * @param string $sIp IP Address * @return bool|array */ - private function _userCanLogin($sIp = '') + private function _userCanLogin() { - if (empty($sIp)) - { - $sIp = Yii::app()->request->getUserHostAddress(); - } - $failed_login_attempts = Failed_login_attempts::model(); $failed_login_attempts->cleanOutOldAttempts(); - if ($failed_login_attempts->isLockedOut($sIp)) + if ($failed_login_attempts->isLockedOut()) { return $this->_getAuthenticationFailedErrorMessage(); } diff --git a/application/controllers/admin/checkintegrity.php b/application/controllers/admin/checkintegrity.php index 32b65bb27fd..78297ff4ba9 100644 --- a/application/controllers/admin/checkintegrity.php +++ b/application/controllers/admin/checkintegrity.php @@ -194,9 +194,11 @@ private function _deleteSurveyLanguageSettings(array $surveyLanguageSettings, ar private function _deleteSurveys(array $surveys, array $aData, Limesurvey_lang $clang) { - foreach ($surveys as $survey) $surveys_ids[] = $survey['sid']; + foreach ($surveys as $survey) + { + Survey::model()->deleteByPk($survey['sid']); + } - Survey::model()->deleteByPk('sid',$surveys_ids); if (Survey::model()->hasErrors()) safeDie(Survey::model()->getError()); $aData['messages'][] = sprintf($clang->gT('Deleting surveys: %u surveys deleted'), count($surveys)); return $aData; diff --git a/application/controllers/admin/conditionsaction.php b/application/controllers/admin/conditionsaction.php index 66e0a62e1e0..1bd97753871 100644 --- a/application/controllers/admin/conditionsaction.php +++ b/application/controllers/admin/conditionsaction.php @@ -792,18 +792,18 @@ function index($subaction, $surveyid=null, $gid=null, $qid=null) $x_axis[$frow['title']]=$frow['question']; } - foreach ($y_axis_db->readAll() as $arow) + foreach ($y_axis_db->readAll() as $yrow) { foreach($x_axis as $key=>$val) { - $shortquestion=$rows['title'].":{$arows['title']}:$key: [".strip_tags($arows['question']). "][" .strip_tags($val). "] " . flattenText($rows['question']); - $cquestions[]=array($shortquestion, $rows['qid'], $rows['type'], $rows['sid'].$X.$rows['gid'].$X.$rows['qid'].$arows['title']."_".$key); + $shortquestion=$rows['title'].":{$yrow['title']}:$key: [".strip_tags($yrow['question']). "][" .strip_tags($val). "] " . flattenText($rows['question']); + $cquestions[]=array($shortquestion, $rows['qid'], $rows['type'], $rows['sid'].$X.$rows['gid'].$X.$rows['qid'].$yrow['title']."_".$key); if ($rows['type'] == ":") { for($ii=$minvalue; $ii<=$maxvalue; $ii+=$stepvalue) { - $canswers[]=array($rows['sid'].$X.$rows['gid'].$X.$rows['qid'].$arows['title']."_".$key, $ii, $ii); + $canswers[]=array($rows['sid'].$X.$rows['gid'].$X.$rows['qid'].$yrow['title']."_".$key, $ii, $ii); } } } @@ -1260,7 +1260,7 @@ function index($subaction, $surveyid=null, $gid=null, $qid=null) ."AND c.qid=:qid " ."AND c.scenario=:scenario " ."AND c.cfieldname NOT LIKE '{%' " // avoid catching SRCtokenAttr conditions - ."ORDER BY g.group_order, q.question_order"; + ."ORDER BY g.group_order, q.question_order, c.cfieldname"; $sLanguage=Survey::model()->findByPk($surveyid)->language; $result=Yii::app()->db->createCommand($query) ->bindValue(":scenario", $scenarionr['scenario']) diff --git a/application/controllers/admin/database.php b/application/controllers/admin/database.php index 0c19739405f..c07ee976f86 100644 --- a/application/controllers/admin/database.php +++ b/application/controllers/admin/database.php @@ -64,11 +64,7 @@ function index($sa = null) $baselang = Survey::model()->findByPk($surveyid)->language; array_unshift($questlangs,$baselang); - $uqresult = Questions::model()->updateAll(array('same_default'=> Yii::app()->request->getPost('samedefault')?1:0), 'sid=:sid ANd qid=:qid', array(':sid'=>$surveyid, ':qid'=>$qid)); - if (!$uqresult) - { - $databaseoutput .= "\n"; - } + Questions::model()->updateAll(array('same_default'=> Yii::app()->request->getPost('samedefault')?1:0), 'sid=:sid ANd qid=:qid', array(':sid'=>$surveyid, ':qid'=>$qid)); $resrow = Questions::model()->with('question_types')->findByAttributes(array('qid'=>$qid)); $q = createQuestion($resrow->question_types['class']); @@ -115,9 +111,9 @@ function index($sa = null) { foreach ($questlangs as $language) { - if (Yii::app()->request->getPost($_POST['defaultanswerscale_0_'.$language.'_0'])) + if (Yii::app()->request->getPost('defaultanswerscale_0_'.$language.'_0')) { - $this->_updateDefaultValues($postqid,0,0,'',$language,Yii::app()->request->getPost['defaultanswerscale_0_'.$language.'_0'],true); + $this->_updateDefaultValues($postqid,0,0,'',$language,Yii::app()->request->getPost('defaultanswerscale_0_'.$language.'_0'),true); } } } @@ -480,7 +476,7 @@ function index($sa = null) if (returnGlobal('copysubquestions') == "Y") { $aSQIDMappings = array(); - $r1 = Questions::getSubQuestions(returnGlobal('oldqid')); + $r1 = Questions::model()->getSubQuestions(returnGlobal('oldqid')); while ($qr1 = $r1->read()) { @@ -493,19 +489,19 @@ function index($sa = null) unset($qr1['qid']); } $qr1['gid'] = $postgid; - $ir1 = Questions::insertRecords($qr1); + $iInsertID = Questions::model()->insertRecords($qr1); if (!isset($qr1['qid'])) { - $aSQIDMappings[$oldqid] = Yii::app()->db->getLastInsertID('qid'); + $aSQIDMappings[$oldqid] = $iInsertID; } } } if (returnGlobal('copyanswers') == "Y") { - $r1 = Answers::getAnswers(returnGlobal('oldqid')); + $r1 = Answers::model()->getAnswers(returnGlobal('oldqid')); while ($qr1 = $r1->read()) { - Answers::insertRecords(array( + Answers::model()->insertRecords(array( 'qid' => $qid, 'code' => $qr1['code'], 'answer' => $qr1['answer'], @@ -517,14 +513,12 @@ function index($sa = null) } if (returnGlobal('copyattributes') == "Y") { - $r1 = Question_attributes::getQuestionAttributes(returnGlobal('oldqid')); + $r1 = Question_attributes::model()->getQuestionAttributes(returnGlobal('oldqid')); while($qr1 = $r1->read()) { - Question_attributes::insertRecords(array( - 'qid' => $qid, - 'attribute' => $qr1['attribute'], - 'value' => $qr1['value'] - )); + $qr1['qid']=$qid; + unset($qr1['qaid']); + Question_attributes::model()->insertRecords($qr1); } } } else { @@ -539,7 +533,7 @@ function index($sa = null) 'attribute' => $validAttribute ); - Question_attributes::insertRecords($data); + Question_attributes::model()->insertRecords($data); } } @@ -633,7 +627,7 @@ function index($sa = null) $result = Question_attributes::model()->findAllByAttributes(array('attribute'=>$validAttribute['name'], 'qid'=>$qid)); if (count($result)>0) { - if($value!=$validAttribute['default']) + if($value!=$validAttribute['default'] && trim($value)!="") { Question_attributes::model()->updateAll(array('value'=>$value),'attribute=:attribute AND qid=:qid', array(':attribute'=>$validAttribute['name'], ':qid'=>$qid)); } @@ -642,7 +636,7 @@ function index($sa = null) Question_attributes::model()->deleteAll('attribute=:attribute AND qid=:qid', array(':attribute'=>$validAttribute['name'], ':qid'=>$qid)); } } - elseif($value!=$validAttribute['default']) + elseif($value!=$validAttribute['default'] && trim($value)!="") { $attribute = new Question_attributes; $attribute->qid = $qid; @@ -784,7 +778,7 @@ function index($sa = null) // Update the group ID on subquestions, too if ($oldgid!=$gid) { - Questions::model()->updateAll(array('gid'=>$gid), 'qid=:qid and parent_qid>0', array(':qid'=>$oldqid)); + Questions::model()->updateAll(array('gid'=>$gid), 'qid=:qid and parent_qid>0', array(':qid'=>$qid)); // if the group has changed then fix the sortorder of old and new group fixSortOrderQuestions($oldgid, $surveyid); fixSortOrderQuestions($gid, $surveyid); @@ -850,7 +844,11 @@ function index($sa = null) } else { - $this->getController()->redirect($this->getController()->createUrl('admin/survey/view/surveyid/'.$surveyid.'/gid/'.$gid.'/qid/'.$qid)); + if(Yii::app()->request->getPost('newpage') == "return") { + $this->getController()->redirect($this->getController()->createUrl('admin/question/editquestion/surveyid/'.$surveyid.'/gid/'.$gid.'/qid/'.$qid)); + } else { + $this->getController()->redirect($this->getController()->createUrl('admin/survey/view/surveyid/'.$surveyid.'/gid/'.$gid.'/qid/'.$qid)); + } } } @@ -1069,42 +1067,19 @@ function index($sa = null) $usresult = Surveys_languagesettings::model()->findAllByPk(array('surveyls_survey_id'=>$surveyid, 'surveyls_language'=>$langname)); if (count($usresult)==0) { - $bplang = $this->getController()->lang; - $aDefaultTexts=templateDefaultTexts($bplang,'unescaped'); - if (getEmailFormat($surveyid) == "html") - { - $ishtml=true; - $aDefaultTexts['admin_detailed_notification']=$aDefaultTexts['admin_detailed_notification_css'].$aDefaultTexts['admin_detailed_notification']; - } - else - { - $ishtml=false; - } + $languagedetails=getLanguageDetails($langname); $insertdata = array( 'surveyls_survey_id' => $surveyid, 'surveyls_language' => $langname, 'surveyls_title' => '', - 'surveyls_email_invite_subj' => $aDefaultTexts['invitation_subject'], - 'surveyls_email_invite' => $aDefaultTexts['invitation'], - 'surveyls_email_remind_subj' => $aDefaultTexts['reminder_subject'], - 'surveyls_email_remind' => $aDefaultTexts['reminder'], - 'surveyls_email_confirm_subj' => $aDefaultTexts['confirmation_subject'], - 'surveyls_email_confirm' => $aDefaultTexts['confirmation'], - 'surveyls_email_register_subj' => $aDefaultTexts['registration_subject'], - 'surveyls_email_register' => $aDefaultTexts['registration'], - 'email_admin_notification_subj' => $aDefaultTexts['admin_notification_subject'], - 'email_admin_notification' => $aDefaultTexts['admin_notification'], - 'email_admin_responses_subj' => $aDefaultTexts['admin_detailed_notification_subject'], - 'email_admin_responses' => $aDefaultTexts['admin_detailed_notification'], 'surveyls_dateformat' => $languagedetails['dateformat'] ); $setting= new Surveys_languagesettings; foreach ($insertdata as $k => $v) $setting->$k = $v; $setting->save(); - unset($bplang); } } } @@ -1153,24 +1128,18 @@ function index($sa = null) */ function _updateDefaultValues($qid,$sqid,$scale_id,$specialtype,$language,$defaultvalue,$ispost) { - //$this->load->helper('database'); if ($defaultvalue=='') // Remove the default value if it is empty { Defaultvalues::model()->deleteByPk(array('sqid'=>$sqid, 'qid'=>$qid, 'specialtype'=>$specialtype, 'scale_id'=>$scale_id, 'language'=>$language)); } else { - $res = Defaultvalues::model()->findByPk(array('sqid'=>$sqid, 'qid'=>$qid, 'specialtype'=>$specialtype, 'scale_id'=>$scale_id, 'language'=>$language)); - $exists=count($res); + $arDefaultValue = Defaultvalues::model()->findByPk(array('sqid'=>$sqid, 'qid'=>$qid, 'specialtype'=>$specialtype, 'scale_id'=>$scale_id, 'language'=>$language)); - if ($exists == 0) + if (is_null($arDefaultValue)) { $data=array('sqid'=>$sqid, 'qid'=>$qid, 'specialtype'=>$specialtype, 'scale_id'=>$scale_id, 'language'=>$language, 'defaultvalue'=>$defaultvalue); - - $value = new Defaultvalues; - foreach ($data as $k => $v) - $value->$k = $v; - $value->save(); + Defaultvalues::model()->insertRecords($data); } else { diff --git a/application/controllers/admin/dataentry.php b/application/controllers/admin/dataentry.php index e954233eaaa..21d318af6ea 100644 --- a/application/controllers/admin/dataentry.php +++ b/application/controllers/admin/dataentry.php @@ -98,7 +98,7 @@ function vvimport() } } } - + function iteratesurvey() { $aData = array(); @@ -462,7 +462,7 @@ function import($surveyid) } Yii::app()->session['flashmessage'] = sprintf($clang->gT("%s old response(s) and according timings were successfully imported."),$iRecordCount,$iRecordCountT); } - $this->getController()->redirect(Yii::app()->getController()->createUrl("/admin/browse/index/surveyid/{$surveyid}")); + $this->getController()->redirect(Yii::app()->getController()->createUrl("/admin/responses/index/surveyid/{$surveyid}")); } } } @@ -707,19 +707,21 @@ public function editdata($subaction, $id, $surveyid, $language='') */ public function delete() { - $subaction = Yii::app()->request->getPost('subaction'); - $surveyid = $_REQUEST['surveyid']; + if (isset($_REQUEST['surveyid']) && !empty($_REQUEST['surveyid'])) + { + $surveyid = $_REQUEST['surveyid']; + } if (!empty($_REQUEST['sid'])) $surveyid = (int)$_REQUEST['sid']; $surveyid = sanitize_int($surveyid); - $id = Yii::app()->request->getPost('id'); + $id = $_REQUEST['id']; $aData = array( 'surveyid' => $surveyid, 'id' => $id ); - if (hasSurveyPermission($surveyid, 'responses','read') && $subaction == "delete" && hasSurveyPermission($surveyid, 'responses', 'delete')) + if (hasSurveyPermission($surveyid, 'responses','read') && hasSurveyPermission($surveyid, 'responses', 'delete')) { $surveytable = "{{survey_".$surveyid.'}}'; $aData['thissurvey'] = getSurveyInfo($surveyid); @@ -811,8 +813,8 @@ public function update() ob_end_flush(); } - $onerecord_link = $this->getController()->createUrl('/').'/admin/browse/index/surveyid/'.$surveyid.'/id/'.$id; - $allrecords_link = $this->getController()->createUrl('/').'/admin/browse/index/surveyid/'.$surveyid.'/all'; + $onerecord_link = $this->getController()->createUrl('/').'/admin/responses/index/surveyid/'.$surveyid.'/id/'.$id; + $allrecords_link = $this->getController()->createUrl('/').'/admin/responses/index/surveyid/'.$surveyid.'/all'; $aDataentryoutput .= "
".$clang->gT("Success")."
\n" .$clang->gT("Record has been updated.")."

\n" ."

\n" @@ -1238,7 +1240,7 @@ public function view($surveyid, $lang=NULL) // Perform a case insensitive natural sort on group name then question title of a multidimensional array usort($deqrows, 'groupOrderThenQuestionOrder'); - + $bgc = 'odd'; foreach ($deqrows as $deqrow) { $qidattributes = getQuestionAttributeValues($deqrow['qid'], $deqrow['type']); @@ -1574,6 +1576,8 @@ public function view($surveyid, $lang=NULL) break; case ":": //ARRAY (Multi Flexi) // $qidattributes=getQuestionAttributeValues($deqrow['qid']); + $minvalue=1; + $maxvalue=10; if (trim($qidattributes['multiflexible_max'])!='' && trim($qidattributes['multiflexible_min']) =='') { $maxvalue=$qidattributes['multiflexible_max']; $minvalue=1; @@ -1582,10 +1586,6 @@ public function view($surveyid, $lang=NULL) $minvalue=$qidattributes['multiflexible_min']; $maxvalue=$qidattributes['multiflexible_min'] + 10; } - if (trim($qidattributes['multiflexible_min'])=='' && trim($qidattributes['multiflexible_max']) =='') { - $minvalue=1; - $maxvalue=10; - } if (trim($qidattributes['multiflexible_min']) !='' && trim($qidattributes['multiflexible_max']) !='') { if($qidattributes['multiflexible_min'] < $qidattributes['multiflexible_max']){ $minvalue=$qidattributes['multiflexible_min']; diff --git a/application/controllers/admin/export.php b/application/controllers/admin/export.php index 1087738f672..70864fb219c 100644 --- a/application/controllers/admin/export.php +++ b/application/controllers/admin/export.php @@ -188,14 +188,10 @@ public function exportresults() if ( ! $exportstyle ) { //FIND OUT HOW MANY FIELDS WILL BE NEEDED - FOR 255 COLUMN LIMIT - $excesscols = createFieldMap($iSurveyID,'full',false,false,getBaseLanguageFromSurveyID($iSurveyID)); //AJS# - $excesscols = array_keys($excesscols); + $aFieldMap = createFieldMap($iSurveyID,'full',false,false,getBaseLanguageFromSurveyID($iSurveyID)); //AJS# + $iFieldCount = count($aFieldMap); - $afieldcount = count($excesscols); - - $this->getController()->_getAdminHeader(); - - $selecthide = "'"; + $selecthide = ""; $selectshow = ""; $selectinc = ""; if ( incompleteAnsFilterState() == "filter" ) @@ -214,8 +210,8 @@ public function exportresults() $data['selecthide'] = $selecthide; $data['selectshow'] = $selectshow; $data['selectinc'] = $selectinc; - $data['afieldcount'] = $afieldcount; - $data['excesscols'] = $excesscols; + $data['afieldcount'] = $iFieldCount; + $data['excesscols'] = $aFieldMap; //get max number of datasets $max_datasets_query = Yii::app()->db->createCommand("SELECT COUNT(id) AS count FROM {{survey_".intval($iSurveyID)."}}")->query()->read(); @@ -274,7 +270,7 @@ public function exportresults() $_POST['attribute_select'] = array(); } - $options->responseCompletionState = 'show'; + $options->responseCompletionState = 'all'; $dquery = ''; if ( in_array('first_name', Yii::app()->request->getPost('attribute_select')) ) @@ -308,11 +304,6 @@ public function exportresults() } } - if ( $options->responseCompletionState == 'inc' ) - { - $options->responseCompletionState = 'incomplete'; - } - $resultsService = new ExportSurveyResultsService(); $resultsService->exportSurvey($iSurveyID, $explang, $options); @@ -1090,12 +1081,12 @@ public function resources() switch ( Yii::app()->request->getParam('export') ) { case 'survey' : - $iSurveyID = sanitize_int(CHttpRequest::getParam('surveyid')); + $iSurveyID = sanitize_int(Yii::app()->getRequest()->getParam('surveyid')); $resourcesdir = 'surveys/' . $iSurveyID; $zipfilename = "resources-survey-$iSurveyID.zip"; break; case 'label' : - $lid = sanitize_int(CHttpRequest::getParam('lid')); + $lid = sanitize_int(Yii::app()->getRequest()->getParam('lid')); $resourcesdir = 'labels/' . $lid; $zipfilename = "resources-labelset-$lid.zip"; break; diff --git a/application/controllers/admin/expressions.php b/application/controllers/admin/expressions.php index af8ff519a8a..2c82f101ef9 100644 --- a/application/controllers/admin/expressions.php +++ b/application/controllers/admin/expressions.php @@ -24,16 +24,7 @@ function index() - + " /> _printOnLoad(Yii::app()->request->getQuery('sa', 'index'))?>> loadHelper('surveytranslator'); //save refurl from where global settings screen is called! - $refurl = CHttpRequest::getUrlReferrer(); + $refurl = Yii::app()->getRequest()->getUrlReferrer(); Yii::app()->session['refurl'] = htmlspecialchars($refurl); //just to be safe! $data['clang'] = $this->getController()->lang; @@ -154,16 +154,16 @@ private function _saveSettings() setGlobalSetting('repeatheadings', $repeatheadingstemp); setGlobalSetting('maxemails', sanitize_int($maxemails)); - $iSessionExpirationTime = (int)($_POST['sess_expiration']); + $iSessionExpirationTime = (int)($_POST['iSessionExpirationTime']); if ($iSessionExpirationTime == 0) $iSessionExpirationTime = 3600; - setGlobalSetting('sess_expiration', $iSessionExpirationTime); + setGlobalSetting('iSessionExpirationTime', $iSessionExpirationTime); setGlobalSetting('ipInfoDbAPIKey', $_POST['ipInfoDbAPIKey']); setGlobalSetting('googleMapsAPIKey', $_POST['googleMapsAPIKey']); setGlobalSetting('googleanalyticsapikey',$_POST['googleanalyticsapikey']); setGlobalSetting('googletranslateapikey',$_POST['googletranslateapikey']); setGlobalSetting('force_ssl', $_POST['force_ssl']); setGlobalSetting('surveyPreview_require_Auth', $_POST['surveyPreview_require_Auth']); - setGlobalSetting('enableXMLRPCInterface', $_POST['enableXMLRPCInterface']); + setGlobalSetting('RPCInterface', $_POST['RPCInterface']); $savetime = trim(strip_tags((float)$_POST['timeadjust']) . ' hours'); //makes sure it is a number, at least 0 if ((substr($savetime, 0, 1) != '-') && (substr($savetime, 0, 1) != '+')) { $savetime = '+' . $savetime; @@ -174,7 +174,7 @@ private function _saveSettings() Yii::app()->session['flashmessage'] = $clang->gT("Global settings were saved."); $url = htmlspecialchars_decode(Yii::app()->session['refurl']); - if($url){CController::redirect($url);} + if($url){Yii::app()->getController()->redirect($url);} } private function _checkSettings() diff --git a/application/controllers/admin/kcfinder.php b/application/controllers/admin/kcfinder.php index 4ec0843c719..70764246b8f 100644 --- a/application/controllers/admin/kcfinder.php +++ b/application/controllers/admin/kcfinder.php @@ -46,13 +46,13 @@ function index($load = false) $_SESSION['KCFINDER']['disabled'] = false; if (preg_match('/^edit:emailsettings/',$_SESSION['FileManagerContext']) != 0) { - $_SESSION['KCFINDER']['uploadURL'] = $this->getController()->createAbsoluteUrl("upload/surveys/{$surveyid}/"); + $_SESSION['KCFINDER']['uploadURL'] = Yii::app()->getRequest()->getHostInfo($schema).Yii::app()->getConfig('uploadurl')."/surveys/{$surveyid}/"; } else { - $_SESSION['KCFINDER']['uploadURL'] = $this->getController()->createUrl("upload/surveys/{$surveyid}/"); + $_SESSION['KCFINDER']['uploadURL'] = Yii::app()->getConfig('uploadurl')."/surveys/{$surveyid}/"; } - $_SESSION['KCFINDER']['uploadDir'] = ROOT . "/upload/surveys/{$surveyid}/"; + $_SESSION['KCFINDER']['uploadDir'] = Yii::app()->getConfig('uploaddir') .DIRECTORY_SEPARATOR.'surveys'.DIRECTORY_SEPARATOR.$surveyid.DIRECTORY_SEPARATOR; } } elseif (preg_match('/^edit:label/', Yii::app()->session['FileManagerContext']) != 0) @@ -63,31 +63,32 @@ function index($load = false) if (Yii::app()->session['USER_RIGHT_MANAGE_LABEL'] == 1 && isset($labelid) && $labelid != '') { $_SESSION['KCFINDER']['disabled'] = false; - $_SESSION['KCFINDER']['uploadURL'] = $this->getController()->createUrl("upload/labels/{$labelid}/"); - $_SESSION['KCFINDER']['uploadDir'] = ROOT . "/upload/labels/{$labelid}/"; + $_SESSION['KCFINDER']['uploadURL'] = Yii::app()->getConfig('uploadurl')."/labels/{$labelid}/"; + $_SESSION['KCFINDER']['uploadDir'] = Yii::app()->getConfig('uploaddir') .DIRECTORY_SEPARATOR.'labels'.DIRECTORY_SEPARATOR.$labelid.DIRECTORY_SEPARATOR; } } } Yii::registerAutoloader(array($this, 'kcfinder_autoload')); - if (!empty($load) && file_exists(ROOT . "/scripts/admin/kcfinder/" . $load . EXT)) + if (!empty($load) && file_exists(Yii::app()->getConfig('generalscripts')."admin/kcfinder/" . $load . EXT)) { - require_once(ROOT . "/scripts/admin/kcfinder/" . $load . EXT); + chdir(Yii::app()->getConfig('generalscripts')."admin/kcfinder/"); + require_once(Yii::app()->getConfig('generalscripts')."admin/kcfinder/" . $load . EXT); } } function kcfinder_autoload($class) { if ($class == "uploader") - require ROOT . "/scripts/admin/kcfinder/core/uploader.php"; + require Yii::app()->getConfig('generalscripts')."kcfinder/core/uploader.php"; elseif ($class == "browser") - require ROOT . "/scripts/admin/kcfinder/core/browser.php"; - elseif (file_exists(ROOT . "/scripts/admin/kcfinder/core/types/$class.php")) - require ROOT . "/scripts/admin/kcfinder/core/types/$class.php"; - elseif (file_exists(ROOT . "/scripts/admin/kcfinder/lib/class_$class.php")) - require ROOT . "/scripts/admin/kcfinder/lib/class_$class.php"; - elseif (file_exists(ROOT . "/scripts/admin/kcfinder/lib/helper_$class.php")) - require ROOT . "/scripts/admin/kcfinder/lib/helper_$class.php"; + require Yii::app()->getConfig('generalscripts')."admin/kcfinder/core/browser.php"; + elseif (file_exists(Yii::app()->getConfig('generalscripts')."admin/kcfinder/core/types/$class.php")) + require Yii::app()->getConfig('generalscripts')."admin/kcfinder/core/types/$class.php"; + elseif (file_exists(Yii::app()->getConfig('generalscripts')."admin/kcfinder/lib/class_$class.php")) + require Yii::app()->getConfig('generalscripts')."admin/kcfinder/lib/class_$class.php"; + elseif (file_exists(Yii::app()->getConfig('generalscripts')."admin/kcfinder/lib/helper_$class.php")) + require Yii::app()->getConfig('generalscripts')."admin/kcfinder/lib/helper_$class.php"; } function css() @@ -335,8 +336,8 @@ function js_localise() $input = new input(); if (!isset($input->get['lng']) || ($input->get['lng'] == 'en')) die; - $file = ROOT . "/scripts/admin/kcfinder/lang/" . $input->get['lng'] . ".php"; - $files = glob(ROOT . "/scripts/admin/kcfinder/lang/*.php"); + $file = Yii::app()->getConfig('generalscripts')."admin/kcfinder/lang/" . $input->get['lng'] . ".php"; + $files = glob(Yii::app()->getConfig('generalscripts')."admin/kcfinder/lang/*.php"); if (!in_array($file, $files)) die; $mtime = @filemtime($file); diff --git a/application/controllers/admin/labels.php b/application/controllers/admin/labels.php index 7150deac61d..b4030e5aad8 100644 --- a/application/controllers/admin/labels.php +++ b/application/controllers/admin/labels.php @@ -12,8 +12,6 @@ * is derivative of works licensed under the GNU General Public License or * other free or open source software licenses. * See COPYRIGHT.php for copyright notices and details. - * - * $Id$ */ /** @@ -22,7 +20,6 @@ * @package LimeSurvey * @author * @copyright 2011 - * @version $Id$ * @access public */ class labels extends Survey_Common_Action @@ -384,9 +381,9 @@ public function getAllSets() public function ajaxSets() { - $lid = CHttpRequest::getPost('lid'); - $answers = CHttpRequest::getPost('answers'); - $code = CHttpRequest::getPost('code'); + $lid = Yii::app()->getRequest()->getPost('lid'); + $answers = Yii::app()->getRequest()->getPost('answers'); + $code = Yii::app()->getRequest()->getPost('code'); //Create new label set $language = ""; foreach ($answers as $lang => $answer) { @@ -396,7 +393,7 @@ public function ajaxSets() if ($lid == 0) { $lset = new Labelsets; - $lset->label_name = sanitize_xss_string(CHttpRequest::getPost('laname')); + $lset->label_name = sanitize_xss_string(Yii::app()->getRequest()->getPost('laname')); $lset->languages = sanitize_xss_string($language); $lset->save(); diff --git a/application/controllers/admin/limereplacementfields.php b/application/controllers/admin/limereplacementfields.php index d61c1077888..5bcf46529ee 100644 --- a/application/controllers/admin/limereplacementfields.php +++ b/application/controllers/admin/limereplacementfields.php @@ -96,7 +96,7 @@ private function _getQuestionList($action, $gid, $qid, array $fieldmap, $questio return $questionList; } - private function _shouldAddQuestion($action, $gid, $qid, array $q, $previousQ) + private function _shouldAddQuestion($action, $gid, $qid, $q, $previousQ) { switch ($action) { diff --git a/application/controllers/admin/participantsaction.php b/application/controllers/admin/participantsaction.php index c6c75854ddd..f34a7bfc420 100644 --- a/application/controllers/admin/participantsaction.php +++ b/application/controllers/admin/participantsaction.php @@ -33,6 +33,7 @@ private function _loadjqGrid($sScript = '', $aData = array()) $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/src/grid.celledit.js'); $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/js/i18n/grid.locale-en.js'); + if (!empty($sScript)) { $this->getController()->_js_admin_includes(Yii::app()->getConfig('adminscripts') . $sScript . '.js'); @@ -64,6 +65,8 @@ protected function _renderWrappedTemplate($sAction = 'participants', $aViewUrls */ function index() { + $iUserID = Yii::app()->session['loginID']; + // if superadmin all the records in the cpdb will be displayed if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) { @@ -72,15 +75,14 @@ function index() // if not only the participants on which he has right on (shared and owned) else { - $iTotalRecords = Participants::getParticipantsOwnerCount($iUserID); + $iTotalRecords = Participants::model()->getParticipantsOwnerCount($iUserID); } // gets the count of participants, their attributes and other such details - $iUserID = Yii::app()->session['loginID']; $aData = array( 'totalrecords' => $iTotalRecords, 'owned' => Participants::model()->count('owner_uid = ' . $iUserID), - 'shared' => Participants::getParticipantsSharedCount($iUserID), + 'shared' => Participants::model()->getParticipantsSharedCount($iUserID), 'attributecount' => ParticipantAttributeNames::model()->count(), 'blacklisted' => Participants::model()->count('owner_uid = ' . $iUserID . ' AND blacklisted = \'Y\'') ); @@ -105,43 +107,45 @@ function displayParticipants() $lang = Yii::app()->session['adminlang']; // loads the survey names to be shown in add to survey // if user is superadmin, all survey names - if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) - { - $aSurveyNames = Surveys_languagesettings::model()->with('survey', 'owner')->findAll('surveyls_language=:lang', array(':lang'=>$lang)); - } - // otherwise owned by him - else - { - $aSurveyNames = Surveys_languagesettings::model()->with('survey', 'owner')->findAll('survey.owner_id=:uid AND surveyls_language=:lang',array('survey.uid'=>Yii::app()->session['loginID'], ':lang'=>$lang)); - } + $urlSearch=Yii::app()->request->getQuery('searchurl'); + $urlSearch=!empty($urlSearch) ? "getParticipantsResults_json/search/$urlSearch" : "getParticipants_json"; + + //Get list of surveys. + //Should be all surveys owned by user (or all surveys for super admin) + $surveys = Survey::model(); + //!!! Is this even possible to execute? + if (empty(Yii::app()->session['USER_RIGHT_SUPERADMIN'])) + $surveys->permission(Yii::app()->user->getId()); + + $aSurveyNames = $surveys->model()->with(array('languagesettings'=>array('condition'=>'surveyls_language=language'), 'owner'))->findAll(); /* Build a list of surveys that have tokens tables */ $tSurveyNames=array(); foreach($aSurveyNames as $row) { - //echo $row['surveyls_survey_id']."
"; - $bTokenExists = tableExists('{{tokens_' . $row['surveyls_survey_id'] . '}}'); + $row = array_merge($row->attributes, $row->languagesettings[0]->attributes); + $bTokenExists = tableExists('{{tokens_' . $row['sid'] . '}}'); if ($bTokenExists) //If tokens table exists { $tSurveyNames[]=$row; } } - // data to be passed to view $aData = array( 'names' => User::model()->findAll(), - 'attributes' => ParticipantAttributeNames::getVisibleAttributes(), - 'allattributes' => ParticipantAttributeNames::getAllAttributes(), - 'attributeValues' => ParticipantAttributeNames::getAllAttributesValues(), + 'attributes' => ParticipantAttributeNames::model()->getVisibleAttributes(), + 'allattributes' => ParticipantAttributeNames::model()->getAllAttributes(), + 'attributeValues' => ParticipantAttributeNames::model()->getAllAttributesValues(), 'surveynames' => $aSurveyNames, - 'tokensurveynames' => $tSurveyNames + 'tokensurveynames' => $tSurveyNames, + 'urlsearch' => $urlSearch ); $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/js/i18n/grid.locale-en.js'); $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/js/jquery.jqGrid.min.js'); $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/css/jquery.multiselect.css'); $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/css/jquery.multiselect.filter.css'); - $this->getController()->_css_admin_includes(Yii::app()->getConfig('styleurl') . 'admin/default/displayParticipants.css'); + $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') . 'displayParticipants.css'); $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/css/ui.jqgrid.css'); $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/css/jquery.ui.datepicker.css'); @@ -198,16 +202,16 @@ function getShareInfo_json() // If super administrator all the share info in the links table will be shown if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) { - $records = Participants::getParticipantSharedAll(); + $records = Participants::model()->getParticipantSharedAll(); $aData->records = count($records); $aData->total = ceil($aData->records / 10); $i = 0; foreach ($records as $row) { - $oShared = User::getName($row['share_uid']); //for conversion of uid to human readable names - $owner = User::getName($row['owner_uid']); - $aData->rows[$i]['id'] = $row['participant_id']; + $oShared = User::model()->getName($row['share_uid']); //for conversion of uid to human readable names + $owner = User::model()->getName($row['owner_uid']); + $aData->rows[$i]['id'] = $row['participant_id']."--".$row['share_uid']; //This is the unique combination per record $aData->rows[$i]['cell'] = array($row['firstname'], $row['lastname'], $row['email'], $oShared[0]['full_name'], $row['share_uid'], $owner[0]['full_name'], $row['date_added'], $row['can_edit']); $i++; } @@ -217,14 +221,14 @@ function getShareInfo_json() // otherwise only the shared participants by that user else { - $records = User::getParticipantShared(Yii::app()->session['loginID']); + $records = User::model()->getParticipantShared(Yii::app()->session['loginID']); $aData->records = count($records); $aData->total = ceil($aData->records / 10); $i = 0; foreach ($records as $row) { - $sharename = User::getName($row['share_uid']); //for conversion of uid to human readable names + $sharename = User::model()->getName($row['share_uid']); //for conversion of uid to human readable names $aData->rows[$i]['id'] = $row['participant_id']; $aData['rows'][$i]['cell'] = array($row['firstname'], $row['lastname'], $row['email'], $sharename['full_name'], $row['share_uid'], $row['date_added'], $row['can_edit']); $i++; @@ -241,9 +245,10 @@ function getShareInfo_json() function editShareInfo() { $operation = Yii::app()->request->getPost('oper'); + $shareIds = Yii::app()->request->getPost('id'); if ($operation == 'del') // If operation is delete , it will delete, otherwise edit it { - ParticipantShares::deleteRow($_POST); + ParticipantShares::model()->deleteRow($shareIds); } else { @@ -252,7 +257,7 @@ function editShareInfo() 'can_edit' => Yii::app()->request->getPost('can_edit'), 'share_uid' => Yii::app()->request->getPost('shared_uid') ); - ParticipantShares::updateShare($aData); + ParticipantShares::model()->updateShare($aData); } } @@ -276,7 +281,7 @@ function getAttributeInfo_json() $limit = Yii::app()->request->getPost('rows'); $limit = isset($limit) ? $limit : 50; //Stop division by zero errors - $records = ParticipantAttributeNames::getAttributes(); + $records = ParticipantAttributeNames::model()->getAttributes(); $attribute_types = array( 'DD' => $clang->gT("Drop-down list"), @@ -286,7 +291,7 @@ function getAttributeInfo_json() $aData->page = $page; $aData->records = count($records); - $aData->total = ceil(ParticipantAttributeNames::getAttributes(true) / $limit); + $aData->total = ceil(ParticipantAttributeNames::model()->getAttributes(true) / $limit); $i = 0; foreach ($records as $row) @@ -305,7 +310,9 @@ function getAttributeInfo_json() */ function editAttributeInfo() { + $clang = Yii::app()->lang; $operation = Yii::app()->request->getPost('oper'); + if ($operation == 'del' && Yii::app()->request->getPost('id')) { $aAttributeIds = (array) explode(',', Yii::app()->request->getPost('id')); @@ -314,7 +321,7 @@ function editAttributeInfo() foreach ($aAttributeIds as $iAttributeId) { - ParticipantAttributeNames::delAttribute($iAttributeId); + ParticipantAttributeNames::model()->delAttribute($iAttributeId); } } elseif ($operation == 'add' && Yii::app()->request->getPost('attribute_name')) @@ -324,7 +331,7 @@ function editAttributeInfo() 'attribute_type' => Yii::app()->request->getPost('attribute_type'), 'visible' => Yii::app()->request->getPost('visible') == 'TRUE' ? 'TRUE' : 'FALSE' ); - echo ParticipantAttributeNames::storeAttribute($aData); + echo ParticipantAttributeNames::model()->storeAttribute($aData); } elseif ($operation == 'edit' && Yii::app()->request->getPost('id')) { @@ -334,8 +341,10 @@ function editAttributeInfo() 'attribute_type' => Yii::app()->request->getPost('attribute_type'), 'visible' => Yii::app()->request->getPost('visible') == 'TRUE' ? 'TRUE' : 'FALSE' ); - ParticipantAttributeNames::saveAttribute($aData); + ParticipantAttributeNames::model()->saveAttribute($aData); + $clang->eT("Attribute display setting updated"); } + } /** @@ -351,17 +360,17 @@ function delParticipant() // Deletes from participants only if ($selectoption == 'po') { - Participants::deleteParticipant($iParticipantId); + Participants::model()->deleteParticipant($iParticipantId); } // Deletes from central and token table elseif ($selectoption == 'ptt') { - Participants::deleteParticipantToken($iParticipantId); + Participants::model()->deleteParticipantToken($iParticipantId); } // Deletes from central , token and assosiated responses as well else { - Participants::deleteParticipantTokenAnswer($iParticipantId); + Participants::model()->deleteParticipantTokenAnswer($iParticipantId); } } @@ -403,7 +412,7 @@ function editParticipant() 'blacklisted' => Yii::app()->request->getPost('blacklisted'), 'owner_uid' => $oid ); - Participants::updateRow($aData); + Participants::model()->updateRow($aData); } // if add it will insert a new row elseif ($operation == 'add') @@ -418,7 +427,7 @@ function editParticipant() 'blacklisted' => Yii::app()->request->getPost('blacklisted'), 'owner_uid' => $oid ); - Participants::insertParticipant($aData); + Participants::model()->insertParticipant($aData); } } @@ -438,7 +447,7 @@ function storeUserControlValues() $stg ->stg_value=Yii::app()->request->getPost('userideditable'); $stg->save(); } - CController::redirect(Yii::app()->getController()->createUrl('admin/participants/userControl')); + Yii::app()->getController()->redirect(Yii::app()->getController()->createUrl('admin/participants/userControl')); } /** @@ -461,7 +470,7 @@ function storeBlacklistValues() $stg->save(); } } - CController::redirect(Yii::app()->getController()->createUrl('admin/participants/blacklistControl')); + Yii::app()->getController()->redirect(Yii::app()->getController()->createUrl('admin/participants/blacklistControl')); } /** @@ -482,8 +491,17 @@ function getSurveyInfo_json() foreach ($records as $row) { - $surveyname = Surveys_languagesettings::getSurveyNames($row['survey_id']); - $aData->rows[$i]['cell'] = array($surveyname[0]['surveyls_title'], '' . $row['survey_id'], $row['token_id'], $row['date_created']); + $surveyname = Surveys_languagesettings::model()->getSurveyNames($row['survey_id']); + $surveylink = ""; + /* Check permissions of each survey before creating a link*/ + if (!hasSurveyPermission($row['survey_id'], 'tokens', 'read')) + { + $surveylink = $row['survey_id']; + } else + { + $surveylink = '' . $row['survey_id'].''; + } + $aData->rows[$i]['cell'] = array($surveyname[0]['surveyls_title'], $surveylink, $row['token_id'], $row['date_created'], $row['date_invited'], $row['date_completed']); $i++; } @@ -506,24 +524,17 @@ function exporttocsvcount() if ($searchcondition != 'getParticipants_json') // if there is a search condition then only the participants that match the search criteria are counted { $condition = explode("||", $searchcondition); - if (count($condition) == 3) - { - $query = Participants::getParticipantsSearch($condition, 0, 0); - } - else - { - $query = Participants::getParticipantsSearchMultiple($condition, 0, 0); - } + $query = Participants::model()->getParticipantsSearchMultiple($condition, 0, 0); } else // if no search criteria all the participants will be counted { - $query = Participants::getParticipantsWithoutLimit(); + $query = Participants::model()->getParticipantsWithoutLimit(); } } else // If no search criteria it will simply return the number of participants { $iUserID = Yii::app()->session['loginID']; - $query = Particiapnts::getParticipantsOwner($iUserID); + $query = Participants::model()->getParticipantsOwner($iUserID); } echo sprintf($clang->gT("Export %s participant(s) to CSV"), count($query)); @@ -536,12 +547,12 @@ function exporttocsvcountAll() { if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) //If super admin all the participants in the central table will be counted { - $query = Participants::getParticipantsWithoutLimit(); + $query = Participants::model()->getParticipantsWithoutLimit(); } else // otherwise only the participants on which the logged in user has the rights { $iUserID = Yii::app()->session['loginID']; - $query = Participants::getParticipantsOwner($iUserID); + $query = Participants::model()->getParticipantsOwner($iUserID); } if (count($query) > 0) // If count is greater than 0 it will show the message @@ -562,12 +573,12 @@ function exporttocsvAll() Yii::app()->loadHelper('export'); // loads the export helper if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) //If super admin all the participants will be exported { - $query = Participants::getParticipantsWithoutLimit(); + $query = Participants::model()->getParticipantsWithoutLimit(); } else // otherwise only the ones over which the user has rights on { $iUserID = Yii::app()->session['loginID']; - $query = Participants::getParticipantsOwner($iUserID); + $query = Participants::model()->getParticipantsOwner($iUserID); } if (!$query) @@ -584,7 +595,7 @@ function exporttocsvAll() $i++; } - $attributenames = ParticipantAttributeNames::getAttributes(); + $attributenames = ParticipantAttributeNames::model()->getAttributes(); // Attribute names are being added to the index 0 of the array foreach ($attributenames as $key => $value) { @@ -609,7 +620,7 @@ function exporttocsvAll() // that are to be exported to the CSV file foreach ($attributenames as $key => $value) { - $answer = ParticipantAttributeNames::getAttributeValue($aData['participant_id'], $value['attribute_id']); + $answer = ParticipantAttributeNames::model()->getAttributeValue($aData['participant_id'], $value['attribute_id']); if (isset($answer['value'])) { // if the attribute value is there for that attribute and the user then it will written to the array $outputarray[$i][$j] = $answer['value']; @@ -644,14 +655,8 @@ function getaddtosurveymsg() { $participantid = ""; $condition = explode("||", $searchcondition); - if (count($condition) == 3) // If there is no and condition , if the count is equal to 3 that means only one condition - { - $query = Participants::getParticipantsSearch($condition, 0, 0); - } - else // if there are 'and' and 'or' condition in the condition the count is to be greater than 3 - { - $query = Participants::getParticipantsSearchMultiple($condition, 0, 0); - } + + $query = Participants::model()->getParticipantsSearchMultiple($condition, 0, 0); printf( $this->getController()->lang->gT("%s participant(s) are to be copied "), count($query)); } @@ -660,11 +665,11 @@ function getaddtosurveymsg() { if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) //If super admin all the participants will be visible { - $query = Participants::getParticipantsWithoutLimit(); + $query = Participants::model()->getParticipantsWithoutLimit(); } else { - $query = Participants::getParticipantsOwner(Yii::app()->session['loginID']); + $query = Participants::model()->getParticipantsOwner(Yii::app()->session['loginID']); } printf($this->getController()->lang->gT("%s participant(s) are to be copied "), count($query)); @@ -686,18 +691,20 @@ function getSearchIDs() { $participantid = ""; $condition = explode("||", $searchcondition); // explode the condition to the array - // format for the condition is field||condition||value - if (count($condition) == 3) // if count is 3 , then it's a single search - { - $query = Participants::getParticipantsSearch($condition, 0, 0); - } - else// if count is more than 3 , then it's a multiple search - { - $query = Participants::getParticipantsSearchMultiple($condition, 0, 0); - } + $query = Participants::model()->getParticipantsSearchMultiple($condition, 0, 0); + foreach ($query as $key => $value) { - $participantid = $participantid . "," . $value['participant_id']; // combine the participant id's in an string + if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) + { + $participantid .= "," . $value['participant_id']; // combine the participant id's in an string + } else + { + if(Participants::model()->is_owner($value['participant_id'])) + { + $participantid .= "," . $value['participant_id']; // combine the participant id's in an string + } + } } echo $participantid; //echo the participant id's } @@ -706,11 +713,11 @@ function getSearchIDs() $participantid = ""; // initiallise the participant id to blank if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) //If super admin all the participants will be visible { - $query = Participants::getParticipantsWithoutLimit(); // get all the participant id if it is a super admin + $query = Participants::model()->getParticipantsWithoutLimit(); // get all the participant id if it is a super admin } else // get participants on which the user has right on { - $query = Participants::getParticipantsOwner(Yii::app()->session['loginID']); + $query = Participants::model()->getParticipantsOwner(Yii::app()->session['loginID']); } foreach ($query as $key => $value) @@ -738,24 +745,19 @@ function exporttocsv() if ($searchcondition != 'getParticipants_json') // If there is a search condition then only does participants are exported { $condition = explode("||", $searchcondition); - if (count($condition) == 3) // Single search - { - $query = Participants::getParticipantsSearch($condition, 0, 0); - } - else //combined search - { - $query = Participants::getParticipantsSearchMultiple($condition, 0, 0); - } + + $query = Participants::model()->getParticipantsSearchMultiple($condition, 0, 0); + } // else all the participants in the central table will be exported since it's superadmin else { - $query = Participants::getParticipantsWithoutLimit(); + $query = Participants::model()->getParticipantsWithoutLimit(); } } else { $iUserID = Yii::app()->session['loginID']; // else only the - $query = Participants::getParticipantsOwner($iUserID); + $query = Participants::model()->getParticipantsOwner($iUserID); } if (!$query) @@ -791,7 +793,7 @@ function exporttocsv() $iAttributeId = explode(",", Yii::app()->request->getQuery('id')); foreach ($iAttributeId as $key => $value) { - $attributename = ParticipantAttributeNames::getAttributeNames($value); + $attributename = ParticipantAttributeNames::model()->getAttributeNames($value); $outputarray[0][$i] = $attributename[0]['attribute_name']; $i++; } @@ -807,7 +809,7 @@ function exporttocsv() } foreach ($iAttributeId as $key => $value) { - $answer = ParticipantAttributeNames::getAttributeValue($aData['participant_id'], $value); + $answer = ParticipantAttributeNames::model()->getAttributeValue($aData['participant_id'], $value); if (isset($answer['value'])) { $outputarray[$i][$j] = $answer['value']; @@ -832,11 +834,11 @@ function getParticipantsResults_json() //First entry is field to search, second method, third value, seperated by double pipe "||" $page = Yii::app()->request->getPost('page'); $limit = Yii::app()->request->getPost('rows'); - $page=($page) ? $page : 1; + $page=($page) ? $page : 1; $limit=($limit) ? $limit : 25; - $attid = ParticipantAttributeNames::getAttributeVisibleID(); - $participantfields = array('participant_id', 'can_edit', 'firstname', 'lastname', 'email', 'blacklisted', 'surveys', 'language', 'owner_uid'); + $attid = ParticipantAttributeNames::model()->getAttributeVisibleID(); + $participantfields = array('participant_id', 'can_edit', 'firstname', 'lastname', 'email', 'blacklisted', 'survey', 'language', 'owner_uid'); //If super admin all the participants will be visible if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) @@ -848,29 +850,24 @@ function getParticipantsResults_json() $condition = explode("||", $searchcondition); $aData = new stdClass(); $aData->page = $page; - if (count($condition) == 3) - { - $records = Participants::getParticipantsSearch($condition, $page, $limit); - $aData->records = count(Participants::getParticipantsSearch($condition, 0, 0)); - $aData->total = ceil($aData->records / $limit); - } - else - { - $records = Participants::getParticipantsSearchMultiple($condition, $page, $limit); - $aData->records = count(Participants::getParticipantsSearchMultiple($condition, 0, 0)); - $aData->total = ceil($aData->records / $limit); - } + + $records = Participants::model()->getParticipantsSearchMultiple($condition, $page, $limit); + + $aData->records = count(Participants::model()->getParticipantsSearchMultiple($condition, 0, 0)); + $aData->total = ceil($aData->records / $limit); + $i = 0; foreach ($records as $row => $value) { - $username = User::getName($value['owner_uid']); //for conversion of uid to human readable names - $surveycount = Participants::getSurveyCount($value['participant_id']); + $username = User::model()->getName($value['owner_uid']); //for conversion of uid to human readable names + $surveycount = Participants::model()->getSurveyCount($value['participant_id']); $sortablearray[$i] = array($value['participant_id'], "true", $value['firstname'], $value['lastname'], $value['email'], $value['blacklisted'], $surveycount, $value['language'], $username[0]['full_name']); // since it's the admin he has access to all editing on the participants inspite of what can_edit option is - $attributes = ParticipantAttributeNames::getParticipantVisibleAttribute($value['participant_id']); + $attributes = ParticipantAttributeNames::model()->getParticipantVisibleAttribute($value['participant_id']); foreach ($attid as $iAttributeId) { - $answer = ParticipantAttributeNames::getAttributeValue($value['participant_id'], $iAttributeId['attribute_id']); + $participantfields[]=$iAttributeId['attribute_id']; + $answer = ParticipantAttributeNames::model()->getAttributeValue($value['participant_id'], $iAttributeId['attribute_id']); if (isset($answer['value'])) { array_push($sortablearray[$i], $answer['value']); @@ -907,6 +904,10 @@ function subval_sort($a, $subkey, $order) if (!empty($sortablearray)) { $indexsort = array_search(Yii::app()->request->getPost('sidx'), $participantfields); + if(is_numeric(Yii::app()->request->getPost('sidx'))) { + + } + //var_dump($sortablearray);echo "\r\n\r\n"; $sortedarray = subval_sort($sortablearray, $indexsort, Yii::app()->request->getPost('sord')); $i = 0; $count = count($sortedarray[0]); @@ -933,26 +934,21 @@ function subval_sort($a, $subkey, $order) $condition = explode("||", $searchcondition); $aData = new stdClass(); $aData->page = $page; - if (count($condition) == 3) - { - $records = Participants::getParticipantsSearch($condition, $page, $limit); - } - else - { - $records = Participants::getParticipantsSearchMultiple($condition, $page, $limit); - } + + $records = Participants::model()->getParticipantsSearchMultiple($condition, $page, $limit); + $i = 0; foreach ($records as $row => $value) { - if (Participants::is_owner($value['participant_id'])) + if (Participants::model()->is_owner($value['participant_id'])) { - $username = User::getName($value['owner_uid']); //for conversion of uid to human readable names - $surveycount = Participants::getSurveyCount($value['participant_id']); + $username = User::model()->getName($value['owner_uid']); //for conversion of uid to human readable names + $surveycount = Participants::model()->getSurveyCount($value['participant_id']); $sortablearray[$i] = array($value['participant_id'], "true", $value['firstname'], $value['lastname'], $value['email'], $value['blacklisted'], $surveycount, $value['language'], $username[0]['full_name']); // since it's the admin he has access to all editing on the participants inspite of what can_edit option is - $attributes = ParticipantAttributeNames::getParticipantVisibleAttribute($value['participant_id']); + $attributes = ParticipantAttributeNames::model()->getParticipantVisibleAttribute($value['participant_id']); foreach ($attid as $iAttributeId) { - $answer = ParticipantAttributeNames::getAttributeValue($value['participant_id'], $iAttributeId['attribute_id']); + $answer = ParticipantAttributeNames::model()->getAttributeValue($value['participant_id'], $iAttributeId['attribute_id']); if (isset($answer['value'])) { array_push($sortablearray[$i], $answer['value']); @@ -1040,17 +1036,17 @@ function subval_sort($a, $subkey, $order) $limit = Yii::app()->request->getPost('rows'); $limit = isset($limit) ? $limit : 50; //Stop division by zero errors - $attid = ParticipantAttributeNames::getAttributeVisibleID(); - $participantfields = array('participant_id', 'can_edit', 'firstname', 'lastname', 'email', 'blacklisted', 'surveys', 'language', 'owner_uid'); + $attid = ParticipantAttributeNames::model()->getAttributeVisibleID(); + $participantfields = array('participant_id', 'can_edit', 'firstname', 'lastname', 'email', 'blacklisted', 'survey', 'language', 'owner_uid'); foreach ($attid as $key => $value) { - array_push($participantfields, $value['attribute_name']); + array_push($participantfields, $value['attribute_id']); } //If super admin all the participants will be visible if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) { - $records = Participants::getParticipants($page, $limit); + $records = Participants::model()->getParticipants($page, $limit); $aData->page = $page; $aData->records = Participants::model()->count(); $aData->total = ceil($aData->records / $limit); @@ -1058,13 +1054,13 @@ function subval_sort($a, $subkey, $order) $sortablearray=array(); foreach ($records as $key => $row) { - $username = User::getName($row['owner_uid']); //for conversion of uid to human readable names - $surveycount = Participants::getSurveyCount($row['participant_id']); + $username = User::model()->getName($row['owner_uid']); //for conversion of uid to human readable names + $surveycount = Participants::model()->getSurveyCount($row['participant_id']); $sortablearray[$i] = array($row['participant_id'], "true", $row['firstname'], $row['lastname'], $row['email'], $row['blacklisted'], $surveycount, $row['language'], $username[0]['full_name']); // since it's the admin he has access to all editing on the participants inspite of what can_edit option is - $attributes = ParticipantAttributeNames::getParticipantVisibleAttribute($row['participant_id']); + $attributes = ParticipantAttributeNames::model()->getParticipantVisibleAttribute($row['participant_id']); foreach ($attid as $iAttributeId) { - $answer = ParticipantAttributeNames::getAttributeValue($row['participant_id'], $iAttributeId['attribute_id']); + $answer = ParticipantAttributeNames::model()->getAttributeValue($row['participant_id'], $iAttributeId['attribute_id']); if (isset($answer['value'])) { array_push($sortablearray[$i], $answer['value']); @@ -1099,22 +1095,22 @@ function subval_sort($a, $subkey, $order) else { $iUserID = Yii::app()->session['loginID']; - $records = Participants::getParticipantsOwner($iUserID); + $records = Participants::model()->getParticipantsOwner($iUserID); $aData->page = $page; $aData->records = count($records); $aData->total = ceil($aData->records / $limit); - $attid = ParticipantAttributeNames::getAttributeVisibleID(); + $attid = ParticipantAttributeNames::model()->getAttributeVisibleID(); $i = 0; $sortablearray=array(); foreach ($records as $row) { - $surveycount = Participants::getSurveyCount($row['participant_id']); - $ownername = User::getName($row['owner_uid']); //for conversion of uid to human readable names + $surveycount = Participants::model()->getSurveyCount($row['participant_id']); + $ownername = User::model()->getName($row['owner_uid']); //for conversion of uid to human readable names $sortablearray[$i] = array($row['participant_id'], $row['can_edit'], $row['firstname'], $row['lastname'], $row['email'], $row['blacklisted'], $surveycount, $row['language'], $ownername[0]['full_name']); - $attributes = ParticipantAttributeNames::getParticipantVisibleAttribute($row['participant_id']); + $attributes = ParticipantAttributeNames::model()->getParticipantVisibleAttribute($row['participant_id']); foreach ($attid as $iAttributeId) { - $answer = ParticipantAttributeNames::getAttributeValue($row['participant_id'], $iAttributeId['attribute_id']); + $answer = ParticipantAttributeNames::model()->getAttributeValue($row['participant_id'], $iAttributeId['attribute_id']); if (isset($answer['value'])) { array_push($sortablearray[$i], $answer['value']); @@ -1153,8 +1149,8 @@ function subval_sort($a, $subkey, $order) function getAttribute_json() { $iParticipantId = Yii::app()->request->getQuery('pid'); - $records = ParticipantAttributeNames::getParticipantVisibleAttribute($iParticipantId); - $getallattributes = ParticipantAttributeNames::getAttributes(); + $records = ParticipantAttributeNames::model()->getParticipantVisibleAttribute($iParticipantId); + $getallattributes = ParticipantAttributeNames::model()->getAttributes(); $aData = new stdClass(); $aData->page = 1; $aData->records = count($records); @@ -1163,14 +1159,17 @@ function getAttribute_json() $aData->rows[0]['cell'] = array(); $i = 0; - $doneattributes = array(); + $doneattributes = array(); //If the user has any actual attribute values, they'll be stored here + + /* Iterate through each attribute owned by this user */ foreach ($records as $row) { $aData->rows[$i]['id'] = $row['participant_id'] . "_" . $row['attribute_id']; $aData->rows[$i]['cell'] = array("", $row['participant_id'], $row['attribute_type'], $row['attribute_name'], $row['value']); + /* Collect allowed values for a DropDown attribute */ if ($row['attribute_type'] == "DD") { - $attvalues = ParticipantAttributeNames::getAttributesValues($row['attribute_id']); + $attvalues = ParticipantAttributeNames::model()->getAttributesValues($row['attribute_id']); if (!empty($attvalues)) { $attval = ""; @@ -1194,47 +1193,54 @@ function getAttribute_json() array_push($doneattributes, $row['attribute_id']); $i++; } + + /* Build a list of attribute names for which this user has NO values stored, keep it in $attributenotdone */ + $attributenotdone=array(); + /* The user has NO values stored against any attribute */ if (count($doneattributes) == 0) { - $attributenotdone = ParticipantAttributeNames::getAttributes(); + $attributenotdone = ParticipantAttributeNames::model()->getAttributes(); } + /* The user has SOME values stored against attributes */ else { - $attributenotdone = ParticipantAttributeNames::getnotaddedAttributes($doneattributes); + $attributenotdone = ParticipantAttributeNames::model()->getnotaddedAttributes($doneattributes); } - if ($attributenotdone > 0) + + /* Go through the empty attributes and build an entry in the output for them */ + foreach ($attributenotdone as $row) { - foreach ($attributenotdone as $row) + $aData->rows[$i]['id'] = $iParticipantId . "_" . $row['attribute_id']; + $aData->rows[$i]['cell'] = array("", $iParticipantId, $row['attribute_type'], $row['attribute_name'], ""); + if ($row['attribute_type'] == "DD") { - - $aData->rows[$i]['id'] = $iParticipantId . "_" . $row['attribute_id']; - $aData->rows[$i]['cell'] = array("", $iParticipantId, $row['attribute_type'], $row['attribute_name'], ""); - if ($row['attribute_type'] == "DD") + $attvalues = ParticipantAttributeNames::model()->getAttributesValues($row['attribute_id']); + if (!empty($attvalues)) { - $attvalues = ParticipantAttributeNames::getAttributesValues($row['attribute_id']); - if (!empty($attvalues)) - { - $attval = ""; - foreach ($attvalues as $val) - { - $attval .= $val['value'] . ":" . $val['value']; - $attval .= ";"; - } - $attval = substr($attval, 0, -1); - array_push($aData->rows[$i]['cell'], $attval); - } - else + $attval = ""; + foreach ($attvalues as $val) { - array_push($aData->rows[$i]['cell'], ""); + $attval .= $val['value'] . ":" . $val['value']; + $attval .= ";"; } + $attval = substr($attval, 0, -1); + array_push($aData->rows[$i]['cell'], $attval); } else { array_push($aData->rows[$i]['cell'], ""); } - $i++; } + else + { + array_push($aData->rows[$i]['cell'], ""); + } + $i++; } + /* TODO: It'd be nice to do a natural sort on the attribute list at some point. + Currently they're returned in order of attributes WITH values, then WITHOUT values + */ + echo ls_json_encode($aData); } @@ -1251,7 +1257,7 @@ function storeParticipants() 'blacklisted' => Yii::app()->request->getPost('blacklisted'), 'owner_uid' => Yii::app()->request->getPost('owner_uid')); - Participants::insertParticipant($aData); + Participants::model()->insertParticipant($aData); } /* @@ -1261,13 +1267,13 @@ function viewAttribute() { $iAttributeId = Yii::app()->request->getQuery('aid'); $aData = array( - 'attributes' => ParticipantAttributeNames::getAttribute($iAttributeId), - 'attributenames' => ParticipantAttributeNames::getAttributeNames($iAttributeId), - 'attributevalues' => ParticipantAttributeNames::getAttributesValues($iAttributeId) + 'attributes' => ParticipantAttributeNames::model()->getAttribute($iAttributeId), + 'attributenames' => ParticipantAttributeNames::model()->getAttributeNames($iAttributeId), + 'attributevalues' => ParticipantAttributeNames::model()->getAttributesValues($iAttributeId) ); - $this->getController()->_css_admin_includes(Yii::app()->getConfig('styleurl') . 'admin/'.Yii::app()->getConfig("admintheme").'/participants.css'); - $this->getController()->_css_admin_includes(Yii::app()->getConfig('styleurl') . 'admin/'.Yii::app()->getConfig("admintheme").'/viewAttribute.css'); + $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') . 'participants.css'); + $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') . 'viewAttribute.css'); $this->_renderWrappedTemplate('participants', array('participantsPanel', 'viewAttribute'), $aData); } @@ -1284,7 +1290,7 @@ function saveAttribute() 'attribute_type' => Yii::app()->request->getPost('attribute_type'), 'visible' => Yii::app()->request->getPost('visible') ); - ParticipantAttributeNames::saveAttribute($aData); + ParticipantAttributeNames::model()->saveAttribute($aData); foreach ($_POST as $key => $value) { @@ -1297,7 +1303,7 @@ function saveAttribute() 'lang' => $key ); - ParticipantAttributeNames::saveAttributeLanguages($langdata); + ParticipantAttributeNames::model()->saveAttributeLanguages($langdata); } } if (Yii::app()->request->getPost('langdata')) @@ -1308,7 +1314,7 @@ function saveAttribute() 'lang' => Yii::app()->request->getPost('langdata') ); - ParticipantAttributeNames::saveAttributeLanguages($langdata); + ParticipantAttributeNames::model()->saveAttributeLanguages($langdata); } if (Yii::app()->request->getPost('attribute_value_name_1')) { @@ -1325,7 +1331,7 @@ function saveAttribute() } $i++; } while (isset($_POST[$attvaluename])); - ParticipantAttributeNames::storeAttributeValues($aDatavalues); + ParticipantAttributeNames::model()->storeAttributeValues($aDatavalues); } if (Yii::app()->request->getPost('editbox')) { @@ -1334,9 +1340,9 @@ function saveAttribute() 'value_id' => Yii::app()->request->getPost('value_id'), 'value' => Yii::app()->request->getPost('editbox') ); - ParticipantAttributeNames::saveAttributeValue($editattvalue); + ParticipantAttributeNames::model()->saveAttributeValue($editattvalue); } - CController::redirect(Yii::app()->getController()->createUrl('admin/participants/attributeControl')); + Yii::app()->getController()->redirect(Yii::app()->getController()->createUrl('admin/participants/attributeControl')); } /* @@ -1346,8 +1352,8 @@ function delAttributeValues() { $iAttributeId = Yii::app()->request->getQuery('aid'); $iValueId = Yii::app()->request->getQuery('vid'); - ParticipantAttributeNames::delAttributeValues($iAttributeId, $iValueId); - CController::redirect(Yii::app()->getController()->createUrl('/admin/participants/viewAttribute/aid/' . $iAttributeId)); + ParticipantAttributeNames::model()->delAttributeValues($iAttributeId, $iValueId); + Yii::app()->getController()->redirect(Yii::app()->getController()->createUrl('/admin/participants/viewAttribute/aid/' . $iAttributeId)); } /* @@ -1359,7 +1365,7 @@ function editAttributevalue() { $iAttributeId = explode("_", Yii::app()->request->getPost('id')); $aData = array('participant_id' => Yii::app()->request->getPost('participant_id'), 'attribute_id' => $iAttributeId[1], 'value' => Yii::app()->request->getPost('attvalue')); - ParticipantAttributeNames::editParticipantAttributeValue($aData); + ParticipantAttributeNames::model()->editParticipantAttributeValue($aData); } } @@ -1395,21 +1401,23 @@ function attributeMapCSV() $selectedcsvfields = array(); foreach ($firstline as $key => $value) { - if (!in_array($value, $regularfields)) + $testvalue = preg_replace('/[^(\x20-\x7F)]*/','', $value); //Remove invalid characters from string + if (!in_array($testvalue, $regularfields)) { array_push($selectedcsvfields, $value); } + $fieldlist[]=$value; } - $linecount = count(file($sFilePath)); - $attributes = ParticipantAttributeNames::model()->getAttributes(); + $attributes = ParticipantAttributeNames::model()->model()->getAttributes(); $aData = array( 'attributes' => $attributes, 'firstline' => $selectedcsvfields, 'fullfilepath' => $sFilePath, 'linecount' => $linecount - 1, - 'filterbea' => $filterblankemails + 'filterbea' => $filterblankemails, + 'participant_id_exists' => in_array('participant_id', $fieldlist) ); $this->_renderWrappedTemplate('participants', 'attributeMapCSV', $aData); } @@ -1427,20 +1435,26 @@ function uploadCSV() $mappedarray = Yii::app()->request->getPost('mappedarray'); $sFilePath = Yii::app()->request->getPost('fullfilepath'); $filterblankemails = Yii::app()->request->getPost('filterbea'); + $overwrite = Yii::app()->request->getPost('overwrite'); $errorinupload = ""; - $tokenlistarray = file($sFilePath); $recordcount = 0; $mandatory = 0; $mincriteria = 0; $imported = 0; $dupcount = 0; + $overwritten = 0; + $dupreason="nameemail"; //Default duplicate comparison method $duplicatelist = array(); $invalidemaillist = array(); $invalidformatlist = array(); $invalidattribute = array(); $invalidparticipantid = array(); - // This allows to read file with MAC line endings too + + /* Adjust system settings to read file with MAC line endings */ @ini_set('auto_detect_line_endings', true); + /* Open the uploaded file into an array */ + $tokenlistarray = file($sFilePath); + // open it and trim the endings $separator = Yii::app()->request->getPost('seperatorused'); $uploadcharset = Yii::app()->request->getPost('characterset'); @@ -1516,7 +1530,7 @@ function uploadCSV() $ignoredcolumns[] = $fieldname; } } - if (!in_array('firstname', $firstline) || !in_array('lastname', $firstline) || !in_array('email', $firstline)) + if ((!in_array('firstname', $firstline) && !in_array('lastname', $firstline) && !in_array('email', $firstline)) && !in_array('participant_id', $firstline)) { $recordcount = count($tokenlistarray); break; @@ -1524,6 +1538,7 @@ function uploadCSV() } else { // After looking at the first line, we now import the actual values $line = convertCSVRowToArray($buffer, $separator, '"'); + if (count($firstline) != count($line)) { $invalidformatlist[] = $recordcount; @@ -1548,12 +1563,37 @@ function uploadCSV() 'owner_uid' => Yii::app()->session['loginID'] ); //HACK - converting into SQL instead of doing an array search - $aData = "firstname = '".mysql_real_escape_string($writearray['firstname'])."' AND lastname = '".mysql_real_escape_string($writearray['lastname'])."' AND email = '".mysql_real_escape_string($writearray['email'])."' AND owner_uid = '".Yii::app()->session['loginID']."'"; + if(in_array('participant_id', $firstline)) { + $dupreason="participant_id"; + $aData = "participant_id = '".mysql_real_escape_string($writearray['participant_id'])."'"; + } else { + $dupreason="nameemail"; + $aData = "firstname = '".mysql_real_escape_string($writearray['firstname'])."' AND lastname = '".mysql_real_escape_string($writearray['lastname'])."' AND email = '".mysql_real_escape_string($writearray['email'])."' AND owner_uid = '".Yii::app()->session['loginID']."'"; + } //End of HACK - $aData = Participants::model()->checkforDuplicate($aData); - if ($aData == true) { + $aData = Participants::model()->checkforDuplicate($aData, "participant_id"); + if ($aData !== false) { $thisduplicate = 1; $dupcount++; + if($overwrite=="true") + { + //Although this person already exists, we want to update the mapped attribute values + if (!empty($mappedarray)) { + //The mapped array contains the attributes we are + //saving in this import + foreach ($mappedarray as $attid => $attname) { + if (!empty($attname)) { + $bData = array('participant_id' => $aData, + 'attribute_id' => $attid, + 'value' => $writearray[$attname]); + Participant_attribute::model()->updateParticipantAttributeValue($bData); + } else { + //If the value is empty, don't write the value + } + } + $overwritten++; + } + } } if ($thisduplicate == 1) { $dupfound = true; @@ -1573,7 +1613,7 @@ function uploadCSV() } } if (!$dupfound && !$invalidemail) { - //If it isn't a duplicate value or an invalid email, process the entry + //If it isn't a duplicate value or an invalid email, process the entry as a new participant //First, process the known fields if (!isset($writearray['participant_id']) || $writearray['participant_id'] == "") { @@ -1635,6 +1675,7 @@ function uploadCSV() } $recordcount++; } + unlink($sFilePath); $clang = $this->getController()->lang; $aData = array(); @@ -1649,6 +1690,8 @@ function uploadCSV() $aData['invalidattribute'] = $invalidattribute; $aData['mandatory'] = $mandatory; $aData['invalidparticipantid'] = $invalidparticipantid; + $aData['overwritten'] = $overwritten; + $aData['dupreason'] = $dupreason; $this->getController()->render('/admin/participants/uploadSummary_view', $aData); } @@ -1702,7 +1745,7 @@ function shareParticipants() 'share_uid' => $iShareUserId, 'date_added' => date(DATE_W3C, $time), 'can_edit' => $bCanEdit); - ParticipantShares::storeParticipantShare($aData); + ParticipantShares::model()->storeParticipantShare($aData); $i++; } @@ -1711,15 +1754,30 @@ function shareParticipants() /* * Responsible for copying the participant from tokens to the central Database + * + * TODO: Most of the work for this function is in the participants model file + * but it doesn't belong there. */ function addToCentral() { $newarr = Yii::app()->request->getPost('newarr'); $mapped = Yii::app()->request->getPost('mapped'); - $response = Participants::copyToCentral(Yii::app()->request->getPost('surveyid'), $newarr, $mapped); + $overwriteauto = Yii::app()->request->getPost('overwriteauto'); + $overwriteman = Yii::app()->request->getPost('overwriteman'); + $createautomap = Yii::app()->request->getPost('createautomap'); + + $response = Participants::model()->copyToCentral(Yii::app()->request->getPost('surveyid'), $newarr, $mapped, $overwriteauto, $overwriteman); $clang = $this->getController()->lang; - printf($clang->gT("%s participants have been copied, %s participants have not been copied because they already exist"), $response['success'], $response['duplicate']); + printf($clang->gT("%s participants have been copied to the central participants table"), $response['success']); + if($response['duplicate'] > 0) { + echo "\r\n"; + printf($clang->gT("%s entries were not copied because they already existed"), $response['duplicate']); + } + if($response['overwriteman']=="true" || $response['overwriteauto']) { + echo "\r\n"; + $clang->eT("Attribute values for existing participants have been updated from the token records"); + } } /* @@ -1727,10 +1785,23 @@ function addToCentral() */ function addToToken() { - $response = Participants::copytoSurvey(Yii::app()->request->getPost('participantid'), Yii::app()->request->getPost('surveyid'), Yii::app()->request->getPost('attributeid')); + $response = Participants::model()->copytoSurvey(Yii::app()->request + ->getPost('participantid'), + Yii::app()->request + ->getPost('surveyid'), Yii::app() + ->request->getPost('attributeid') + ); $clang = $this->getController()->lang; - printf($clang->gT("%s participants have been copied, %s participants have not been copied because they already exist"), $response['success'], $response['duplicate']); + printf($clang->gT("%s participants have been copied to the survey token table"), $response['success']); + if($response['duplicate']>0) { + echo "\r\n"; + printf($clang->gT("%s entries were not copied because they already existed"), $response['duplicate']); + } + if($response['overwrite']=="true") { + echo "\r\n"; + $clang->eT("Attribute values for existing participants have been updated from the participants records"); + } } /* @@ -1742,14 +1813,25 @@ function addToTokenattmap() $iSurveyId = Yii::app()->request->getPost('surveyid'); $mapped = Yii::app()->request->getPost('mapped'); $newcreate = Yii::app()->request->getPost('newarr'); + $overwriteauto = Yii::app()->request->getPost('overwrite'); + $overwriteman = Yii::app()->request->getPost('overwriteman'); + $overwritest = Yii::app()->request->getPost('overwritest'); + $createautomap = Yii::app()->request->getPost('createautomap'); + $clang = $this->getController()->lang; - if (empty($newcreate[0])) - { - $newcreate = array(); - } - $response = Participants::copytosurveyatt($iSurveyId, $mapped, $newcreate, $iParticipantId); + if (empty($newcreate[0])) { $newcreate = array(); } + + $response = Participants::model()->copytosurveyatt($iSurveyId, $mapped, $newcreate, $iParticipantId, $overwriteauto, $overwriteman, $overwritest, $createautomap); - printf($clang->gT("%s participants have been copied,%s participants have not been copied because they already exist"), $response['success'], $response['duplicate']); + printf($clang->gT("%s participants have been copied to the survey token table"), $response['success']); + if($response['duplicate']>0) { + echo "\r\n"; + printf($clang->gT("%s entries were not copied because they already existed"), $response['duplicate']); + } + if($response['overwriteauto']=="true" || $response['overwriteman']=="true") { + echo "\r\n"; + $clang->eT("Attribute values for existing participants have been updated from the participants records"); + } } /* @@ -1759,14 +1841,20 @@ function attributeMap() { Yii::app()->loadHelper('common'); $this->getController()->_js_admin_includes(Yii::app()->getConfig('adminscripts') . "attributeMap.js"); - $this->getController()->_css_admin_includes(Yii::app()->getConfig('styleurl') . "admin/".Yii::app()->getConfig('admintheme')."/attributeMap.css"); + $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') ."attributeMap.css"); $iSurveyId = Yii::app()->request->getPost('survey_id'); $redirect = Yii::app()->request->getPost('redirect'); $count = Yii::app()->request->getPost('count'); $iParticipantId = Yii::app()->request->getPost('participant_id'); - $attributes = ParticipantAttributeNames::getAttributes(); - $arr = Tokens_dynamic::model($iSurveyId)->find(); + $attributes = ParticipantAttributeNames::model()->getAttributes(); + $tokenattributefieldnames = getTokenFieldsAndNames($iSurveyId, TRUE); + /* $arr = Yii::app()->db + ->createCommand() + ->select('*') + ->from("{{tokens_$iSurveyId}}") + ->queryRow(); + if (is_array($arr)) { $tokenfieldnames = array_keys($arr); @@ -1775,25 +1863,25 @@ function attributeMap() else { $tokenattributefieldnames = array(); - } + } */ - $selectedattribute = array(); - $selectedcentralattribute = array(); - $alreadymappedattid = array(); + $selectedattribute = array(); //List of existing attribute fields that are not mapped + $selectedcentralattribute = array(); //List of attributes that haven't already been mapped + $alreadymappedattid = array(); //List of fields already mapped to this tokens table $alreadymappedattname = array(); $i = 0; $j = 0; foreach ($tokenattributefieldnames as $key => $value) { - if (is_numeric($value[10])) + if (is_numeric($key[10])) //Assumes that if the 11th character is a number, it must be a token-table created attribute { - $selectedattribute[$i] = $value; + $selectedattribute[$key] = $value; $i++; } else { - array_push($alreadymappedattid, substr($value, 15)); + array_push($alreadymappedattid, substr($key, 15)); } } foreach ($attributes as $row) @@ -1830,13 +1918,14 @@ function attributeMapToken() Yii::app()->loadHelper('common'); $iSurveyId = Yii::app()->request->getQuery('sid'); - $attributes = ParticipantAttributeNames::getAttributes(); + $attributes = ParticipantAttributeNames::model()->getAttributes(); $tokenattributefieldnames = getTokenFieldsAndNames($iSurveyId, TRUE); $selectedattribute = array(); $selectedcentralattribute = array(); $alreadymappedattid = array(); $alreadymappedattdisplay = array(); + $alreadymappedattnames = array(); $i = 0; $j = 0; @@ -1848,8 +1937,20 @@ function attributeMapToken() } else { - array_push($alreadymappedattid, substr($key, 15)); - array_push($alreadymappedattdisplay, $key); + $attributeid=substr($key,15); + $continue=false; + foreach($attributes as $attribute) { + if($attribute['attribute_id']==$attributeid) { + $continue=true; + } + } + if($continue) { + array_push($alreadymappedattid, $attributeid); + array_push($alreadymappedattdisplay, $key); + $alreadymappedattnames[$key]=$value; + } else { + $selectedattribute[$value]=$key; + } } } foreach ($attributes as $row) @@ -1863,17 +1964,23 @@ function attributeMapToken() $aData = array( 'attribute' => $selectedcentralattribute, 'tokenattribute' => $selectedattribute, - 'alreadymappedattributename' => $alreadymappedattdisplay + 'alreadymappedattributename' => $alreadymappedattdisplay, + 'alreadymappedattdescription' => $alreadymappedattnames ); $this->_renderWrappedTemplate('participants', 'attributeMapToken', $aData); } + /** + * This function deletes the uploaded csv file if the import is cancelled + * + */ function mapCSVcancelled() { unlink(Yii::app()->getConfig('tempdir') . '/' . basename(Yii::app()->request->getPost('fullfilepath'))); } + function blacklistParticipant() { $this->load->model('participants_model'); diff --git a/application/controllers/admin/printablesurvey.php b/application/controllers/admin/printablesurvey.php index e669f0328be..948f78e6a1b 100644 --- a/application/controllers/admin/printablesurvey.php +++ b/application/controllers/admin/printablesurvey.php @@ -74,8 +74,6 @@ function index($surveyid, $lang = null) $surveyfaxto = $desrow['faxto']; $dateformattype = $desrow['surveyls_dateformat']; - $data['welcome']=$welcome; - $data['surveydesc']=$surveydesc; if(isset($_POST['printableexport'])){$pdf->titleintopdf($surveyname,$surveydesc);} @@ -96,14 +94,19 @@ function index($surveyid, $lang = null) }; //define('PRINT_TEMPLATE' , '/templates/print/' , true); - if(is_file(Yii::app()->getConfig('usertemplaterootdir').'/'.$template.'/print_survey.pstpl')) + if(is_file(Yii::app()->getConfig('usertemplaterootdir').DIRECTORY_SEPARATOR.$template.DIRECTORY_SEPARATOR.'print_survey.pstpl')) { - define('PRINT_TEMPLATE_DIR' , Yii::app()->getConfig('usertemplaterootdir').'/'.$template.'/' , true); + define('PRINT_TEMPLATE_DIR' , Yii::app()->getConfig('usertemplaterootdir').DIRECTORY_SEPARATOR.$template.DIRECTORY_SEPARATOR , true); define('PRINT_TEMPLATE_URL' , Yii::app()->getConfig('usertemplaterooturl').'/'.$template.'/' , true); } + elseif(is_file(Yii::app()->getConfig('usertemplaterootdir').'/'.$template.'/print_survey.pstpl')) + { + define('PRINT_TEMPLATE_DIR' , Yii::app()->getConfig('standardtemplaterootdir').DIRECTORY_SEPARATOR.$template.DIRECTORY_SEPARATOR , true); + define('PRINT_TEMPLATE_URL' , Yii::app()->getConfig('standardtemplaterooturl').'/'.$template.'/' , true); + } else { - define('PRINT_TEMPLATE_DIR' , Yii::app()->getConfig('standardtemplaterootdir').'/default/' , true); + define('PRINT_TEMPLATE_DIR' , Yii::app()->getConfig('standardtemplaterootdir').DIRECTORY_SEPARATOR.'default'.DIRECTORY_SEPARATOR , true); define('PRINT_TEMPLATE_URL' , Yii::app()->getConfig('standardtemplaterooturl').'/default/' , true); } @@ -1260,7 +1263,7 @@ function index($surveyid, $lang = null) } else { $checkboxlayout=false; } - $mearesult=Questions::model()->getAllRecords(" parent_qid='{$deqrow['qid']}' AND language='{$surveyprintlang}' ", array('question_order')); + $mearesult=Questions::model()->getAllRecords(" parent_qid='{$deqrow['qid']}' and scale_id=0 AND language='{$surveyprintlang}' ", array('question_order')); // if ($checkboxlayout === false) @@ -1283,7 +1286,7 @@ function index($surveyid, $lang = null) $question['QUESTION_TYPE_HELP'] .= self::_array_filter_help($qidattributes, $surveyprintlang, $surveyid); $question['ANSWER'] .= "\n\n\t\n\t\t\n\t\t\t\n"; - $fresult=Questions::model()->getAllRecords(" parent_qid='{$deqrow['qid']}' AND language='{$surveyprintlang}' ", array('question_order')); + $fresult=Questions::model()->getAllRecords(" parent_qid='{$deqrow['qid']}' and scale_id=1 AND language='{$surveyprintlang}' ", array('question_order')); $fcount = $fresult->getRowCount(); $fwidth = "120"; @@ -1308,12 +1311,13 @@ function index($surveyid, $lang = null) $a=1; //Counter for pdfoutput $rowclass = 'array1'; + $result = $mearesult->readAll(); foreach ($result as $frow) { $question['ANSWER'] .= "\t\n"; $rowclass = alternation($rowclass,'row'); - $answertext=$mearow['question']; + $answertext=$frow['question']; if (strpos($answertext,'|')) {$answertext=substr($answertext,0, strpos($answertext,'|'));} $question['ANSWER'] .= "\t\t\t\t\t\n"; //$printablesurveyoutput .="\t\t\t\t\t\n\t\t\t
 
$answertext"; @@ -1690,7 +1694,7 @@ function index($surveyid, $lang = null) } $survey_output['THEREAREXQUESTIONS'] = str_replace( '{NUMBEROFQUESTIONS}' , $total_questions , $clang->gT('There are {NUMBEROFQUESTIONS} questions in this survey')); - $data['numques']=$survey_output['THEREAREXQUESTIONS']; + // START recursive tag stripping. // PHP 5.1.0 introduced the count parameter for preg_replace() and thus allows this procedure to run with only one regular expression. // Previous version of PHP needs two regular expressions to do the same thing and thus will run a bit slower. @@ -1759,7 +1763,6 @@ function index($surveyid, $lang = null) } $survey_output['GROUPS'] = preg_replace( '/(]*>){NOTEMPTY}(<\/div>)/' , '\1 \2' , $survey_output['GROUPS']); - $data['survey_output']=$survey_output; // END recursive empty tag stripping. @@ -1776,7 +1779,7 @@ function index($surveyid, $lang = null) $pdf->titleintopdf($clang->gT("Submit Your Survey."),$clang->gT("Thank you for completing this survey.")); $pdf->write_out($clang->gT($surveyname)." ".$surveyid.".pdf"); } else { - $this->getController()->render('/admin/survey/printablesurvey_view', $data); + echo self::_populate_template( 'survey' , $survey_output ); } } diff --git a/application/controllers/admin/question.php b/application/controllers/admin/question.php index b7cedacb13f..4684a50c31c 100644 --- a/application/controllers/admin/question.php +++ b/application/controllers/admin/question.php @@ -112,10 +112,6 @@ public function editdefaultvalues($surveyid, $gid, $qid) $gid = sanitize_int($gid); $qid = sanitize_int($qid); - $aData['display']['menu_bars']['surveysummary'] = 'editdefaultvalues'; - $aData['display']['menu_bars']['gid_action'] = 'editdefaultvalues'; - $aData['display']['menu_bars']['qid_action'] = 'editdefaultvalues'; - $clang = $this->getController()->lang; Yii::app()->loadHelper('surveytranslator'); @@ -172,8 +168,7 @@ public function editdefaultvalues($surveyid, $gid, $qid) )); $defaultvalue = $defaultvalue != null ? $defaultvalue->defaultvalue : null; - $langopts[$language][$questionrow['type']]['Ydefaultvalue'] = - $defaultvalue == null ? '' : $defaultvalue->defaultvalue; + $langopts[$language][$questionrow['type']]['Ydefaultvalue'] = $defaultvalue; } } } @@ -218,6 +213,18 @@ public function editdefaultvalues($surveyid, $gid, $qid) } } } + if ($qtproperties[$questionrow['type']]['answerscales'] == 0 && + $qtproperties[$questionrow['type']]['subquestions'] == 0) + { + $defaultvalue = Defaultvalues::model()->findByAttributes(array( + 'specialtype' => '', + 'qid' => $qid, + 'scale_id' => 0, + 'language' => $language + )); + $langopts[$language][$questionrow['type']][0] = $defaultvalue != null ? $defaultvalue->defaultvalue : null; + } + } $aData = array( @@ -230,6 +237,8 @@ public function editdefaultvalues($surveyid, $gid, $qid) 'qtproperties' => $qtproperties, 'baselang' => $baselang, ); + $aData['display']['menu_bars']['surveysummary'] = 'editdefaultvalues'; + $aData['display']['menu_bars']['qid_action'] = 'editdefaultvalues'; $this->_renderWrappedTemplate('survey/Question', 'editdefaultvalues_view', $aData); } @@ -1080,20 +1089,31 @@ public function preview($surveyid, $qid, $lang = null) "; - - //hide/show the filter - //filtersettings by default aren't shown when showing the results - //$statisticsoutput .= ''; + + //Call the javascript file $this->getController()->_js_admin_includes(Yii::app()->getConfig('adminscripts') . 'statistics.js'); $aData['display']['menu_bars']['browse'] = $clang->gT("Quick statistics"); @@ -209,7 +154,7 @@ public function run($surveyid, $subaction = null) */ //store all the data in $rows - $rows = Questions::getQuestionList($surveyid, $language); + $rows = Questions::model()->getQuestionList($surveyid, $language); //SORT IN NATURAL ORDER! usort($rows, 'groupOrderThenQuestionOrder'); @@ -243,7 +188,7 @@ public function run($surveyid, $subaction = null) $error.='
'.$clang->gT('You do not have the Freetype Library installed. Showing charts requires the Freetype library to function properly.'); $error.='
'.$clang->gT('visit http://us2.php.net/manual/en/ref.image.php for more information').'
'; } - + if ($grapherror) { unset($_POST['usegraph']); @@ -274,11 +219,6 @@ public function run($surveyid, $subaction = null) $aData['selectinc'] = $selectinc; $aData['error'] = $error; - //if ($selecthide!='') - //{ - // $statisticsoutput .= " style='display:none' "; - //} - $survlangs = Survey::model()->findByPk($surveyid)->additionalLanguages; $survlangs[] = Survey::model()->findByPk($surveyid)->language; $aData['survlangs'] = $survlangs; @@ -286,13 +226,10 @@ public function run($surveyid, $subaction = null) //if the survey contains timestamps you can filter by timestamp, too - //Output selector - //second row below options -> filter settings headline - $filterchoice_state=returnGlobal('filterchoice_state'); $aData['filterchoice_state'] = $filterchoice_state; @@ -357,7 +294,7 @@ public function run($surveyid, $subaction = null) { case "K": // Multiple Numerical //get answers - $result = Questions::getQuestionsForStatistics('title as code, question as answer', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title as code, question as answer', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); $aData['result'][$key1]['key1'] = $result; break; @@ -366,7 +303,7 @@ public function run($surveyid, $subaction = null) case "Q": // Multiple Short Text //get subqestions - $result = Questions::getQuestionsForStatistics('title as code, question as answer', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title as code, question as answer', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); $aData['result'][$key1] = $result; break; @@ -375,7 +312,7 @@ public function run($surveyid, $subaction = null) case "A": // ARRAY OF 5 POINT CHOICE QUESTIONS //get answers - $result = Questions::getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); $aData['result'][$key1] = $result; break; @@ -383,7 +320,7 @@ public function run($surveyid, $subaction = null) //just like above only a different loop case "B": // ARRAY OF 10 POINT CHOICE QUESTIONS - $result = Questions::getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); $aData['result'][$key1] = $result; break; @@ -391,7 +328,7 @@ public function run($surveyid, $subaction = null) case "C": // ARRAY OF YES\No\$clang->gT("Uncertain") QUESTIONS //get answers - $result = Questions::getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); $aData['result'][$key1] = $result; break; @@ -399,26 +336,26 @@ public function run($surveyid, $subaction = null) //similiar to the above one case "E": // ARRAY OF Increase/Same/Decrease QUESTIONS - $result = Questions::getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); $aData['result'][$key1] = $result; break; case ";": //ARRAY (Multi Flex) (Text) - $result = Questions::getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}' AND scale_id = 0", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}' AND scale_id = 0", 'question_order'); $aData['result'][$key1] = $result; foreach($result as $key => $row) { - $fresult = Questions::getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}' AND scale_id = 1", 'question_order'); + $fresult = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}' AND scale_id = 1", 'question_order'); $aData['fresults'][$key1][$key] = $fresult; } break; case ":": //ARRAY (Multi Flex) (Numbers) - $result = Questions::getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}' AND scale_id = 0", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}' AND scale_id = 0", 'question_order'); $aData['result'][$key1] = $result; foreach($result as $row) { - $fresult = Questions::getQuestionsForStatistics('*', "parent_qid=$flt[0] AND language = '{$language}' AND scale_id = 1", 'question_order, title'); + $fresult = Questions::model()->getQuestionsForStatistics('*', "parent_qid=$flt[0] AND language = '{$language}' AND scale_id = 1", 'question_order, title'); $aData['fresults'][$key1] = $fresult; } break; @@ -430,13 +367,13 @@ public function run($surveyid, $subaction = null) case "F": // FlEXIBLE ARRAY case "H": // ARRAY (By Column) //Get answers. We always use the answer code because the label might be too long elsewise - $result = Questions::getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); $aData['result'][$key1] = $result; //check all the answers foreach($result as $row) { - $fresult = Answers::getQuestionsForStatistics('*', "qid=$flt[0] AND language = '{$language}'", 'sortorder, code'); + $fresult = Answers::model()->getQuestionsForStatistics('*', "qid=$flt[0] AND language = '{$language}'", 'sortorder, code'); $aData['fresults'][$key1] = $fresult; } @@ -448,14 +385,14 @@ public function run($surveyid, $subaction = null) case "R": //RANKING //get some answers - $result = Answers::getQuestionsForStatistics('code, answer', "qid=$flt[0] AND language = '{$language}'", 'sortorder, answer'); + $result = Answers::model()->getQuestionsForStatistics('code, answer', "qid=$flt[0] AND language = '{$language}'", 'sortorder, answer'); $aData['result'][$key1] = $result; break; case "1": // MULTI SCALE //get answers - $result = Questions::getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid=$flt[0] AND language = '{$language}'", 'question_order'); $aData['result'][$key1] = $result; //loop through answers foreach($result as $key => $row) @@ -466,7 +403,7 @@ public function run($surveyid, $subaction = null) $aData['dshresults'][$key1][$key] = $dshresult; - $fresult = Answers::getQuestionsForStatistics('*', "qid=$flt[0] AND language = '{$language}' AND scale_id = 0", 'sortorder, code'); + $fresult = Answers::model()->getQuestionsForStatistics('*', "qid=$flt[0] AND language = '{$language}' AND scale_id = 0", 'sortorder, code'); $aData['fresults'][$key1][$key] = $fresult; @@ -480,7 +417,7 @@ public function run($surveyid, $subaction = null) case "M": //M - Multiple choice //get answers - $result = Questions::getQuestionsForStatistics('title, question', "parent_qid = $flt[0] AND language = '$language'", 'question_order'); + $result = Questions::model()->getQuestionsForStatistics('title, question', "parent_qid = $flt[0] AND language = '$language'", 'question_order'); $aData['result'][$key1] = $result; break; @@ -495,7 +432,7 @@ public function run($surveyid, $subaction = null) default: //get answers - $result = Answers::getQuestionsForStatistics('code, answer', "qid=$flt[0] AND language = '$language'", 'sortorder, answer'); + $result = Answers::model()->getQuestionsForStatistics('code, answer', "qid=$flt[0] AND language = '$language'", 'sortorder, answer'); $aData['result'][$key1] = $result; break; @@ -509,8 +446,6 @@ public function run($surveyid, $subaction = null) //used to adjust linebreaks $previousquestiontype = $flt[2]; - //Group close - //$statisticsoutput .= "\n\t\t\t\t
\n"; } // ----------------------------------- END FILTER FORM --------------------------------------- @@ -519,18 +454,16 @@ public function run($surveyid, $subaction = null) //Show Summary results if (isset($summary) && $summary) { - if(isset($_POST['usegraph'])) - { - $usegraph = 1; - } - else - { - $usegraph = 0; - } + $usegraph=isset($_POST['usegraph']) ? 1 : 0; $aData['usegraph'] = $usegraph; + $showtextinline=isset($_POST['showtextinline']) ? 1 : 0; + $aData['showtextinline'] = $showtextinline; $outputType = $_POST['outputtype']; - switch($outputType){ + $selects=buildSelects($summary, $surveyid, $statlang); + $aData['sql']=implode(" AND ", $selects); + + switch($outputType){ case 'html': $statisticsoutput .= generate_statistics($surveyid,$summary,$summary,$usegraph,$outputType,'DD',$statlang); break; @@ -543,22 +476,44 @@ public function run($surveyid, $subaction = null) exit; break; default: - break; - } } //end if -> show summary results - + + $aData['sStatisticsLanguage']=$statlang; $aData['output'] = $statisticsoutput; + $aData['summary'] = $summary; $this->_renderWrappedTemplate('export', 'statistics_view', $aData); } + /* Returns a simple list of values in a particular column, that meet the + * requirements of the SQL + * + * */ + function listcolumn($surveyid, $column, $sql, $sortby="", $sortmethod="", $sorttype="") + { + $search['condition']=$column." != ''"; + if($sorttype=='N') {$sortby = "($sortby * 1)";} //Converts text sorting into numerical sorting + if($sortby != "") $search['order']=$sortby.' '.$sortmethod; + $results=Survey_dynamic::model($surveyid)->findAll($search); + foreach($results as $row) { + $output[]=array("id"=>$row['id'], "value"=>$row[$column]); + } + $aData['surveyid']=$surveyid; + $aData['data']=$output; + $aData['column']=$column; + $aData['sortby']=$sortby; + $aData['sortmethod']=$sortmethod; + $aData['sorttype']=$sorttype; + $this->getController()->render('export/statistics_browse_view', $aData); + } + function graph() { - Yii::app()->loadHelper('admin/statistics_helper'); + Yii::app()->loadHelper('admin/statistics'); Yii::app()->loadHelper("surveytranslator"); // Initialise PCHART @@ -570,8 +525,8 @@ function graph() $aData['success'] = 1; - if (isset($_POST['cmd']) || !isset($_POST['id'])) { - list($qsid, $qgid, $qqid) = explode("X", substr($_POST['id'], 1), 3); + if (isset($_POST['cmd']) && isset($_POST['id'])) { + list($qsid, $qgid, $qqid) = explode("X", substr($_POST['id'], 0), 3); $qtype = substr($_POST['id'], 0, 1); $aattr = getQuestionAttributeValues($qqid, substr($_POST['id'], 0, 1)); $field = substr($_POST['id'], 1); @@ -654,7 +609,8 @@ function graph() $aData['success'] = 0; } - $this->_renderWrappedTemplate('export', 'statistics_graph_view', $aData); + //$this->_renderWrappedTemplate('export', 'statistics_graph_view', $aData); + $this->getController()->render('export/statistics_graph_view', $aData); } /** diff --git a/application/controllers/admin/surveyadmin.php b/application/controllers/admin/surveyadmin.php index eccb0e4ee1d..f64023093e6 100644 --- a/application/controllers/admin/surveyadmin.php +++ b/application/controllers/admin/surveyadmin.php @@ -38,11 +38,6 @@ class SurveyAdmin extends Survey_Common_Action public function __construct($controller, $id) { parent::__construct($controller, $id); - - if (Yii::app()->session['USER_RIGHT_SUPERADMIN'] != 1) - { - die(); - } } /** @@ -295,8 +290,8 @@ public function deactivate($iSurveyID = null) //Update the auto_increment value from the table before renaming $new_autonumber_start = 0; - $query = "SELECT id FROM ".Yii::app()->db->quoteTableName($oldtable)." ORDER BY id desc LIMIT 1"; - $result = Yii::app()->db->createCommand($query)->query(); + $query = "SELECT id FROM ".Yii::app()->db->quoteTableName($oldtable)." ORDER BY id desc"; + $result = Yii::app()->db->createCommand($query)->limit(1)->query(); if ($result->getRowCount() > 0) { foreach ($result->readAll() as $row) @@ -360,6 +355,9 @@ public function deactivate($iSurveyID = null) */ public function activate($iSurveyID) { + if (!hasSurveyPermission($iSurveyID, 'surveyactivation', 'update')) die(); + $clang = Yii::app()->lang; + $iSurveyID = (int) $iSurveyID; $aData = array(); @@ -402,7 +400,52 @@ public function activate($iSurveyID) $survey->save(); } - $aViewUrls['output'] = activateSurvey($iSurveyID); + $aResult=activateSurvey($iSurveyID); + if (isset($aResult['error'])) + { + $aViewUrls['output']= "
\n
\n" . + "
".$clang->gT("Activate Survey")." ($surveyid)
\n"; + if ($aResult['error']=='surveytablecreation') + { + $aViewUrls['output'].="
".$clang->gT("Survey table could not be created.")."
\n"; + } + else + { + $aViewUrls['output'].="
".$clang->gT("Timings table could not be created.")."
\n"; + } + $aViewUrls['output'].="

" . + $clang->gT("Database error!!")."\n " ."\n" . + "

".implode(' ', $createsurvey)."
\n + ".$clang->gT("Main Admin Screen")."\n
" ; + } + else + { + $aViewUrls['output']= "
\n
\n" + ."
".$clang->gT("Activate Survey")." ({$iSurveyID})
\n" + ."
".$clang->gT("Survey has been activated. Results table has been successfully created.")."


\n"; + + if (isset($aResult['warning'])) + { + $aViewUrls['output'] .= "
" + .$clang->gT("The required directory for saving the uploaded files couldn't be created. Please check file premissions on the /upload/surveys directory.") + ."
"; + } + + if ($survey->allowregister=='Y') + { + $aViewUrls['output'] .= $clang->gT("This survey allows public registration. A token table must also be created.")."

\n" + ."getController()->createUrl("admin/tokens/index/surveyid/".$iSurveyID))."\" />\n"; + } + else + { + $aViewUrls['output'] .= $clang->gT("This survey is now active, and responses can be recorded.")."

\n" + ."".$clang->gT("Open-access mode").": ".$clang->gT("No invitation code is needed to complete the survey.")."
".$clang->gT("You can switch to the closed-access mode by initialising a token table with the button below.")."

\n" + ."getController()->createUrl("admin/tokens/index/surveyid/".$iSurveyID))."\" />\n" + ."getController()->createUrl("admin/survey/view/surveyid/".$iSurveyID))."\" />\n"; + } + $aViewUrls['output'] .= "

 \n"; + } + $this->_renderWrappedTemplate('survey', $aViewUrls, $aData); } @@ -488,116 +531,119 @@ public function getSurveys_json() //!!! Is this even possible to execute? if (empty(Yii::app()->session['USER_RIGHT_SUPERADMIN'])) $surveys->permission(Yii::app()->user->getId()); + $surveys = $surveys->with(array('languagesettings'=>array('condition'=>'surveyls_language=language'), 'owner'))->findAll(); $aSurveyEntries = new stdClass(); $aSurveyEntries->page = 1; foreach ($surveys as $rows) { - $aSurveyEntry = array(); $rows = array_merge($rows->attributes, $rows->languagesettings[0]->attributes, $rows->owner->attributes); - - // Set status - if ($rows['active'] == "Y" && $rows['expires'] != '' && $rows['expires'] < dateShift(date("Y-m-d H:i:s"), "Y-m-d", Yii::app()->getConfig('timeadjust'))) - { - $aSurveyEntry[] = '' . $clang->gT('; - } - elseif ($rows['active'] == "Y" && $rows['startdate'] != '' && $rows['startdate'] > dateShift(date("Y-m-d H:i:s"), "Y-m-d", Yii::app()->getConfig('timeadjust'))) - { - $aSurveyEntry[] = '' . $clang->gT('; - } - elseif ($rows['active'] == "Y") + if($rows['users_name'] == Yii::app()->session['user'] || Yii::app()->session['USER_RIGHT_SUPERADMIN'] == 1)//If is owner or superadmin show survey. { - if (hasSurveyPermission($rows['sid'], 'surveyactivation', 'update')) + $aSurveyEntry = array(); + // Set status + if ($rows['active'] == "Y" && $rows['expires'] != '' && $rows['expires'] < dateShift(date("Y-m-d H:i:s"), "Y-m-d", Yii::app()->getConfig('timeadjust'))) { - $aSurveyEntry[] = '' . $clang->gT('; + $aSurveyEntry[] = '' . $clang->gT('; } - else + elseif ($rows['active'] == "Y" && $rows['startdate'] != '' && $rows['startdate'] > dateShift(date("Y-m-d H:i:s"), "Y-m-d", Yii::app()->getConfig('timeadjust'))) { - $aSurveyEntry[] = '' . $clang->gT('; + $aSurveyEntry[] = '' . $clang->gT('; } - } - else - { - $condition = "sid={$rows['sid']} AND language='" . $rows['language'] . "'"; - $questionsCountResult = Questions::model()->findAll($condition); - - if (count($questionsCountResult) && hasSurveyPermission($rows['sid'], 'surveyactivation', 'update')) + elseif ($rows['active'] == "Y") { - $aSurveyEntry[] = '' . $clang->gT('; + if (hasSurveyPermission($rows['sid'], 'surveyactivation', 'update')) + { + $aSurveyEntry[] = '' . $clang->gT('; + } + else + { + $aSurveyEntry[] = '' . $clang->gT('; + } } else { - $aSurveyEntry[] = '' . $clang->gT('; + $condition = "sid={$rows['sid']} AND language='" . $rows['language'] . "'"; + $questionsCountResult = Questions::model()->findAll($condition); + + if (count($questionsCountResult) && hasSurveyPermission($rows['sid'], 'surveyactivation', 'update')) + { + $aSurveyEntry[] = '' . $clang->gT('; + } + else + { + $aSurveyEntry[] = '' . $clang->gT('; + } } - } - //Set SID - $aSurveyEntry[] = $rows['sid']; - '' . $rows['sid'] . ''; + //Set SID + $aSurveyEntry[] = $rows['sid']; + '' . $rows['sid'] . ''; - //Set Title - $aSurveyEntry[] = '' . $rows['surveyls_title'] . ''; + //Set Title + $aSurveyEntry[] = '' . $rows['surveyls_title'] . ''; - //Set Date - Yii::import('application.libraries.Date_Time_Converter', true); - $datetimeobj = new Date_Time_Converter(array($rows['datecreated'], "Y-m-d H:i:s")); - $aSurveyEntry[] = '' . $datetimeobj->convert($dateformatdetails['phpdate']); + //Set Date + Yii::import('application.libraries.Date_Time_Converter', true); + $datetimeobj = new Date_Time_Converter(array($rows['datecreated'], "Y-m-d H:i:s")); + $aSurveyEntry[] = '' . $datetimeobj->convert($dateformatdetails['phpdate']); - //Set Owner - $aSurveyEntry[] = $rows['users_name'] . ' ('. $clang->gT('Edit') .')'; + //Set Owner + $aSurveyEntry[] = $rows['users_name'] . ' ('. $clang->gT('Edit') .')'; - //Set Access - if (Yii::app()->db->schema->getTable('{{tokens_' . $rows['sid'] . '}}')) - { - $aSurveyEntry[] = $clang->gT("Closed"); - } - else - { - $aSurveyEntry[] = $clang->gT("Open"); - } + //Set Access + if (Yii::app()->db->schema->getTable('{{tokens_' . $rows['sid'] . '}}')) + { + $aSurveyEntry[] = $clang->gT("Closed"); + } + else + { + $aSurveyEntry[] = $clang->gT("Open"); + } - //Set Anonymous - if ($rows['anonymized'] == "Y") - { - $aSurveyEntry[] = $clang->gT("Yes"); - } - else - { - $aSurveyEntry[] = $clang->gT("No"); - } + //Set Anonymous + if ($rows['anonymized'] == "Y") + { + $aSurveyEntry[] = $clang->gT("Yes"); + } + else + { + $aSurveyEntry[] = $clang->gT("No"); + } - //Set Responses - if ($rows['active'] == "Y") - { - $partial = Survey_dynamic::model($rows['sid'])->countByAttributes(array('submitdate' => null)); - $all = Survey_dynamic::model($rows['sid'])->count(); + //Set Responses + if ($rows['active'] == "Y") + { + $partial = Survey_dynamic::model($rows['sid'])->countByAttributes(array('submitdate' => null)); + $all = Survey_dynamic::model($rows['sid'])->count(); - $aSurveyEntry[] = $all - $partial; - $aSurveyEntry[] = $partial; - $aSurveyEntry[] = $all; + $aSurveyEntry[] = $all - $partial; + $aSurveyEntry[] = $partial; + $aSurveyEntry[] = $all; - $aSurveyEntry['viewurl'] = $this->getController()->createUrl("/admin/survey/view/surveyid/" . $rows['sid']); - if (Yii::app()->db->schema->getTable("{{tokens_" . $rows['sid'] . "}}")) - { - $tokens = Tokens_dynamic::model($rows['sid'])->count(); - $tokenscompleted = Tokens_dynamic::model($rows['sid'])->count(array( - 'condition' => "completed <> 'N'" - )); + $aSurveyEntry['viewurl'] = $this->getController()->createUrl("/admin/survey/view/surveyid/" . $rows['sid']); + if (Yii::app()->db->schema->getTable("{{tokens_" . $rows['sid'] . "}}")) + { + $tokens = Tokens_dynamic::model($rows['sid'])->count(); + $tokenscompleted = Tokens_dynamic::model($rows['sid'])->count(array( + 'condition' => "completed <> 'N'" + )); - $aSurveyEntry[] = $tokens; - $aSurveyEntry[] = ($tokens == 0) ? 0 : round($tokenscompleted / $tokens * 100, 1); + $aSurveyEntry[] = $tokens; + $aSurveyEntry[] = ($tokens == 0) ? 0 : round($tokenscompleted / $tokens * 100, 1); + } + else + { + $aSurveyEntry[] = $aSurveyEntry[] = ''; + } } else { - $aSurveyEntry[] = $aSurveyEntry[] = ''; + $aSurveyEntry[] = $aSurveyEntry[] = $aSurveyEntry[] = $aSurveyEntry[] = $aSurveyEntry[] = ''; } + $aSurveyEntries->rows[] = array('id' => $rows['sid'], 'cell' => $aSurveyEntry); } - else - { - $aSurveyEntry[] = $aSurveyEntry[] = $aSurveyEntry[] = $aSurveyEntry[] = $aSurveyEntry[] = ''; - } - $aSurveyEntries->rows[] = array('id' => $rows['sid'], 'cell' => $aSurveyEntry); } echo ls_json_encode($aSurveyEntries); @@ -668,10 +714,14 @@ public function editlocalsettings($iSurveyID) $aData['surveyid'] = $iSurveyID = sanitize_int($iSurveyID); $aViewUrls = array(); - $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts').'/scripts/admin/surveysettings.js'); + $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts').'admin/surveysettings.js'); if (hasSurveyPermission($iSurveyID, 'surveylocale', 'read')) { + if (hasSurveyPermission($iSurveyID, 'surveylocale', 'update')) + { + Yii::app()->session['FileManagerContext'] = "edit:survey:{$iSurveyID}"; + } $editsurvey = ''; $grplangs = Survey::model()->findByPk($iSurveyID)->additionalLanguages; $baselang = Survey::model()->findByPk($iSurveyID)->language; @@ -842,86 +892,8 @@ public function copy() if ($action == 'importsurvey' && !$aData['bFailed']) { - - if (isset($sExtension) && strtolower($sExtension) == 'csv') - { - $aImportResults = CSVImportSurvey($sFullFilepath, null, (isset($_POST['translinksfields']))); - } - elseif (isset($sExtension) && strtolower($sExtension) == 'lss') - { - $aImportResults = XMLImportSurvey($sFullFilepath, null, null, null, (isset($_POST['translinksfields']))); - } - elseif (isset($sExtension) && strtolower($sExtension) == 'xls') - { - $aImportResults = ExcelImportSurvey($sFullFilepath); - } - elseif (isset($sExtension) && strtolower($sExtension) == 'zip') // Import a survey archive - { - Yii::import("application.libraries.admin.pclzip.pclzip", true); - $pclzip = new PclZip(array('p_zipname' => $sFullFilepath)); - $aFiles = $pclzip->listContent(); - - if ($pclzip->extract(PCLZIP_OPT_PATH, Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR, PCLZIP_OPT_BY_EREG, '/(lss|lsr|lsi|lst)$/') == 0) - { - unset($pclzip); - } - // Step 1 - import the LSS file and activate the survey - foreach ($aFiles as $aFile) - { - if (pathinfo($aFile['filename'], PATHINFO_EXTENSION) == 'lss') - { - //Import the LSS file - $aImportResults = XMLImportSurvey(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename'], null, null, null, true); - // Activate the survey - Yii::app()->loadHelper("admin/activate"); - $activateoutput = activateSurvey($aImportResults['newsid']); - unlink(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename']); - break; - } - } - // Step 2 - import the responses file - foreach ($aFiles as $aFile) - { - if (pathinfo($aFile['filename'], PATHINFO_EXTENSION) == 'lsr') - { - //Import the LSS file - $aResponseImportResults = XMLImportResponses(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename'], $aImportResults['newsid'], $aImportResults['FieldReMap']); - $aImportResults = array_merge($aResponseImportResults, $aImportResults); - unlink(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename']); - break; - } - } - // Step 3 - import the tokens file - if exists - foreach ($aFiles as $aFile) - { - if (pathinfo($aFile['filename'], PATHINFO_EXTENSION) == 'lst') - { - Yii::app()->loadHelper("admin/token"); - if (createTokenTable($aImportResults['newsid'])) - $aTokenCreateResults = array('tokentablecreated' => true); - $aImportResults = array_merge($aTokenCreateResults, $aImportResults); - $aTokenImportResults = XMLImportTokens(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename'], $aImportResults['newsid']); - $aImportResults = array_merge($aTokenImportResults, $aImportResults); - unlink(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename']); - break; - } - } - // Step 4 - import the timings file - if exists - foreach ($aFiles as $aFile) - { - if (pathinfo($aFile['filename'], PATHINFO_EXTENSION) == 'lsi' && tableExists("survey_{$aImportResults['newsid']}_timings")) - { - $aTimingsImportResults = XMLImportTimings(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename'], $aImportResults['newsid'], $aImportResults['FieldReMap']); - $aImportResults = array_merge($aTimingsImportResults, $aImportResults); - unlink(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename']); - break; - } - } - } - else - { - $importerror = true; - } + $aImportResults=importSurveyFile($sFullFilepath,(isset($_POST['translinksfields']))); + if (is_null($aImportResults)) $importerror = true; } elseif ($action == 'copysurvey' && (empty($importerror) || !$importerror)) { @@ -940,7 +912,7 @@ public function copy() unlink($sFullFilepath); } -// if (isset($aImportResults['error']) && $aImportResults['error']) safeDie($aImportResults['error']); + // if (isset($aImportResults['error']) && $aImportResults['error']) safeDie($aImportResults['error']); if (!$aData['bFailed']) { @@ -1534,17 +1506,13 @@ function insert($iSurveyId=null) 'tokenlength' => $_POST['tokenlength'] ); - if(Yii::app()->getConfig('filterxsshtml') && Yii::app()->session['USER_RIGHT_SUPERADMIN'] != 1) - $xssfilter = true; - else - $xssfilter = false; if (!is_null($iSurveyId)) { $aInsertData['wishSID'] = $iSurveyId; } - $iNewSurveyid = Survey::model()->insertNewSurvey($aInsertData, $xssfilter); + $iNewSurveyid = Survey::model()->insertNewSurvey($aInsertData); if (!$iNewSurveyid) die('Survey could not be created.'); @@ -1572,23 +1540,8 @@ function insert($iSurveyId=null) $sDescription = fixCKeditorText($sDescription); $sWelcome = fixCKeditorText($sWelcome); - // Load default email templates for the chosen language - $oLanguage = new Limesurvey_lang($_POST['language']); - $aDefaultTexts = templateDefaultTexts($oLanguage, 'unescaped'); - unset($oLanguage); - - if ($_POST['htmlemail'] && $_POST['htmlemail'] == "Y") - { - $bIsHTMLEmail = true; - $aDefaultTexts['admin_detailed_notification'] = $aDefaultTexts['admin_detailed_notification_css'] . conditionalNewlineToBreak($aDefaultTexts['admin_detailed_notification'], $bIsHTMLEmail, 'unescaped'); - } - else - { - $bIsHTMLEmail = false; - } // Insert base language into surveys_language_settings table - $aInsertData = array('surveyls_survey_id' => $iNewSurveyid, 'surveyls_title' => $sTitle, 'surveyls_description' => $sDescription, @@ -1597,24 +1550,12 @@ function insert($iSurveyId=null) 'surveyls_urldescription' => $_POST['urldescrip'], 'surveyls_endtext' => $_POST['endtext'], 'surveyls_url' => $_POST['url'], - 'surveyls_email_invite_subj' => $aDefaultTexts['invitation_subject'], - 'surveyls_email_invite' => conditionalNewlineToBreak($aDefaultTexts['invitation'], $bIsHTMLEmail, 'unescaped'), - 'surveyls_email_remind_subj' => $aDefaultTexts['reminder_subject'], - 'surveyls_email_remind' => conditionalNewlineToBreak($aDefaultTexts['reminder'], $bIsHTMLEmail, 'unescaped'), - 'surveyls_email_confirm_subj' => $aDefaultTexts['confirmation_subject'], - 'surveyls_email_confirm' => conditionalNewlineToBreak($aDefaultTexts['confirmation'], $bIsHTMLEmail, 'unescaped'), - 'surveyls_email_register_subj' => $aDefaultTexts['registration_subject'], - 'surveyls_email_register' => conditionalNewlineToBreak($aDefaultTexts['registration'], $bIsHTMLEmail, 'unescaped'), - 'email_admin_notification_subj' => $aDefaultTexts['admin_notification_subject'], - 'email_admin_notification' => conditionalNewlineToBreak($aDefaultTexts['admin_notification'], $bIsHTMLEmail, 'unescaped'), - 'email_admin_responses_subj' => $aDefaultTexts['admin_detailed_notification_subject'], - 'email_admin_responses' => $aDefaultTexts['admin_detailed_notification'], 'surveyls_dateformat' => (int) $_POST['dateformat'], 'surveyls_numberformat' => (int) $_POST['numberformat'] ); $langsettings = new Surveys_languagesettings; - $langsettings->insertNewSurvey($aInsertData, $xssfilter); + $langsettings->insertNewSurvey($aInsertData); Yii::app()->session['flashmessage'] = $this->getController()->lang->gT("Survey was successfully added."); diff --git a/application/controllers/admin/surveypermission.php b/application/controllers/admin/surveypermission.php index aa15d97b695..d980255f2b7 100644 --- a/application/controllers/admin/surveypermission.php +++ b/application/controllers/admin/surveypermission.php @@ -36,12 +36,12 @@ function index($surveyid) if(hasSurveyPermission($surveyid,'survey','read')) { - $aBaseSurveyPermissions=Survey_permissions::getBasePermissions(); + $aBaseSurveyPermissions=Survey_permissions::model()->getBasePermissions(); $this->getController()->_js_admin_includes(Yii::app()->baseUrl.'/scripts/jquery/jquery.tablesorter.min.js'); $this->getController()->_js_admin_includes(Yii::app()->baseUrl.'/scripts/admin/surveysecurity.js'); - $result2 = Survey_permissions::getUserDetails($surveyid); + $result2 = Survey_permissions::model()->getUserDetails($surveyid); $surveysecurity ="
".$clang->gT("Survey permissions")."
\n" . "" @@ -219,7 +219,7 @@ function addusergroup($surveyid) if( (count($result) > 0 && in_array($postusergroupid,getSurveyUserGroupList('simpleugidarray',$surveyid))) ||Yii::app()->session['USER_RIGHT_SUPERADMIN'] == 1) { if($postusergroupid > 0){ - $result2 = User::getCommonUID($surveyid, $postusergroupid); //Checked + $result2 = User::model()->getCommonUID($surveyid, $postusergroupid); //Checked if($result2->getRowCount() > 0) { foreach ($result2->readAll() as $row2 ) @@ -302,7 +302,7 @@ function adduser($surveyid) if($postuserid > 0){ - $isrresult = Survey_permissions::insertSomeRecords(array('sid' => $surveyid, 'uid' => $postuserid, 'permission' => 'survey', 'read_p' => 1)); + $isrresult = Survey_permissions::model()->insertSomeRecords(array('sid' => $surveyid, 'uid' => $postuserid, 'permission' => 'survey', 'read_p' => 1)); if($isrresult) { @@ -405,7 +405,7 @@ function set($surveyid) . "\n"; //content - $aBasePermissions=Survey_permissions::getBasePermissions(); + $aBasePermissions=Survey_permissions::model()->getBasePermissions(); $oddcolumn=false; foreach($aBasePermissions as $sPermissionKey=>$aCRUDPermissions) @@ -548,7 +548,7 @@ function surveyright($surveyid) $iOwnerID=$resrow['owner_id']; } - $aBaseSurveyPermissions = Survey_permissions::getBasePermissions(); + $aBaseSurveyPermissions = Survey_permissions::model()->getBasePermissions(); $aPermissions=array(); foreach ($aBaseSurveyPermissions as $sPermissionKey=>$aCRUDPermissions) { @@ -575,14 +575,14 @@ function surveyright($surveyid) { foreach ($oResult as $aRow) { - Survey_permissions::setPermission($aRow->uid, $surveyid, $aPermissions); + Survey_permissions::model()->setPermission($aRow->uid, $surveyid, $aPermissions); } $addsummary .= "
".$clang->gT("Survey permissions for all users in this group were successfully updated.")."
\n"; } } else { - if (Survey_permissions::setPermission($postuserid, $surveyid, $aPermissions)) + if (Survey_permissions::model()->setPermission($postuserid, $surveyid, $aPermissions)) { $addsummary .= "
".$clang->gT("Survey permissions were successfully updated.")."
\n"; } diff --git a/application/controllers/admin/templates.php b/application/controllers/admin/templates.php index 19b20c73fb4..c18f0014e51 100644 --- a/application/controllers/admin/templates.php +++ b/application/controllers/admin/templates.php @@ -76,7 +76,7 @@ public function upload() $aViewUrls = $this->_initialise('default', 'welcome', 'startpage.pstpl', FALSE); $lid = returnGlobal('lid'); $action = returnGlobal('action'); - + if ($action == 'templateupload') { if (Yii::app()->getConfig('demoMode')) $this->getController()->error($clang->gT("Demo mode: Uploading templates is disabled.")); @@ -187,7 +187,7 @@ public function uploadfile() $allowedtemplateuploads=Yii::app()->getConfig('allowedtemplateuploads'); $filename=sanitize_filename($_FILES['upload_file']['name'],false,false);// Don't force lowercase or alphanumeric $fullfilepath=$basedestdir."/".$templatename . "/" . $filename; - + if($action=="templateuploadfile") { if(Yii::app()->getConfig('demoMode')) @@ -200,7 +200,7 @@ public function uploadfile() } elseif(!in_array(substr(strrchr($filename, '.'),1),explode ( "," , $allowedtemplateuploads ))) { - + $uploadresult = $clang->gT("This file type is not allowed to be uploaded."); } else @@ -350,15 +350,16 @@ public function templaterename() { if (returnGlobal('action') == "templaterename" && returnGlobal('newname') && returnGlobal('copydir')) { $clang = Yii::app()->lang; - $newdirname = Yii::app()->getConfig('usertemplaterootdir') . "/" . returnGlobal('newname'); + $newname=sanitize_paranoid_string(returnGlobal('newname')); + $newdirname = Yii::app()->getConfig('usertemplaterootdir') . "/" . $newname; $olddirname = Yii::app()->getConfig('usertemplaterootdir') . "/" . returnGlobal('copydir'); if (isStandardTemplate(returnGlobal('newname'))) - $this->getController()->error(sprintf($clang->gT("Template could not be renamed to `%s`.", "js"), returnGlobal('newname')) . " " . $clang->gT("This name is reserved for standard template.", "js")); + $this->getController()->error(sprintf($clang->gT("Template could not be renamed to `%s`.", "js"), $newname) . " " . $clang->gT("This name is reserved for standard template.", "js")); elseif (rename($olddirname, $newdirname) == false) - $this->getController()->error(sprintf($clang->gT("Directory could not be renamed to `%s`.", "js"), returnGlobal('newname')) . " " . $clang->gT("Maybe you don't have permission.", "js")); + $this->getController()->error(sprintf($clang->gT("Directory could not be renamed to `%s`.", "js"), $newname) . " " . $clang->gT("Maybe you don't have permission.", "js")); else { - $templatename = returnGlobal('newname'); + $templatename = $newname; $this->index("startpage.pstpl", "welcome", $templatename); } } @@ -378,7 +379,8 @@ public function templatecopy() // Copies all the files from one template directory to a new one // This is a security issue because it is allowing copying from get variables... Yii::app()->loadHelper('admin/template'); - $newdirname = Yii::app()->getConfig('usertemplaterootdir') . "/" . returnGlobal('newname'); + $newname= sanitize_paranoid_string(returnGlobal('newname')); + $newdirname = Yii::app()->getConfig('usertemplaterootdir') . "/" . $newname; $copydirname = getTemplatePath(returnGlobal('copydir')); $mkdirresult = mkdir_p($newdirname); @@ -392,13 +394,13 @@ public function templatecopy() $this->getController()->error(sprintf($clang->gT("Failed to copy %s to new template directory.", "js"), $file)); } - $templatename = returnGlobal('newname'); + $templatename = $newname; $this->index("startpage.pstpl", "welcome", $templatename); } elseif ($mkdirresult == 2) - $this->getController()->error(sprintf($clang->gT("Directory with the name `%s` already exists - choose another name", "js"), returnGlobal('newname'))); + $this->getController()->error(sprintf($clang->gT("Directory with the name `%s` already exists - choose another name", "js"), $newname)); else - $this->getController()->error(sprintf($clang->gT("Unable to create directory `%s`.", "js"), returnGlobal('newname')) . " " . $clang->gT("Please check the directory permissions.", "js")); + $this->getController()->error(sprintf($clang->gT("Unable to create directory `%s`.", "js"), $newname) . " " . $clang->gT("Please check the directory permissions.", "js")); ; } } diff --git a/application/controllers/admin/tokens.php b/application/controllers/admin/tokens.php index 0be76f1aa23..47ce7828e6f 100644 --- a/application/controllers/admin/tokens.php +++ b/application/controllers/admin/tokens.php @@ -34,7 +34,7 @@ function index($iSurveyId) if (!hasSurveyPermission($iSurveyId, 'tokens', 'read')) { - die("no permissions"); // TODO Replace + die("You do not have permission to view this page"); // TODO Replace } Yii::app()->loadHelper("surveytranslator"); @@ -57,6 +57,9 @@ function index($iSurveyId) } else { + //Check that the tokens table has the required fields + Tokens_dynamic::model($iSurveyId)->checkColumns(); + $aData['thissurvey'] = $thissurvey; $aData['surveyid'] = $iSurveyId; $aData['queries'] = Tokens_dynamic::model($iSurveyId)->summary(); @@ -82,7 +85,7 @@ function bounceprocessing($iSurveyId) $clang = $this->getController()->lang; $thissurvey = getSurveyInfo($iSurveyId); - if (($thissurvey['bounceprocessing'] != 'N' || ($thissurvey['bounceprocessing'] == 'G' && getGlobalSetting('bounceaccounttype') == 'off')) + if (($thissurvey['bounceprocessing'] != 'N' || ($thissurvey['bounceprocessing'] == 'G' && getGlobalSetting('bounceaccounttype') == 'off')) && hasSurveyPermission($iSurveyId, 'tokens', 'update')) { $bouncetotal = 0; @@ -241,22 +244,32 @@ function bounceprocessing($iSurveyId) */ function browse($iSurveyId, $limit = 50, $start = 0, $order = false, $searchstring = false) { + /* Check permissions */ + if (!hasSurveyPermission($iSurveyId, 'tokens', 'read')) + { + die("You do not have permission to view this page"); // TODO Replace + } + // CHECK TO SEE IF A TOKEN TABLE EXISTS FOR THIS SURVEY $bTokenExists = tableExists('{{tokens_' . $iSurveyId . '}}'); if (!$bTokenExists) //If no tokens table exists { self::_newtokentable($iSurveyId); } + // Javascript $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . "admin/tokens.js"); $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . "admin/tokentocpdb.js"); $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/jquery.multiselect.min.js"); $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/jqGrid/js/i18n/grid.locale-en.js"); $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/jqGrid/js/jquery.jqGrid.min.js"); - $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/css/jquery.multiselect.css"); - $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/css/jquery.multiselect.filter.css"); + $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/jquery-ui-timepicker-addon.js"); + // CSS +// $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/css/jquery.multiselect.css"); +// $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/css/jquery.multiselect.filter.css"); $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/jqGrid/css/ui.jqgrid.css"); $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . "jquery/jqGrid/css/jquery.ui.datepicker.css"); $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') . "displayParticipants.css"); + $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') . "jquery-ui/jquery-timepicker.css"); Yii::app()->loadHelper('surveytranslator'); Yii::import('application.libraries.Date_Time_Converter', true); @@ -349,9 +362,14 @@ function getTokens_json($iSurveyId) } $clang = $this->getController()->lang; $page = Yii::app()->request->getPost('page'); + $sidx = Yii::app()->request->getPost('sidx'); + $sidx = !empty($sidx) ? $sidx : "lastname"; + $sord = Yii::app()->request->getPost('sord'); + $sord = !empty($sord) ? $sord : "asc"; $limit = Yii::app()->request->getPost('rows'); - - $tokens = Tokens_dynamic::model($iSurveyId)->findAll(); + $limit = isset($limit) ? $limit : 25; //Stop division by zero errors + $page = isset($page) ? $page : 1; //Stop division by zero errors + $tokens = Tokens_dynamic::model($iSurveyId)->findAll(array("order"=>$sidx. " ". $sord)); $aData = new stdClass; $aData->page = $page; @@ -375,17 +393,39 @@ function getTokens_json($iSurveyId) $token['validuntil'] = ''; $aData->rows[$i]['id'] = $token['tid']; - $action = 'getController()->createUrl("survey/index/sid/{$iSurveyId}/token/{$token['token']}") . '", "_blank")\'>'; - $action .= 'gT("Are you sure you want to delete this entry?") . ' (' . $token['tid'] . ')")) {$("#displaytokens").delRowData(' . $token['tid'] . ');$.post(delUrl,{tid:' . $token['tid'] . '});}\'>'; - + $prow = Survey::model()->findByPk($iSurveyId)->getAttributes(); //Get survey settings + + $action=""; + if($token['token'] != "" && ($token['completed'] == "N" || $token['completed'] =="")) { + $action .= 'getController()->createUrl("survey/index/sid/{$iSurveyId}/token/{$token['token']}") . '", "_blank")\'>'; + } elseif ($token['completed'] != "N" && $token['completed'] != "" && $prow['anonymized'] == "N" ) { + //Get the survey response id of the matching entry + $id=Survey_dynamic::model($iSurveyId)->findAllByAttributes(array('token'=>$token['token'])); + $action .= 'getController()->createUrl("admin/responses/view/surveyid/{$iSurveyId}/id/{$id[0]['id']}").'", "_top")\'>'; + } else { + $action .= '
'; + } + $action .= 'gT("Are you sure you want to delete this entry?") . ' (' . $token['tid'] . ')")) {$("#displaytokens").delRowData(' . $token['tid'] . ');$.post(delUrl,{tid:' . $token['tid'] . '});}\'>'; if (strtolower($token['emailstatus']) == 'ok') { - if ($token['sent'] == 'N') - $action .= 'getController()->createUrl("admin/tokens/email/surveyid/{$iSurveyId}/tokenids/" . $token['tid']) . '", "_blank")\' />'; - else - $action .= 'getController()->createUrl("admin/tokens/email/action/remind/surveyid/{$iSurveyId}/tokenids/" . $token['tid']) . '", "_blank")\' />'; + if($token['completed'] == 'N' && $token['usesleft'] > 0) + { + if ($token['sent'] == 'N') + $action .= 'getController()->createUrl("admin/tokens/email/surveyid/{$iSurveyId}/tokenids/" . $token['tid']) . '", "_blank")\' />'; + else + $action .= 'getController()->createUrl("admin/tokens/email/action/remind/surveyid/{$iSurveyId}/tokenids/" . $token['tid']) . '", "_blank")\' />'; + } else { + $action .= '
'; + } + } else { + $action .= '
'; + } + $action .= ''; + if(!empty($token['participant_id']) && $token['participant_id'] != "") { + $action .= 'getController()->createUrl("admin/participants/displayParticipants/searchurl/participant_id||equal||".$token['participant_id']).'", "_top")\'>'; + } else { + $action .= '
'; } - $action .= ''; $aData->rows[$i]['cell'] = array($token['tid'], $action, $token['firstname'], $token['lastname'], $token['email'], $token['emailstatus'], $token['token'], $token['language'], $token['sent'], $token['remindersent'], $token['remindercount'], $token['completed'], $token['usesleft'], $token['validfrom'], $token['validuntil']); $attributes = getAttributeFieldNames($iSurveyId); foreach ($attributes as $attribute) @@ -397,6 +437,115 @@ function getTokens_json($iSurveyId) echo ls_json_encode($aData); } + function getSearch_json($iSurveyId) + { + $clang = $this->getController()->lang; + // CHECK TO SEE IF A TOKEN TABLE EXISTS FOR THIS SURVEY + $bTokenExists = tableExists('{{tokens_' . $iSurveyId . '}}'); + if (!$bTokenExists) //If no tokens table exists + { + self::_newtokentable($iSurveyId); + } + $prow = Survey::model()->findByPk($iSurveyId)->getAttributes(); //Get survey settings + $page = (Yii::app()->request->getPost('page') != "") ? Yii::app()->request->getPost('page') : 1; + $limit = (Yii::app()->request->getPost('rows') != "") ? Yii::app()->request->getPost('rows') : 25 ; + $fields = array('tid', 'firstname', 'lastname', 'email', 'emailstatus', 'token', 'language', 'sent', 'sentreminder', 'remindercount', 'completed', 'usesleft', 'validfrom', 'validuntil'); + $searchcondition = Yii::app()->request->getQuery('search'); + $searchcondition = urldecode($searchcondition); + $finalcondition = array(); + $condition = explode("||", $searchcondition); + $aData = new stdClass(); + if (count($condition) == 3) + { + $records = Tokens_dynamic::model($iSurveyId)->getSearch($condition, $page, $limit); + $aData->records = count(Tokens_dynamic::model($iSurveyId)->getSearch($condition, 0, 0)); + } + else + { + $records = Tokens_dynamic::model($iSurveyId)->getSearchMultiple($condition, $page, $limit); + $aData->records = count(Tokens_dynamic::model($iSurveyId)->getSearchMultiple($condition, 0, 0)); + } + $aData->page = $page; + $aData->total = ceil($aData->records / $limit); + + $i = 0; + foreach ($records as $row => $value) + { + $action=""; + if($value['token'] != "" && ($value['completed'] == "N" || $value['completed'] =="")) { + $action .= 'getController()->createUrl("survey/index/sid/{$iSurveyId}/token/{$value['token']}") . '", "_blank")\'>'; + } elseif ($value['completed'] != "N" && $value['completed'] != "" && $prow['anonymized'] == "N" ) { + //Get the survey response id of the matching entry + $id=Survey_dynamic::model($iSurveyId)->findAllByAttributes(array('token'=>$value['token'])); + $action .= 'getController()->createUrl("admin/responses/view/surveyid/{$iSurveyId}/id/{$id[0]['id']}").'", "_top")\'>'; + + } else { + $action .= '
'; + } + $action .= 'gT("Are you sure you want to delete this entry?") . ' (' . $value['tid'] . ')")) {$("#displaytokens").delRowData(' . $value['tid'] . ');$.post(delUrl,{tid:' . $value['tid'] . '});}\'>'; + if (strtolower($value['emailstatus']) == 'ok') + { + if($value['completed'] == 'N' && $value['usesleft'] > 0) + { + if ($value['sent'] == 'N') + $action .= 'getController()->createUrl("admin/tokens/email/surveyid/{$iSurveyId}/tokenids/" . $value['tid']) . '", "_blank")\' />'; + else + $action .= 'getController()->createUrl("admin/tokens/email/action/remind/surveyid/{$iSurveyId}/tokenids/" . $value['tid']) . '", "_blank")\' />'; + } else { + $action .= '
'; + } + } + $action .= ''; + if(!empty($value['participant_id']) && $value['participant_id'] != "") { + $action .= 'getController()->createUrl("admin/participants/displayParticipants/searchurl/participant_id||equal||".$value['participant_id']).'", "_top")\'>'; + } else { + $action .= '
'; + } + + $sortablearray[$i] = array($value['tid'], $action, $value['firstname'], $value['lastname'], $value['email'], $value['emailstatus'], $value['token'], $value['language'], $value['sent'], $value['remindersent'], $value['remindercount'], $value['completed'], $value['usesleft'], $value['validfrom'], $value['validuntil']); + $i++; + } + function subval_sort($a, $subkey, $order) + { + foreach ($a as $k => $v) + { + $b[$k] = strtolower($v[$subkey]); + } + if ($order == "asc") + { + asort($b, SORT_REGULAR); + } + else + { + arsort($b, SORT_REGULAR); + } + foreach ($b as $key => $val) + { + $c[] = $a[$key]; + } + return $c; + } + + if (!empty($sortablearray)) + { + $indexsort = array_search(Yii::app()->request->getPost('sidx'), $fields); + $sortedarray = subval_sort($sortablearray, $indexsort, Yii::app()->request->getPost('sord')); + $i = 0; + $count = count($sortedarray[0]); + foreach ($sortedarray as $key => $value) + { + $aData->rows[$i]['id'] = $value[0]; + $aData->rows[$i]['cell'] = array(); + for ($j = 0; $j < $count; $j++) + { + array_push($aData->rows[$i]['cell'], $value[$j]); + } + $i++; + } + } + echo ls_json_encode($aData); + } + function editToken($iSurveyId) { // CHECK TO SEE IF A TOKEN TABLE EXISTS FOR THIS SURVEY @@ -428,7 +577,7 @@ function editToken($iSurveyId) // { // $sLang = Yii::app()->request->getPost('language'); // } - Tokens_dynamic::sid($iSurveyId); + Tokens_dynamic::model()->sid($iSurveyId); echo $from . ',' . $until; $aData = array( @@ -453,7 +602,7 @@ function editToken($iSurveyId) $this->getController()->error(sprintf($this->controller->lang->gT('%s cannot be empty'), $desc['description'])); $aData[$attr_name] = Yii::app()->request->getPost($attr_name); } - $token = Tokens_dynamic::model()->find('tid=' . CHttpRequest::getPost('id')); + $token = Tokens_dynamic::model()->find('tid=' . Yii::app()->getRequest()->getPost('id')); foreach ($aData as $k => $v) $token->$k = $v; @@ -585,10 +734,10 @@ function addnew($iSurveyId) $attrfieldnames = Survey::model()->findByPk($iSurveyId)->tokenAttributes; foreach ($attrfieldnames as $attr_name => $desc) { - $value = CHttpRequest::getPost($attr_name); + $value = Yii::app()->getRequest()->getPost($attr_name); if ($desc['mandatory'] == 'Y' && trim($value) == '') $this->getController()->error(sprintf($clang->gT('%s cannot be empty'), $desc['description'])); - $aData[$attr_name] = CHttpRequest::getPost($attr_name); + $aData[$attr_name] = Yii::app()->getRequest()->getPost($attr_name); } $udresult = Tokens_dynamic::model($iSurveyId)->findAll("token <> '' and token = '$sanitizedtoken'"); @@ -727,6 +876,11 @@ function edit($iSurveyId, $iTokenId) */ function delete($iSurveyId) { + /* Check permissions */ + if (!hasSurveyPermission($iSurveyId, 'tokens', 'read')) + { + die("You do not have permission to view this page"); // TODO Replace + } // CHECK TO SEE IF A TOKEN TABLE EXISTS FOR THIS SURVEY $bTokenExists = tableExists('{{tokens_' . $iSurveyId . '}}'); if (!$bTokenExists) //If no tokens table exists @@ -739,6 +893,11 @@ function delete($iSurveyId) if (hasSurveyPermission($iSurveyId, 'tokens', 'delete')) { $aTokenIds = explode(',', $iTokenId); //Make the tokenids string into an array + + //Delete any survey_links + Survey_links::model()->deleteTokenLink($aTokenIds, $iSurveyId); + + //Then delete the tokens Tokens_dynamic::model($iSurveyId)->deleteRecords($aTokenIds); } } @@ -817,33 +976,70 @@ function addDummies($iSurveyId, $subaction = '') $amount = sanitize_int(Yii::app()->request->getPost('amount')); $tokenlength = sanitize_int(Yii::app()->request->getPost('tokenlen')); - for ($i = 0; $i < $amount; $i++) + // Fill an array with all existing tokens + $criteria = Tokens_dynamic::model($iSurveyId)->getDbCriteria(); + $criteria->select = 'token'; + $ntresult = Tokens_dynamic::model($iSurveyId)->findAllAsArray($criteria); //Use AsArray to skip active record creation + $existingtokens=array(); + foreach ($ntresult as $tkrow) + { + $existingtokens[$tkrow['token']] = true ; + } + $invalidtokencount=0; + $newDummyToken=0; + while ($newDummyToken<$amount && $invalidtokencount<50) { $aDataToInsert = $aData; - $aDataToInsert['firstname'] = str_replace('{TOKEN_COUNTER}', $i, $aDataToInsert['firstname']); - $aDataToInsert['lastname'] = str_replace('{TOKEN_COUNTER}', $i, $aDataToInsert['lastname']); - $aDataToInsert['email'] = str_replace('{TOKEN_COUNTER}', $i, $aDataToInsert['email']); + $aDataToInsert['firstname'] = str_replace('{TOKEN_COUNTER}', $newDummyToken, $aDataToInsert['firstname']); + $aDataToInsert['lastname'] = str_replace('{TOKEN_COUNTER}', $newDummyToken, $aDataToInsert['lastname']); + $aDataToInsert['email'] = str_replace('{TOKEN_COUNTER}', $newDummyToken, $aDataToInsert['email']); $isvalidtoken = false; - while ($isvalidtoken == false) + while ($isvalidtoken == false && $invalidtokencount<50) { $newtoken = randomChars($tokenlength); if (!isset($existingtokens[$newtoken])) { $isvalidtoken = true; - $existingtokens[$newtoken] = null; + $existingtokens[$newtoken] = true; + $invalidtokencount=0; + } + else + { + $invalidtokencount ++; } } + if($isvalidtoken) + { + $aDataToInsert['token'] = $newtoken; + Tokens_dynamic::model()->insertToken($iSurveyId, $aDataToInsert); + $newDummyToken ++; + } - $aDataToInsert['token'] = $newtoken; - Tokens_dynamic::insertToken($iSurveyId, $aDataToInsert); } + $aData['thissurvey'] = getSurveyInfo($iSurveyId); + $aData['surveyid'] = $iSurveyId; + if(!$invalidtokencount) + { + $aData['success'] = false; + $message=array('title' => $clang->gT("Success"), + 'message' => $clang->gT("New dummy tokens were added.") . "

\ngetController()->createUrl("admin/tokens/browse/surveyid/$iSurveyId") . "', '_top')\" />\n" + ); + } + else + { + $aData['success'] = true; + $message= array( + 'title' => $clang->gT("Failed"), + 'message' => "

".sprintf($clang->gT("Only %s new dummy tokens were added after %s trials."),$newDummyToken,$invalidtokencount) + .$clang->gT("Try with a bigger token length.")."

" + ."\ngetController()->createUrl("admin/tokens/browse/surveyid/$iSurveyId") . "', '_top')\" />\n" + ); + } + $this->_renderWrappedTemplate('token', array('tokenbar','message' => $message),$aData); - $this->_renderWrappedTemplate('token', array('message' => array( - 'title' => $clang->gT("Success"), - 'message' => $clang->gT("New dummy tokens were added.") . "

\ngetController()->createUrl("admin/tokens/browse/surveyid/$iSurveyId") . "', '_top')\" />\n" - ) )); } else { @@ -868,6 +1064,11 @@ function addDummies($iSurveyId, $subaction = '') */ function managetokenattributes($iSurveyId) { + /* Check permissions */ + if (!hasSurveyPermission($iSurveyId, 'tokens', 'read')) + { + die("You do not have permission to view this page"); // TODO Replace + } // CHECK TO SEE IF A TOKEN TABLE EXISTS FOR THIS SURVEY $bTokenExists = tableExists('{{tokens_' . $iSurveyId . '}}'); if (!$bTokenExists) //If no tokens table exists @@ -998,6 +1199,11 @@ function updatetokenattributedescriptions($iSurveyId) */ function email($iSurveyId, $aTokenIds = null) { + /* Check permissions */ + if (!hasSurveyPermission($iSurveyId, 'tokens', 'read')) + { + die("You do not have permission to view this page"); // TODO Replace + } // CHECK TO SEE IF A TOKEN TABLE EXISTS FOR THIS SURVEY $bTokenExists = tableExists('{{tokens_' . $iSurveyId . '}}'); if (!$bTokenExists) //If no tokens table exists @@ -1149,9 +1355,12 @@ function email($iSurveyId, $aTokenIds = null) $from = Yii::app()->request->getPost('from_' . $emrow['language']); - $fieldsarray["{OPTOUTURL}"] = $this->getController()->createUrl("/optout/langcode/" . trim($emrow['language']) . "/surveyid/{$iSurveyId}/token/{$emrow['token']}"); - $fieldsarray["{OPTINURL}"] = $this->getController()->createUrl("/optin/langcode/" . trim($emrow['language']) . "/surveyid/{$iSurveyId}/token/{$emrow['token']}"); - $fieldsarray["{SURVEYURL}"] = $this->getController()->createUrl("/survey/langcode/" . trim($emrow['language']) . "/surveyid/{$iSurveyId}/token/{$emrow['token']}"); + $fieldsarray["{OPTOUTURL}"] = $this->getController() + ->createAbsoluteUrl("/optout/tokens/langcode/" . trim($emrow['language']) . "/surveyid/{$iSurveyId}/token/{$emrow['token']}"); + $fieldsarray["{OPTINURL}"] = $this->getController() + ->createAbsoluteUrl("/optin/tokens/langcode/" . trim($emrow['language']) . "/surveyid/{$iSurveyId}/token/{$emrow['token']}"); + $fieldsarray["{SURVEYURL}"] = $this->getController() + ->createAbsoluteUrl("/survey/index/sid/{$iSurveyId}/token/{$emrow['token']}/langcode/" . trim($emrow['language']) . "/"); foreach(array('OPTOUT', 'OPTIN', 'SURVEY') as $key) { @@ -1184,37 +1393,45 @@ function email($iSurveyId, $aTokenIds = null) { $tokenoutput .= $emrow['tid'] . " " . ReplaceFields($clang->gT("Email to {FIRSTNAME} {LASTNAME} ({EMAIL}) skipped: Token is not valid anymore.") . "
", $fieldsarray); } - elseif (SendEmailMessage($modmessage, $modsubject, $to, $from, Yii::app()->getConfig("sitename"), $bHtml, getBounceEmail($iSurveyId), null, $customheaders)) + else { - // Put date into sent - $udequery = Tokens_dynamic::model($iSurveyId)->findByPk($emrow['tid']); - if ($bEmail) - { - $tokenoutput .= $clang->gT("Invitation sent to:"); - $udequery->sent = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust")); - } - else - { - $tokenoutput .= $clang->gT("Reminder sent to:"); - $udequery->remindersent = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust")); - $udequery->remindercount = $udequery->remindercount + 1; - } - $udequery->save(); - - $tokenoutput .= " {$emrow['firstname']} {$emrow['lastname']} ({$emrow['email']})
\n"; - if (Yii::app()->getConfig("emailsmtpdebug") == 2) + if (SendEmailMessage($modmessage, $modsubject, $to, $from, Yii::app()->getConfig("sitename"), $bHtml, getBounceEmail($iSurveyId), null, $customheaders)) { - $tokenoutput .= $maildebug; + // Put date into sent + $udequery = Tokens_dynamic::model($iSurveyId)->findByPk($emrow['tid']); + if ($bEmail) + { + $tokenoutput .= $clang->gT("Invitation sent to:"); + $udequery->sent = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust")); + } + else + { + $tokenoutput .= $clang->gT("Reminder sent to:"); + $udequery->remindersent = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust")); + $udequery->remindercount = $udequery->remindercount + 1; + } + $udequery->save(); + //Update central participant survey_links + if(!empty($emrow['participant_id'])) + { + $slquery = Survey_links::model()->find('participant_id = "'.$emrow['participant_id'].'" AND survey_id = '.$iSurveyId.' AND token_id = '.$emrow['tid']); + $slquery->date_invited = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust")); + $slquery->save(); + } + $tokenoutput .= " {$emrow['firstname']} {$emrow['lastname']} ({$emrow['email']})
\n"; + if (Yii::app()->getConfig("emailsmtpdebug") == 2) + { + $tokenoutput .= $maildebug; + } + } else { + $tokenoutput .= ReplaceFields($clang->gT("Email to {FIRSTNAME} {LASTNAME} ({EMAIL}) failed. Error Message:") . " " . $maildebug . "
", $fieldsarray); } } - else - { - $tokenoutput .= ReplaceFields($clang->gT("Email to {FIRSTNAME} {LASTNAME} ({EMAIL}) failed. Error Message:") . " " . $maildebug . "
", $fieldsarray); - } unset($fieldsarray); } $aViewUrls = array('tokenbar', 'emailpost'); + $aData['tokenoutput']=$tokenoutput; if ($ctcount > $emcount) { @@ -1843,7 +2060,6 @@ function import($iSurveyId) $this->_renderWrappedTemplate('token', array('tokenbar', 'csvpost'), $aData); } - } else { @@ -1891,10 +2107,23 @@ function tokenify($iSurveyId) else { //get token length from survey settings - $newtokencount = Tokens_dynamic::model($iSurveyId)->createTokens($iSurveyId); + $newtoken = Tokens_dynamic::model($iSurveyId)->createTokens($iSurveyId); + $newtokencount = $newtoken['0']; + $neededtokencount = $newtoken['1']; + if($neededtokencount>$newtokencount) + { + $aData['success'] = false; + $message = sprintf($clang->ngT('Only %s token has been created.','Only %s tokens have been created.',$newtokencount),$newtokencount) + .sprintf($clang->ngT('Need %s token.','Need %s tokens.',$neededtokencount),$neededtokencount); + } + else + { + $aData['success'] = true; + $message = sprintf($clang->ngT('%s token has been created.','%s tokens have been created.',$newtokencount),$newtokencount); + } $this->_renderWrappedTemplate('token', array('tokenbar', 'message' => array( 'title' => $clang->gT("Create tokens"), - 'message' => sprintf($clang->ngT('%s token has been created.','%s tokens have been created.',$newtokencount),$newtokencount) + 'message' => $message )), $aData); } } @@ -1921,6 +2150,8 @@ function kill($iSurveyId) } $date = date('YmdHis'); + /* If there is not a $_POST value of 'ok', then ask if the user is sure they want to + delete the tokens table */ if (!Yii::app()->request->getPost('ok')) { $this->_renderWrappedTemplate('token', array('tokenbar', 'message' => array( @@ -1934,18 +2165,23 @@ function kill($iSurveyId) )), $aData); } else + /* The user has confirmed they want to delete the tokens table */ { $oldtable = "tokens_$iSurveyId"; $newtable = "old_tokens_{$iSurveyId}_$date"; Yii::app()->db->createCommand()->renameTable("{{{$oldtable}}}", "{{{$newtable}}}"); + Survey::model()->updateByPk($iSurveyId, array('attributedescriptions' => "a:0:{}")); + + //Remove any survey_links to the CPDB + Survey_links::model()->deleteLinksBySurvey($iSurveyId); $this->_renderWrappedTemplate('token', array('tokenbar', 'message' => array( 'title' => $clang->gT("Delete Tokens Table"), 'message' => '
' . $clang->gT("The tokens table has now been removed and tokens are no longer required to access this survey.") . "
" . $clang->gT("A backup of this table has been made and can be accessed by your system administrator.") . "
\n" . "(\"old_tokens_{$iSurveyId}_$date\")" . "

\n" . "getController()->createUrl("admin/") . "', '_top')\" />" + . $clang->gT("Main Admin Screen") . "' onclick=\"window.open('" . Yii::app()->getController()->createUrl("admin/survey/view/surveyid/".$iSurveyId) . "', '_top')\" />" )), $aData); LimeExpressionManager::SetDirtyFlag(); // so that knows that token tables have changed @@ -2067,10 +2303,34 @@ function _newtokentable($iSurveyId) . $clang->gT("Continue") . "' onclick=\"window.open('" . $this->getController()->createUrl("admin/tokens/index/surveyid/$iSurveyId") . "', '_top')\" />\n" ))); } + /* Restore a previously deleted tokens table */ elseif (returnGlobal('restoretable') == "Y" && Yii::app()->request->getPost('oldtable') && hasSurveyPermission($iSurveyId, 'surveyactivation', 'update')) { + //Rebuild attributedescription value for the surveys table + $table = Yii::app()->db->schema->getTable(Yii::app()->request->getPost('oldtable')); + $fields=array_filter(array_keys($table->columns), 'filterForAttributes'); + foreach ($fields as $fieldname) + { + $name=$fieldname; + if($fieldname[10]=='c') { //This belongs to a cpdb attribute + $cpdbattid=substr($fieldname,15); + $data=ParticipantAttributeNames::model()->getAttributeName($cpdbattid, Yii::app()->session['adminlang']); + $name=$data['attribute_name']; + } + $fieldcontents[$fieldname] = array( + 'description' => $name, + 'mandatory' => 'N', + 'show_register' => 'N' + ); + } + Survey::model()->updateByPk($iSurveyId, array('attributedescriptions' => serialize($fieldcontents))); + + Yii::app()->db->createCommand()->renameTable(Yii::app()->request->getPost('oldtable'), Yii::app()->db->tablePrefix."tokens_".intval($iSurveyId)); + //Add any survey_links from the renamed table + Survey_links::model()->rebuildLinksFromTokenTable($iSurveyId); + $this->_renderWrappedTemplate('token', array('message' => array( 'title' => $clang->gT("Import old tokens"), 'message' => $clang->gT("A token table has been created for this survey and the old tokens were imported.") . " (\"" . Yii::app()->db->tablePrefix . "tokens_$iSurveyId" . "\")

\n" @@ -2104,83 +2364,6 @@ function _newtokentable($iSurveyId) } } - function getSearch_json($iSurveyId) - { - // CHECK TO SEE IF A TOKEN TABLE EXISTS FOR THIS SURVEY - $bTokenExists = tableExists('{{tokens_' . $iSurveyId . '}}'); - if (!$bTokenExists) //If no tokens table exists - { - self::_newtokentable($iSurveyId); - } - $page = Yii::app()->request->getPost('page'); - $limit = Yii::app()->request->getPost('rows'); - $fields = array('tid', 'firstname', 'lastname', 'email', 'emailstatus', 'token', 'language', 'sent', 'sentreminder', 'remindercount', 'completed', 'usesleft', 'validfrom', 'validuntil'); - $searchcondition = Yii::app()->request->getQuery('search'); - $searchcondition = urldecode($searchcondition); - $finalcondition = array(); - $condition = explode("||", $searchcondition); - $aData = new Object(); - if (count($condition) == 3) - { - $records = Tokens_dynamic::model($iSurveyId)->getSearch($condition, $page, $limit); - $aData->records = count(Tokens_dynamic::model($iSurveyId)->getSearch($condition, 0, 0)); - } - else - { - $records = Tokens_dynamic::model($iSurveyId)->getSearchMultiple($condition, $page, $limit); - $aData->records = count(Tokens_dynamic::model($iSurveyId)->getSearchMultiple($condition, 0, 0)); - } - $aData->page = $page; - $aData->total = ceil($aData->records / $limit); - - $i = 0; - foreach ($records as $row => $value) - { - $sortablearray[$i] = array($value['tid'], $value['firstname'], $value['lastname'], $value['email'], $value['emailstatus'], $value['token'], $value['language'], $value['sent'], $value['remindersent'], $value['remindercount'], $value['completed'], $value['usesleft'], $value['validfrom'], $value['validuntil']); - $i++; - } - - function subval_sort($a, $subkey, $order) - { - foreach ($a as $k => $v) - { - $b[$k] = strtolower($v[$subkey]); - } - if ($order == "asc") - { - asort($b, SORT_REGULAR); - } - else - { - arsort($b, SORT_REGULAR); - } - foreach ($b as $key => $val) - { - $c[] = $a[$key]; - } - return $c; - } - - if (!empty($sortablearray)) - { - $indexsort = array_search(Yii::app()->request->getPost('sidx'), $fields); - $sortedarray = subval_sort($sortablearray, $indexsort, Yii::app()->request->getPost('sord')); - $i = 0; - $count = count($sortedarray[0]); - foreach ($sortedarray as $key => $value) - { - $aData->rows[$i]['id'] = $value[0]; - $aData->rows[$i]['cell'] = array(); - for ($j = 0; $j < $count; $j++) - { - array_push($aData->rows[$i]['cell'], $value[$j]); - } - $i++; - } - } - echo ls_json_encode($aData); - } - /** * Renders template(s) wrapped in header and footer * diff --git a/application/controllers/admin/translate.php b/application/controllers/admin/translate.php index 79179764743..8ca6477a21b 100644 --- a/application/controllers/admin/translate.php +++ b/application/controllers/admin/translate.php @@ -24,10 +24,10 @@ class translate extends Survey_Common_Action { public function index() { - $surveyid = sanitize_int($_REQUEST['surveyid']); - $tolang = CHttpRequest::getParam('lang'); - $action = CHttpRequest::getParam('action'); - $actionvalue = CHttpRequest::getPost('actionvalue'); + $iSurveyID = sanitize_int($_REQUEST['surveyid']); + $tolang = Yii::app()->getRequest()->getParam('lang'); + $action = Yii::app()->getRequest()->getParam('action'); + $actionvalue = Yii::app()->getRequest()->getPost('actionvalue'); //echo $this->query('title','querybase'); //die(); @@ -40,19 +40,19 @@ public function index() $this->getController()->_js_admin_includes(Yii::app()->getConfig("adminscripts") . 'translation.js'); $clang = Yii::app()->lang; - $baselang = Survey::model()->findByPk($surveyid)->language; - $langs = Survey::model()->findByPk($surveyid)->additionalLanguages; + $baselang = Survey::model()->findByPk($iSurveyID)->language; + $langs = Survey::model()->findByPk($iSurveyID)->additionalLanguages; Yii::app()->loadHelper("database"); Yii::app()->loadHelper("admin/htmleditor"); - if ( empty($tolang) && count($langs) > 1 ) + if ( empty($tolang) && count($langs) > 0 ) { $tolang = $langs[0]; } // TODO need to do some validation here on surveyid - $surveyinfo = getSurveyInfo($surveyid); + $surveyinfo = getSurveyInfo($iSurveyID); $survey_title = $surveyinfo['name']; Yii::app()->loadHelper("surveytranslator"); @@ -61,11 +61,11 @@ public function index() $baselangdesc = $supportedLanguages[$baselang]['description']; $aData = array( - "surveyid" => $surveyid, + "surveyid" => $iSurveyID, "survey_title" => $survey_title, "tolang" => $tolang, "clang" => $clang, - "adminmenu" => $this->showTranslateAdminmenu($surveyid, $survey_title, $tolang) + "adminmenu" => $this->showTranslateAdminmenu($iSurveyID, $survey_title, $tolang) ); $aViewUrls['translateheader_view'][] = $aData; @@ -74,21 +74,22 @@ public function index() if ( ! empty($tolang) ) { - if ( $actionvalue == "translateSave" ) + // Only save if the administration user has the correct permission + if ( $actionvalue == "translateSave" && hasSurveyPermission($iSurveyID, 'translations', 'update') ) { - $this->_translateSave($surveyid, $tolang, $baselang, $tab_names); + $this->_translateSave($iSurveyID, $tolang, $baselang, $tab_names); } $tolangdesc = $supportedLanguages[$tolang]['description']; // Display tabs with fields to translate, as well as input fields for translated values - $aViewUrls = array_merge($aViewUrls, $this->_displayUntranslatedFields($surveyid, $tolang, $baselang, $tab_names, $baselangdesc, $tolangdesc)); + $aViewUrls = array_merge($aViewUrls, $this->_displayUntranslatedFields($iSurveyID, $tolang, $baselang, $tab_names, $baselangdesc, $tolangdesc)); //var_dump(array_keys($aViewUrls));die(); } $this->_renderWrappedTemplate('translate', $aViewUrls, $aData); } - private function _translateSave($surveyid, $tolang, $baselang, $tab_names) + private function _translateSave($iSurveyID, $tolang, $baselang, $tab_names) { $tab_names_full = $tab_names; @@ -102,24 +103,24 @@ private function _translateSave($surveyid, $tolang, $baselang, $tab_names) foreach( $tab_names_full as $type ) { - $size = (int) CHttpRequest::getPost("{$type}_size"); + $size = (int) Yii::app()->getRequest()->getPost("{$type}_size"); // start a loop in order to update each record $i = 0; while ($i <= $size) { // define each variable - if ( CHttpRequest::getPost("{$type}_newvalue_{$i}") ) + if ( Yii::app()->getRequest()->getPost("{$type}_newvalue_{$i}") ) { - $old = CHttpRequest::getPost("{$type}_oldvalue_{$i}"); - $new = CHttpRequest::getPost("{$type}_newvalue_{$i}"); + $old = Yii::app()->getRequest()->getPost("{$type}_oldvalue_{$i}"); + $new = Yii::app()->getRequest()->getPost("{$type}_newvalue_{$i}"); // check if the new value is different from old, and then update database if ( $new != $old ) { - $id1 = CHttpRequest::getPost("{$type}_id1_{$i}"); - $id2 = CHttpRequest::getPost("{$type}_id2_{$i}"); + $id1 = Yii::app()->getRequest()->getPost("{$type}_id1_{$i}"); + $id2 = Yii::app()->getRequest()->getPost("{$type}_id2_{$i}"); - $this->query($type, 'queryupdate', $surveyid, $tolang, $baselang, $id1, $id2, $new); + $this->query($type, 'queryupdate', $iSurveyID, $tolang, $baselang, $id1, $id2, $new); } } $i++; @@ -127,9 +128,9 @@ private function _translateSave($surveyid, $tolang, $baselang, $tab_names) } // end foreach } - private function _displayUntranslatedFields($surveyid, $tolang, $baselang, $tab_names, $baselangdesc, $tolangdesc) + private function _displayUntranslatedFields($iSurveyID, $tolang, $baselang, $tab_names, $baselangdesc, $tolangdesc) { - $aData['surveyid'] = $surveyid; + $aData['surveyid'] = $iSurveyID; $aData['clang'] = Yii::app()->lang; $aData['tab_names'] = $tab_names; $aData['tolang'] = $tolang; @@ -153,8 +154,8 @@ private function _displayUntranslatedFields($surveyid, $tolang, $baselang, $tab_ { $associated = TRUE; $amTypeOptions2 = $this->setupTranslateFields($type2); - $resultbase2 = $this->query($type, "querybase", $surveyid, $tolang, $baselang); - $resultto2 = $this->query($type, "queryto", $surveyid, $tolang, $baselang); + $resultbase2 = $this->query($type, "querybase", $iSurveyID, $tolang, $baselang); + $resultto2 = $this->query($type, "queryto", $iSurveyID, $tolang, $baselang); } // Setup form // start a counter in order to number the input fields for each record @@ -162,8 +163,8 @@ private function _displayUntranslatedFields($surveyid, $tolang, $baselang, $tab_ $evenRow = FALSE; $all_fields_empty = TRUE; - $resultbase = $this->query($type, "querybase", $surveyid, $tolang, $baselang); - $resultto = $this->query($type, "queryto", $surveyid, $tolang, $baselang); + $resultbase = $this->query($type, "querybase", $iSurveyID, $tolang, $baselang); + $resultto = $this->query($type, "queryto", $iSurveyID, $tolang, $baselang); $aData['baselangdesc'] = $baselangdesc; $aData['tolangdesc'] = $tolangdesc; $aData['type'] = $type; @@ -205,12 +206,12 @@ private function _displayUntranslatedFields($surveyid, $tolang, $baselang, $tab_ $aData['associated'] = $associated; $evenRow = !($evenRow); - $aData['translateFields'] = $this->displayTranslateFields($surveyid, $gid, $qid, $type, + $aData['translateFields'] = $this->displayTranslateFields($iSurveyID, $gid, $qid, $type, $amTypeOptions, $baselangdesc, $tolangdesc, $textfrom, $textto, $i, $rowfrom, $evenRow); if ($associated && strlen(trim((string)$textfrom2)) > 0) { $evenRow = !($evenRow); - $aData['translateFields'] .= $this->displayTranslateFields($surveyid, $gid, $qid, $type2, + $aData['translateFields'] .= $this->displayTranslateFields($iSurveyID, $gid, $qid, $type2, $amTypeOptions2, $baselangdesc, $tolangdesc, $textfrom2, $textto2, $i, $resultbase2[$i], $evenRow); } @@ -221,6 +222,7 @@ private function _displayUntranslatedFields($surveyid, $tolang, $baselang, $tab_ $aData['all_fields_empty'] = $all_fields_empty; $aData['translateFieldsFooter'] = $this->displayTranslateFieldsFooter(); + $aData['bReadOnly']=!hasSurveyPermission($iSurveyID, 'translations', 'update'); $aViewUrls['output'] .= $this->getController()->render("/admin/translate/translatefieldsfooter_view", $aData, true); } // end foreach @@ -232,18 +234,18 @@ private function _displayUntranslatedFields($surveyid, $tolang, $baselang, $tab_ /** * showTranslateAdminmenu() creates the main menu options for the survey translation page - * @param string $surveyid The survey ID + * @param string $iSurveyID The survey ID * @param string $survey_title * @param string $tolang * @param string $activated * @param string $scriptname * @return string */ - private function showTranslateAdminmenu($surveyid, $survey_title, $tolang) + private function showTranslateAdminmenu($iSurveyID, $survey_title, $tolang) { $clang = Yii::app()->lang; $publicurl = Yii::app()->getConfig('publicurl'); - $menuitem_url = "{$publicurl}/index.php?sid={$surveyid}&newtest=Y&lang="; + $menuitem_url = "{$publicurl}/index.php?sid={$iSurveyID}&newtest=Y&lang="; $adminmenu = ""; $adminmenu .= CHtml::openTag('div', array('class'=>'menubar')); @@ -258,7 +260,7 @@ private function showTranslateAdminmenu($surveyid, $survey_title, $tolang) $clang->gT("Return to survey administration"), "Administration", "home.png", - $this->getController()->createUrl("admin/survey/view/surveyid/{$surveyid}/") + $this->getController()->createUrl("admin/survey/view/surveyid/{$iSurveyID}/") ); // Separator @@ -267,7 +269,7 @@ private function showTranslateAdminmenu($surveyid, $survey_title, $tolang) // Test / execute survey button if ( ! empty ($tolang) ) { - $adminmenu .= $this->_getSurveyButton($surveyid, $menuitem_url); + $adminmenu .= $this->_getSurveyButton($iSurveyID, $menuitem_url); } // End of survey-bar-left @@ -275,7 +277,7 @@ private function showTranslateAdminmenu($surveyid, $survey_title, $tolang) // Survey language list - $adminmenu .= $this->_getLanguageList($surveyid, $tolang); + $adminmenu .= $this->_getLanguageList($iSurveyID, $tolang); $adminmenu .= CHtml::closeTag('div'); $adminmenu .= CHtml::closeTag('div'); @@ -284,20 +286,20 @@ private function showTranslateAdminmenu($surveyid, $survey_title, $tolang) /* * _getSurveyButton() returns test / execute survey button - * @param string $surveyid Survey id + * @param string $iSurveyID Survey id * @param string $menuitem_url Menu item url */ - private function _getSurveyButton($surveyid, $menuitem_url) + private function _getSurveyButton($iSurveyID, $menuitem_url) { $survey_button = ""; - $imageurl = Yii::app()->getConfig("imageurl"); + $imageurl = Yii::app()->getConfig("adminimageurl"); $clang = Yii::app()->lang; - $baselang = Survey::model()->findByPk($surveyid)->language; - $langs = Survey::model()->findByPk($surveyid)->additionalLanguages; + $baselang = Survey::model()->findByPk($iSurveyID)->language; + $langs = Survey::model()->findByPk($iSurveyID)->additionalLanguages; - $surveyinfo = Survey::model()->with(array('languagesettings'=>array('condition'=>'surveyls_language=language')))->findByPk($surveyid); + $surveyinfo = Survey::model()->with(array('languagesettings'=>array('condition'=>'surveyls_language=language')))->findByPk($iSurveyID); $surveyinfo = array_merge($surveyinfo->attributes, $surveyinfo->languagesettings[0]->attributes); $surveyinfo = array_map('flattenText', $surveyinfo); @@ -357,17 +359,17 @@ private function _getSurveyButton($surveyid, $menuitem_url) /* * _getLanguageList() returns survey language list - * @param string $surveyid Survey id + * @param string $iSurveyID Survey id * @param string @clang Language object * @param string $tolang The target translation code */ - private function _getLanguageList($surveyid, $tolang) + private function _getLanguageList($iSurveyID, $tolang) { $language_list = ""; $clang = Yii::app()->lang; - $langs = Survey::model()->findByPk($surveyid)->additionalLanguages; + $langs = Survey::model()->findByPk($iSurveyID)->additionalLanguages; $supportedLanguages = getLanguageData(FALSE,Yii::app()->session['adminlang']); $language_list .= CHtml::openTag('div', array('class'=>'menubar-right')); // Opens .menubar-right div @@ -381,7 +383,7 @@ private function _getLanguageList($surveyid, $tolang) ) ); - if ( count(Survey::model()->findByPk($surveyid)->additionalLanguages) > 1 ) + if ( count(Survey::model()->findByPk($iSurveyID)->additionalLanguages) > 1 ) { $selected = ( ! isset($tolang) ) ? "selected" : ""; @@ -389,7 +391,7 @@ private function _getLanguageList($surveyid, $tolang) 'option', array( 'selected' => $selected, - 'value' => $this->getController()->createUrl("admin/translate/index/surveyid/{$surveyid}/") + 'value' => $this->getController()->createUrl("admin/translate/index/surveyid/{$iSurveyID}/") ), $clang->gT("Please choose...") ); @@ -404,7 +406,7 @@ private function _getLanguageList($surveyid, $tolang) 'option', array( 'selected' => $selected, - 'value' => $this->getController()->createUrl("admin/translate/index/surveyid/{$surveyid}/lang/{$lang}") + 'value' => $this->getController()->createUrl("admin/translate/index/surveyid/{$iSurveyID}/lang/{$lang}") ), $tolangtext ); @@ -419,7 +421,7 @@ private function _getLanguageList($surveyid, $tolang) /** * setupTranslateFields() creates a customised array with database query * information for use by survey translation - * @param string $surveyid Survey id + * @param string $iSurveyID Survey id * @param string $type Type of database field that is being translated, e.g. title, question, etc. * @param string $baselang The source translation language code, e.g. "En" * @param string $tolang The target translation language code, e.g. "De" @@ -739,7 +741,7 @@ private function setupTranslateFields($type) return $aData; } - private function query($type, $action, $surveyid, $tolang, $baselang, $id1 = "", $id2 = "", $new = "") + private function query($type, $action, $iSurveyID, $tolang, $baselang, $id1 = "", $id2 = "", $new = "") { $amTypeOptions = array(); switch ($action) @@ -763,59 +765,59 @@ private function query($type, $action, $surveyid, $tolang, $baselang, $id1 = "", case 'emailregistrationbody': case 'email_confirm': case 'email_confirmbody': - return Surveys_languagesettings::model()->findAllByPk(array('surveyls_survey_id'=>$surveyid, 'surveyls_language'=>$baselang)); + return Surveys_languagesettings::model()->findAllByPk(array('surveyls_survey_id'=>$iSurveyID, 'surveyls_language'=>$baselang)); case 'group': case 'group_desc': - return Groups::model()->findAllByAttributes(array('sid'=>$surveyid, 'language'=>$baselang), array('order' => 'gid')); + return Groups::model()->findAllByAttributes(array('sid'=>$iSurveyID, 'language'=>$baselang), array('order' => 'gid')); case 'question': case 'question_help': - return Questions::model()->findAllByAttributes(array('sid' => $surveyid,'language' => $baselang,'parent_qid' => 0), array('order' => 'question_order, scale_id')); + return Questions::model()->findAllByAttributes(array('sid' => $iSurveyID,'language' => $baselang,'parent_qid' => 0), array('order' => 'question_order, scale_id')); case 'subquestion': - return Questions::model()->with('parents', 'groups')->findAllByAttributes(array('sid' => $surveyid,'language' => $baselang), array('order' => 'groups.group_order, parents.question_order, t.scale_id, t.question_order', 'condition'=>'parents.language=:baselang AND groups.language=:baselang AND t.parent_qid>0', 'params'=>array(':baselang'=>$baselang))); + return Questions::model()->with('parents', 'groups')->findAllByAttributes(array('sid' => $iSurveyID,'language' => $baselang), array('order' => 'groups.group_order, parents.question_order, t.scale_id, t.question_order', 'condition'=>'parents.language=:baselang AND groups.language=:baselang AND t.parent_qid>0', 'params'=>array(':baselang'=>$baselang))); case 'answer': - return Answers::model()->with('questions', 'groups')->findAllByAttributes(array('language' => $baselang), array('order' => 'groups.group_order, questions.question_order, t.scale_id, t.sortorder', 'condition'=>'questions.sid=:sid AND questions.language=:baselang AND groups.language=:baselang', 'params'=>array(':baselang'=>$baselang, ':sid' => $surveyid))); + return Answers::model()->with('questions', 'groups')->findAllByAttributes(array('language' => $baselang), array('order' => 'groups.group_order, questions.question_order, t.scale_id, t.sortorder', 'condition'=>'questions.sid=:sid AND questions.language=:baselang AND groups.language=:baselang', 'params'=>array(':baselang'=>$baselang, ':sid' => $iSurveyID))); } case "queryupdate": switch ( $type ) { case 'title': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_title'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_title'=>$new)); case 'description': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_description'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_description'=>$new)); case 'welcome': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_welcometext'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_welcometext'=>$new)); case 'end': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_endtext'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_endtext'=>$new)); case 'emailinvite': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_invite_subj'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_invite_subj'=>$new)); case 'emailinvitebody': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_invite'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_invite'=>$new)); case 'emailreminder': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_remind_subj'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_remind_subj'=>$new)); case 'emailreminderbody': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_remind'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_remind'=>$new)); case 'emailconfirmation': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_confirm_subj'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_confirm_subj'=>$new)); case 'emailconfirmationbody': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_confirm'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_confirm'=>$new)); case 'emailregistration': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_register_subj'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_register_subj'=>$new)); case 'emailregistrationbody': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_register'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_register'=>$new)); case 'email_confirm': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_confirm_subject'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_confirm_subject'=>$new)); case 'email_confirmbody': - return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$surveyid,'surveyls_language'=>$tolang),array('surveyls_email_confirm'=>$new)); + return Surveys_languagesettings::model()->updateByPk(array('surveyls_survey_id'=>$iSurveyID,'surveyls_language'=>$tolang),array('surveyls_email_confirm'=>$new)); case 'group': - return Groups::model()->updateByPk(array('gid'=>$id1, 'language'=>$tolang),array('group_name' => $new), 'sid=:sid', array(':sid'=>$surveyid)); + return Groups::model()->updateByPk(array('gid'=>$id1, 'language'=>$tolang),array('group_name' => $new), 'sid=:sid', array(':sid'=>$iSurveyID)); case 'group_desc': - return Groups::model()->updateByPk(array('gid'=>$id1, 'language'=>$tolang),array('description' => $new), 'sid=:sid', array(':sid'=>$surveyid)); + return Groups::model()->updateByPk(array('gid'=>$id1, 'language'=>$tolang),array('description' => $new), 'sid=:sid', array(':sid'=>$iSurveyID)); case 'question': - return Questions::model()->updateByPk(array('qid'=>$id1, 'language'=>$tolang),array('question' => $new), 'sid=:sid AND parent_qid=0', array(':sid'=>$surveyid)); + return Questions::model()->updateByPk(array('qid'=>$id1, 'language'=>$tolang),array('question' => $new), 'sid=:sid AND parent_qid=0', array(':sid'=>$iSurveyID)); case 'question_help': - return Questions::model()->updateByPk(array('qid'=>$id1, 'language'=>$tolang),array('help' => $new), 'sid=:sid AND parent_qid=0', array(':sid'=>$surveyid)); + return Questions::model()->updateByPk(array('qid'=>$id1, 'language'=>$tolang),array('help' => $new), 'sid=:sid AND parent_qid=0', array(':sid'=>$iSurveyID)); case 'subquestion': - return Questions::model()->updateByPk(array('qid'=>$id1, 'language'=>$tolang),array('question' => $new), 'sid=:sid', array(':sid'=>$surveyid)); + return Questions::model()->updateByPk(array('qid'=>$id1, 'language'=>$tolang),array('question' => $new), 'sid=:sid', array(':sid'=>$iSurveyID)); case 'answer': return Answers::model()->updateByPk(array('qid'=>$id1, 'code'=>$id2, 'language'=>$tolang),array('answer' => $new)); } @@ -854,7 +856,7 @@ private function displayTranslateFieldsHeader($baselangdesc, $tolangdesc, $type) /** * displayTranslateFields() Formats and displays translation fields (base language as well as to language) - * @param string $surveyid Survey id + * @param string $iSurveyID Survey id * @param string $gid Group id * @param string $qid Question id * @param string $type Type of database field that is being translated, e.g. title, question, etc. @@ -868,7 +870,7 @@ private function displayTranslateFieldsHeader($baselangdesc, $tolangdesc, $type) * @param boolean $evenRow TRUE for even rows, FALSE for odd rows * @return string $translateoutput */ - private function displayTranslateFields($surveyid, $gid, $qid, $type, $amTypeOptions, + private function displayTranslateFields($iSurveyID, $gid, $qid, $type, $amTypeOptions, $baselangdesc, $tolangdesc, $textfrom, $textto, $i, $rowfrom, $evenRow) { $translateoutput = ""; @@ -921,7 +923,7 @@ private function displayTranslateFields($surveyid, $gid, $qid, $type, $amTypeOpt "edit" . $type , $type . "_newvalue_" . $i, htmlspecialchars($textto), - $surveyid, + $iSurveyID, $gid, $qid, "translate" . $amTypeOptions["HTMLeditorType"] @@ -990,7 +992,10 @@ private function displayTranslateFieldsFooter() */ private function menuItem( $jsMenuText, $menuImageText, $menuImageFile, $scriptname) { - $img_tag = CHtml::image(Yii::app()->getConfig("imageurl") . "/" . $menuImageFile, $jsMenuText, array('name'=>$menuImageText)); + + $imageurl = Yii::app()->getConfig("adminimageurl"); + + $img_tag = CHtml::image($imageurl . "/" . $menuImageFile, $jsMenuText, array('name'=>$menuImageText)); $menuitem = CHtml::link($img_tag, '#', array( 'onclick' => "window.open('{$scriptname}', '_top')" )); @@ -1003,7 +1008,10 @@ private function menuItem( $jsMenuText, $menuImageText, $menuImageFile, $scriptn */ private function menuSeparator() { - $image = CHtml::image(Yii::app()->getConfig("imageurl") . "/separator.gif", ''); + + $imageurl = Yii::app()->getConfig("adminimageurl"); + + $image = CHtml::image($imageurl . "/separator.gif", ''); return $image; } @@ -1015,9 +1023,9 @@ private function translate_google_api() { header('Content-type: application/json'); - $sBaselang = CHttpRequest::getPost('baselang'); - $sTolang = CHttpRequest::getPost('tolang'); - $sToconvert = CHttpRequest::getPost('text'); + $sBaselang = Yii::app()->getRequest()->getPost('baselang'); + $sTolang = Yii::app()->getRequest()->getPost('tolang'); + $sToconvert = Yii::app()->getRequest()->getPost('text'); $aSearch = array('zh-Hans','zh-Hant-HK','zh-Hant-TW', 'nl-informal','de-informal','it-formal','pt-BR','es-MX','nb','nn'); diff --git a/application/controllers/admin/update.php b/application/controllers/admin/update.php index 48663b6f952..6395dd9c19a 100644 --- a/application/controllers/admin/update.php +++ b/application/controllers/admin/update.php @@ -533,20 +533,18 @@ function db($continue = null) { $clang = $this->getController()->lang; Yii::app()->loadHelper("update/update"); - $getHeader = true; if(isset($continue) && $continue=="yes") { $aViewUrls['output'] = CheckForDBUpgrades($continue); updateCheck(); - $getHeader = false; + $aData['display']['header'] = false; } else { + $aData['display']['header'] = true; $aViewUrls['output'] = CheckForDBUpgrades(); } - $aData['display']['header'] = false; - $this->_renderWrappedTemplate('update', $aViewUrls, $aData); } diff --git a/application/controllers/admin/useraction.php b/application/controllers/admin/useraction.php index b094a0f4f19..eb25741ba71 100644 --- a/application/controllers/admin/useraction.php +++ b/application/controllers/admin/useraction.php @@ -223,7 +223,7 @@ function deluser() } if ($action == "finaldeluser") { - $this->deleteFinalUser($ownerUser, $transfer_surveys_to); + $aViewUrls=$this->deleteFinalUser($ownerUser, $transfer_surveys_to); } else { @@ -246,7 +246,7 @@ function deluser() } } - $this->_renderWrappedTemplate('user', $aViewUrls); + return $aViewUrls; } function deleteFinalUser($result, $transfer_surveys_to) @@ -413,7 +413,7 @@ function setUserRights() ) // if(Yii::app()->session['loginID'] != $postuserid) { $aData['postuserid'] = $postuserid; - $this->_renderWrappedTemplate('user', 'setUserRights', $aData); + $this->_renderWrappedTemplate('user', 'setuserrights', $aData); } // if else { diff --git a/application/controllers/admin/usergroups.php b/application/controllers/admin/usergroups.php index 7ee6dff5898..9d5bd33e7d0 100644 --- a/application/controllers/admin/usergroups.php +++ b/application/controllers/admin/usergroups.php @@ -277,7 +277,7 @@ public function index($ugid = false, $header = false) $aViewUrls = array(); $aData['ugid'] = $ugid; - + $aData['imageurl'] = Yii::app()->getConfig("adminimageurl"); $clang = Yii::app()->lang; if (Yii::app()->session['loginID']) { diff --git a/application/controllers/survey/index.php b/application/controllers/survey/index.php index 4e982a1ca9b..e39a6d6c634 100644 --- a/application/controllers/survey/index.php +++ b/application/controllers/survey/index.php @@ -524,50 +524,52 @@ function sendreq(surveyid) //Clear session and remove the incomplete response if requested. if (isset($move) && $move == "clearall") { + // delete the response but only if not already completed $s_lang = $_SESSION['survey_'.$surveyid]['s_lang']; - if (isset($_SESSION['survey_'.$surveyid]['srid'])) + if (isset($_SESSION['survey_'.$surveyid]['srid']) && !Survey_dynamic::model($surveyid)->isCompleted($_SESSION['survey_'.$surveyid]['srid'])) { - // find out if there are any fuqt questions - checked - $fieldmap = createFieldMap($surveyid,'short',false,false,$s_lang); - foreach ($fieldmap as $field) - { - $q = $field['q']; - if ($q->fileUpload() && !strpos($q->fieldname, "_filecount")) + // delete the response but only if not already completed + $result= dbExecuteAssoc('DELETE FROM {{survey_'.$surveyid.'}} WHERE id='.$_SESSION['survey_'.$surveyid]['srid']." AND submitdate IS NULL"); + if($result->count()>0){ + // find out if there are any fuqt questions - checked + $fieldmap = createFieldMap($surveyid,'short',false,false,$s_lang); //AJS# + foreach ($fieldmap as $field) { - $questions[] = $q; + $q = $field['q']; + if ($q->fileUpload() && !strpos($q->fieldname, "_filecount")) + { + if (!isset($questions)) { $questions = array(); } + $qid[] = $q; + } } - } - // if yes, extract the response json to those questions - if (isset($qid)) - { - $query = "SELECT * FROM {{survey_".$surveyid."}} WHERE id=".$_SESSION['survey_'.$surveyid]['srid']; - $result = dbExecuteAssoc($query); - foreach($result->readAll() as $row) + // if yes, extract the response json to those questions + if (isset($qid)) { - foreach ($questions as $q) + $query = "SELECT * FROM {{survey_".$surveyid."}} WHERE id=".$_SESSION['survey_'.$surveyid]['srid']; + $result = dbExecuteAssoc($query); + foreach($result->readAll() as $row) { - $json = $row[$q->fieldname]; - if ($json == "" || $json == NULL) - continue; - - // decode them - $phparray = json_decode($json); - - foreach ($phparray as $metadata) + foreach ($qid as $question) { - $target = Yii::app()->getConfig("uploaddir")."/surveys/".$surveyid."/files/"; - // delete those files - unlink($target.$metadata->filename); + $json = $row[$q->fieldname]; + if ($json == "" || $json == NULL) + continue; + + // decode them + $phparray = json_decode($json); + + foreach ($phparray as $metadata) + { + $target = Yii::app()->getConfig("uploaddir")."/surveys/".$surveyid."/files/"; + // delete those files + unlink($target.$metadata->filename); + } } } } + // done deleting uploaded files } - // done deleting uploaded files - - - // delete the response but only if not already completed - dbExecuteAssoc('DELETE FROM {{survey_'.$surveyid.'}} WHERE id='.$_SESSION['survey_'.$surveyid]['srid']." AND submitdate IS NULL"); // also delete a record from saved_control when there is one dbExecuteAssoc('DELETE FROM {{saved_control}} WHERE srid='.$_SESSION['survey_'.$surveyid]['srid'].' AND sid='.$surveyid); diff --git a/application/core/Survey_Common_Action.php b/application/core/Survey_Common_Action.php index 9027c88bd7c..c55072bef04 100644 --- a/application/core/Survey_Common_Action.php +++ b/application/core/Survey_Common_Action.php @@ -195,9 +195,16 @@ protected function _renderWrappedTemplate($sAction = '', $aViewUrls = array(), $ $sViewPath .= $sAction . '/'; } + + // Header if(!isset($aData['display']['header']) || $aData['display']['header'] !== false) + { + // Send HTTP header + header("Content-type: text/html; charset=UTF-8"); // needed for correct UTF-8 encoding Yii::app()->getController()->_getAdminHeader(); + } + // Menu bars if (!isset($aData['display']['menu_bars']) || ($aData['display']['menu_bars'] !== false && (!is_array($aData['display']['menu_bars']) || !in_array('browse', array_keys($aData['display']['menu_bars']))))) @@ -345,7 +352,7 @@ function _questionbar($iSurveyId, $gid, $qid, $action = null) foreach ($qrresult as $qrrow) { $q = createQuestion($qrrow->question_types['class'], array('surveyid'=>$iSurveyId, 'id'=>$qid)); - $flatrow = array_map('flattenText', $qrrow->attributes); + $qrrow = $qrrow->attributes; if (hasSurveyPermission($iSurveyId, 'surveycontent', 'read')) { if (count(Survey::model()->findByPk($iSurveyId)->additionalLanguages) != 0) @@ -359,7 +366,7 @@ function _questionbar($iSurveyId, $gid, $qid, $action = null) } } $aData['qproperties']=$q->questionProperties(); - if ($action == 'editansweroptions' || $action == "editsubquestions" || $action == "editquestion" || $action == "editdefaultvalues" || $action == "copyquestion") + if ($action == 'editansweroptions' || $action == "editsubquestions" || $action == "editquestion" || $action == "editdefaultvalues" || $action =="editdefaultvalues" || $action == "copyquestion") { $qshowstyle = "style='display: none'"; } @@ -373,7 +380,7 @@ function _questionbar($iSurveyId, $gid, $qid, $action = null) $aData['qid'] = $qid; $aData['gid'] = $gid; $aData['clang'] = $clang; - $aData['qrrow'] = $flatrow; + $aData['qrrow'] = $qrrow; $aData['baselang'] = $baselang; $aAttributesWithValues = Questions::model()->getAdvancedSettingsWithValues($q, $baselang); $DisplayArray = array(); @@ -889,7 +896,7 @@ function _browsemenubar($iSurveyId, $title='') rsort($tmp_survlangs); $aData['tmp_survlangs'] = $tmp_survlangs; - $this->getController()->render("/admin/browse/browsemenubar_view", $aData); + $this->getController()->render("/admin/responses/browsemenubar_view", $aData); } /** * Load menu bar of user group controller. @@ -903,8 +910,8 @@ function _userGroupBar($ugid = 0) if (!empty($ugid)) { $grpquery = "SELECT gp.* FROM {{user_groups}} AS gp, {{user_in_groups}} AS gu WHERE gp.ugid=gu.ugid AND gp.ugid = $ugid AND gu.uid=" . Yii::app()->session['loginID']; - $grpresult = dbExecuteAssoc($grpquery); - $grpresultcount = dbRecordsCount($grpquery); + $grpresult = Yii::app()->db->createCommand($grpquery)->query(); //Checked + $grpresultcount = $grpresult->getRowCount(); if ($grpresultcount > 0) { $grow = array_map('htmlspecialchars', $grpresult->read()); @@ -920,7 +927,7 @@ function _userGroupBar($ugid = 0) } $data['ugid'] = $ugid; - + $data['imageurl'] = Yii::app()->getConfig("adminimageurl"); // Don't came from rendertemplate ? $this->getController()->render('/admin/usergroup/usergroupbar_view', $data); } diff --git a/application/helpers/SurveyRuntimeHelper.php b/application/helpers/SurveyRuntimeHelper.php index 279ecfaf581..9daac318dfd 100644 --- a/application/helpers/SurveyRuntimeHelper.php +++ b/application/helpers/SurveyRuntimeHelper.php @@ -24,8 +24,12 @@ class SurveyRuntimeHelper { function run($surveyid,$args) { extract($args); $LEMsessid = 'survey_' . $surveyid; - - // $LEMdebugLevel - customizable debugging for Lime Expression Manager + $sTemplatePath=getTemplatePath(Yii::app()->getConfig("defaulttemplate")).DIRECTORY_SEPARATOR; + if (isset ($_SESSION['survey_'.$surveyid]['templatepath'])) + { + $sTemplatePath=$_SESSION['survey_'.$surveyid]['templatepath']; + } + // $LEMdebugLevel - customizable debugging for Lime Expression Manager $LEMdebugLevel = 0; // LEM_DEBUG_TIMING; // (LEM_DEBUG_TIMING + LEM_DEBUG_VALIDATION_SUMMARY + LEM_DEBUG_VALIDATION_DETAIL); $LEMskipReprocessing=false; // true if used GetLastMoveResult to avoid generation of unneeded extra JavaScript switch ($thissurvey['format']) @@ -90,6 +94,8 @@ function run($surveyid,$args) { if (!isset($_SESSION[$LEMsessid]['step'])) // || !$_SESSION[$LEMsessid]['step']) - don't do this for step0, else rebuild the session { $totalquestions = buildsurveysession($surveyid); + $sTemplatePath=$_SESSION['survey_'.$surveyid]['templatepath']; + LimeExpressionManager::StartSurvey($thissurvey['sid'], $surveyMode, $surveyOptions, false, $LEMdebugLevel); $_SESSION[$LEMsessid]['step'] = 0; if ($surveyMode == 'survey') @@ -149,7 +155,7 @@ function run($surveyid,$args) { if (isset($_SESSION[$LEMsessid]['LEMtokenResume'])) { LimeExpressionManager::StartSurvey($thissurvey['sid'], $surveyMode, $surveyOptions, false,$LEMdebugLevel); - $moveResult = LimeExpressionManager::JumpTo($_SESSION[$LEMsessid]['step']+1,false,false); // if late in the survey, will re-validate contents, which may be overkill + $moveResult = LimeExpressionManager::JumpTo($_SESSION[$LEMsessid]['step'],false,false); // if late in the survey, will re-validate contents, which may be overkill unset($_SESSION[$LEMsessid]['LEMtokenResume']); unset($_SESSION[$LEMsessid]['LEMreload']); } @@ -353,12 +359,12 @@ function run($surveyid,$args) { sendCacheHeaders(); doHeader(); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"), array(), $redata); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"), array(), $redata); //Check for assessments if ($thissurvey['assessments'] == "Y" && $assessments) { - echo templatereplace(file_get_contents("$thistpl/assessment.pstpl"), array(), $redata); + echo templatereplace(file_get_contents($sTemplatePath."assessment.pstpl"), array(), $redata); } // fetch all filenames from $_SESSIONS['files'] and delete them all @@ -399,7 +405,7 @@ function run($surveyid,$args) { $thissurvey['surveyls_url']=templatereplace($thissurvey['surveyls_url']); // to do INSERTANS substitutions $content = ''; - $content .= templatereplace(file_get_contents("$thistpl/startpage.pstpl"), array(), $redata); + $content .= templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"), array(), $redata); //Check for assessments if ($thissurvey['assessments'] == "Y") @@ -407,7 +413,7 @@ function run($surveyid,$args) { $assessments = doAssessment($surveyid); if ($assessments) { - $content .= templatereplace(file_get_contents("$thistpl/assessment.pstpl"), array(), $redata); + $content .= templatereplace(file_get_contents($sTemplatePath."assessment.pstpl"), array(), $redata); } } @@ -424,7 +430,7 @@ function run($surveyid,$args) { $content = ''; - $content .= templatereplace(file_get_contents("$thistpl/startpage.pstpl"), array(), $redata); + $content .= templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"), array(), $redata); //echo $thissurvey['url']; //Check for assessments @@ -433,7 +439,7 @@ function run($surveyid,$args) { $assessments = doAssessment($surveyid); if ($assessments) { - $content .= templatereplace(file_get_contents("$thistpl/assessment.pstpl"), array(), $redata); + $content .= templatereplace(file_get_contents($sTemplatePath."assessment.pstpl"), array(), $redata); } } @@ -486,7 +492,9 @@ function run($surveyid,$args) { $url = passthruReplace($thissurvey['surveyls_url'], $thissurvey); $url = templatereplace($url); // TODO - check safety of this - provides access to any replacement value $url = str_replace("{SAVEDID}", $saved_id, $url); // to activate the SAVEDID in the END URL - $url = str_replace("{TOKEN}", $clienttoken, $url); // to activate the TOKEN in the END URL + if(isset($clienttoken) && $clienttoken) { + $url = str_replace("{TOKEN}", $clienttoken, $url); // to activate the TOKEN in the END URL + } $url = str_replace("{SID}", $surveyid, $url); // to activate the SID in the END URL $url = str_replace("{LANG}", $clang->getlangcode(), $url); // to activate the LANG in the END URL header("Location: {$url}"); @@ -503,7 +511,7 @@ function run($surveyid,$args) { echo $content; } $redata['completed'] = $completed; - echo templatereplace(file_get_contents("$thistpl/completed.pstpl"), array('completed' => $completed), $redata); + echo templatereplace(file_get_contents($sTemplatePath."completed.pstpl"), array('completed' => $completed), $redata); echo "\n
\n"; if ((($LEMdebugLevel & LEM_DEBUG_TIMING) == LEM_DEBUG_TIMING)) { @@ -513,7 +521,7 @@ function run($surveyid,$args) { { echo "
Group/Question Validation Results:" . $moveResult['message'] . "
\n"; } - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl")); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl")); doFooter(); exit; } @@ -526,10 +534,10 @@ function run($surveyid,$args) { if ($surveyExists < 1) { //SURVEY DOES NOT EXIST. POLITELY EXIT. - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"), array(), $redata); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"), array(), $redata); echo "\t

\n"; echo "\t" . $clang->gT("Sorry. There is no matching survey.") . "
 \n"; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"), array(), $redata); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"), array(), $redata); doFooter(); exit; } @@ -699,6 +707,9 @@ function run($surveyid,$args) { sendCacheHeaders(); doHeader(); + $redata = compact(array_keys(get_defined_vars())); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"), array(), $redata); + //popup need jquery if (isset($popup)) { echo $popup; @@ -712,10 +723,6 @@ function run($surveyid,$args) { echo $fpopup; } - $redata = compact(array_keys(get_defined_vars())); - - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"), array(), $redata); - //ALTER PAGE CLASS TO PROVIDE WHOLE-PAGE ALTERNATION if ($surveyMode != 'survey' && $_SESSION[$LEMsessid]['step'] != $_SESSION[$LEMsessid]['prevstep'] || (isset($_SESSION[$LEMsessid]['stepno']) && $_SESSION[$LEMsessid]['stepno'] % 2)) @@ -748,19 +755,19 @@ function run($surveyid,$args) { } else { - echo templatereplace(file_get_contents("$thistpl/welcome.pstpl"), array(), $redata) . "\n"; + echo templatereplace(file_get_contents($sTemplatePath."welcome.pstpl"), array(), $redata) . "\n"; } if ($thissurvey['anonymized'] == "Y") { - echo templatereplace(file_get_contents("$thistpl/privacy.pstpl"), array(), $redata) . "\n"; + echo templatereplace(file_get_contents($sTemplatePath."privacy.pstpl"), array(), $redata) . "\n"; } } // <-- START THE SURVEY --> if ($surveyMode != 'survey') { - echo templatereplace(file_get_contents("{$thistpl}/survey.pstpl"), array(), $redata); + echo templatereplace(file_get_contents($sTemplatePath."survey.pstpl"), array(), $redata); } // the runonce element has been changed from a hidden to a text/display:none one @@ -771,22 +778,33 @@ function run($surveyid,$args) { \n"; - echo templatereplace(file_get_contents("$thistpl/endgroup.pstpl"), array(), $redata); + echo templatereplace(file_get_contents($sTemplatePath."endgroup.pstpl"), array(), $redata); echo "\n\n\n"; } @@ -997,7 +1015,7 @@ function checkconditions(value, name, type, evt_type) $redata = compact(array_keys(get_defined_vars())); echo "\n\n\n"; - echo templatereplace(file_get_contents("$thistpl/navigator.pstpl"), array(), $redata); + echo templatereplace(file_get_contents($sTemplatePath."navigator.pstpl"), array(), $redata); echo "\n"; if ($thissurvey['active'] != "Y") @@ -1114,7 +1132,7 @@ function checkconditions(value, name, type, evt_type) } echo "\n"; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"), array(), $redata); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"), array(), $redata); echo "\n"; diff --git a/application/helpers/admin/activate_helper.php b/application/helpers/admin/activate_helper.php index 446b364dbc9..22292a4d8ac 100644 --- a/application/helpers/admin/activate_helper.php +++ b/application/helpers/admin/activate_helper.php @@ -17,12 +17,12 @@ * fixes the numbering of questions * @param $fixnumbering */ -function fixNumbering($fixnumbering, $surveyid) +function fixNumbering($fixnumbering, $iSurveyID) { Yii::app()->loadHelper("database"); - LimeExpressionManager::RevertUpgradeConditionsToRelevance($surveyid); + LimeExpressionManager::RevertUpgradeConditionsToRelevance($iSurveyID); //Fix a question id - requires renumbering a question $oldqid = $fixnumbering; $query = "SELECT qid FROM {{questions}} ORDER BY qid DESC"; @@ -63,7 +63,7 @@ function fixNumbering($fixnumbering, $surveyid) $query = "UPDATE {{answers}} SET qid=$newqid WHERE qid=$oldqid"; $result = db_execute_assosc($query); - LimeExpressionManager::UpgradeConditionsToRelevance($surveyid); + LimeExpressionManager::UpgradeConditionsToRelevance($iSurveyID); } /** * checks consistency of groups @@ -92,15 +92,16 @@ function checkGroup($postsid) /** * checks questions in a survey for consistency * @param $postsid - * @param $surveyid +* @param $iSurveyID * @return array $faildcheck */ -function checkQuestions($postsid, $surveyid) +function checkQuestions($postsid, $iSurveyID) { $clang = Yii::app()->lang; //CHECK TO MAKE SURE ALL QUESTION TYPES THAT REQUIRE ANSWERS HAVE ACTUALLY GOT ANSWERS + $chkquery = "SELECT qid, question, gid, type FROM {{questions}} WHERE sid={$iSurveyID} and parent_qid=0"; $chkresult = Questions::model()->with('question_types')->findAllByAttributes(array('sid' => $surveyid, 'parent_qid' => 0)); foreach ($chkresult as $chkrow) @@ -131,7 +132,7 @@ function checkQuestions($postsid, $surveyid) //NOW CHECK THAT ALL QUESTIONS HAVE A 'QUESTION TYPE' FIELD SET //$chkquery = "SELECT qid, question, gid FROM {{questions}} WHERE sid={$_GET['sid']} AND type = ''"; - $chkquery = "SELECT qid, question, gid FROM {{questions}} WHERE sid={$surveyid} AND type = ''"; + $chkquery = "SELECT qid, question, gid FROM {{questions}} WHERE sid={$iSurveyID} AND type = ''"; $chkresult = Yii::app()->db->createCommand($chkquery)->query()->readAll(); foreach ($chkresult as $chkrow) { @@ -143,7 +144,7 @@ function checkQuestions($postsid, $surveyid) //ChECK THAT certain array question types have answers set //$chkquery = "SELECT q.qid, question, gid FROM {{questions}} as q WHERE (select count(*) from {{answers}} as a where a.qid=q.qid and scale_id=0)=0 and sid={$_GET['sid']} AND type IN ('F', 'H', 'W', 'Z', '1') and q.parent_qid=0"; - $chkquery = "SELECT q.qid, question, gid FROM {{questions}} as q WHERE (select count(*) from {{answers}} as a where a.qid=q.qid and scale_id=0)=0 and sid={$surveyid} AND type IN ('F', 'H', 'W', 'Z', '1') and q.parent_qid=0"; + $chkquery = "SELECT q.qid, question, gid FROM {{questions}} as q WHERE (select count(*) from {{answers}} as a where a.qid=q.qid and scale_id=0)=0 and sid={$iSurveyID} AND type IN ('F', 'H', 'W', 'Z', '1') and q.parent_qid=0"; $chkresult = Yii::app()->db->createCommand($chkquery)->query()->readAll(); foreach($chkresult as $chkrow){ $failedcheck[]=array($chkrow['qid'], $chkrow['question'], ": ".$clang->gT("This question requires answers, but none are set."), $chkrow['gid']); @@ -151,7 +152,7 @@ function checkQuestions($postsid, $surveyid) //CHECK THAT DUAL Array has answers set //$chkquery = "SELECT q.qid, question, gid FROM {{questions}} as q WHERE (select count(*) from {{answers}} as a where a.qid=q.qid and scale_id=1)=0 and sid={$_GET['sid']} AND type='1' and q.parent_qid=0"; - $chkquery = "SELECT q.qid, question, gid FROM {{questions}} as q WHERE (select count(*) from {{answers}} as a where a.qid=q.qid and scale_id=1)=0 and sid={$surveyid} AND type='1' and q.parent_qid=0"; + $chkquery = "SELECT q.qid, question, gid FROM {{questions}} as q WHERE (select count(*) from {{answers}} as a where a.qid=q.qid and scale_id=1)=0 and sid={$iSurveyID} AND type='1' and q.parent_qid=0"; $chkresult = Yii::app()->db->createCommand($chkquery)->query()->readAll(); foreach ($chkresult as $chkrow){ $failedcheck[]=array($chkrow['qid'], $chkrow['question'], ": ".$clang->gT("This question requires a second answer set but none is set."), $chkrow['gid']); @@ -172,7 +173,7 @@ function checkQuestions($postsid, $surveyid) // $c++; // } //TO AVOID NATURAL SORT ORDER ISSUES, FIRST GET ALL QUESTIONS IN NATURAL SORT ORDER, AND FIND OUT WHICH NUMBER IN THAT ORDER THIS QUESTION IS - $qorderquery = "SELECT * FROM {{questions}} WHERE sid=$surveyid AND type not in ('S', 'D', 'T', 'Q')"; + $qorderquery = "SELECT * FROM {{questions}} WHERE sid=$iSurveyID AND type not in ('S', 'D', 'T', 'Q')"; $qorderresult = Yii::app()->db->createCommand($qorderquery)->query()->readAll(); $qrows = array(); //Create an empty array in case FetchRow does not return any rows foreach ($qorderresult as $qrow) {$qrows[] = $qrow;} // Get table output into array @@ -219,7 +220,7 @@ function checkQuestions($postsid, $surveyid) } //CHECK THAT ALL THE CREATED FIELDS WILL BE UNIQUE - $fieldmap = createFieldMap($surveyid,'full',false,false,getBaseLanguageFromSurveyID($surveyid)); //AJS# + $fieldmap = createFieldMap($iSurveyID,'full',false,false,getBaseLanguageFromSurveyID($surveyid)); //AJS# if (isset($fieldmap)) { foreach($fieldmap as $fielddata) @@ -237,7 +238,7 @@ function checkQuestions($postsid, $surveyid) foreach ($duplicates as $dup) { $q = $fieldmap[$dup]['q']; - $fix = "[Click Here to Fix]"; + $fix = "[Click Here to Fix]"; $failedcheck[]=array($badquestion['qid'], $badquestion['question'], ": Bad duplicate fieldname $fix", $badquestion['gid']); } } @@ -249,16 +250,15 @@ function checkQuestions($postsid, $surveyid) /** * Function to activate a survey - * @param int $surveyid The Survey ID +* @param int $iSurveyID The Survey ID * @param bool $simulate * @return string */ -function activateSurvey($surveyid, $simulate = false) +function activateSurvey($iSurveyID, $simulate = false) { - $clang = Yii::app()->lang; $createsurvey=''; $activateoutput=''; @@ -266,19 +266,10 @@ function activateSurvey($surveyid, $simulate = false) $fieldstiming = array(); $createsurveydirectory=false; //Check for any additional fields for this survey and create necessary fields (token and datestamp) - $pquery = "SELECT anonymized, allowregister, datestamp, ipaddr, refurl, savetimings FROM {{surveys}} WHERE sid={$surveyid}"; - $prow = Yii::app()->db->createCommand($pquery)->query()->read(); - if ($prow['allowregister'] == "Y") - { - $surveyallowsregistration="TRUE"; - } - if ($prow['savetimings'] == "Y") - { - $savetimings="TRUE"; - } + $prow = Survey::model()->findByAttributes(array('sid' => $iSurveyID)); //Get list of questions for the base language - $fieldmap = createFieldMap($surveyid,'full',true,false,getBaseLanguageFromSurveyID($surveyid)); //AJS + $fieldmap = createFieldMap($iSurveyID,'full',true,false,getBaseLanguageFromSurveyID($surveyid)); //AJS $createsurvey = array(); foreach ($fieldmap as $arow) //With each question, create the appropriate field(s) @@ -303,15 +294,15 @@ function activateSurvey($surveyid, $simulate = false) $createsurvey[$q->fieldname] = "integer"; break; case "ipaddr": - if ($prow['ipaddr'] == "Y") + if ($prow->ipaddr == "Y") $createsurvey[$q->fieldname] = "text"; break; case "refurl": - if ($prow['refurl'] == "Y") + if ($prow->refurl == "Y") $createsurvey[$q->fieldname] = "text"; break; case "token": - if ($prow['anonymized'] == "N") + if ($prow->anonymized == "N") { $createsurvey[$q->fieldname] = "VARCHAR(36)"; } @@ -344,36 +335,18 @@ function activateSurvey($surveyid, $simulate = false) // If last question is of type MCABCEFHP^QKJR let's get rid of the ending coma in createsurvey //$createsurvey = rtrim($createsurvey, ",\n")."\n"; // Does nothing if not ending with a comma - $tabname = "{{survey_{$surveyid}}}"; + $tabname = "{{survey_{$iSurveyID}}}"; $command = new CDbCommand(Yii::app()->db); try { $execresult = $command->createTable($tabname,$createsurvey); - $execresult = true; } catch (CDbException $e) { - echo $e->getMessage(); - $execresult = false; + return array('error'=>'surveytablecreation'); } - - if (!$execresult) - { - $link = Yii::app()->getController()->createUrl("admin/survey/view/surveyid/".$surveyid); - $activateoutput .= "
\n
\n" . - "
".$clang->gT("Activate Survey")." ($surveyid)
\n" . - "
".$clang->gT("Survey could not be actived.")."
\n" . - "

" . - $clang->gT("Database error!!")."\n " ."\n" . - "

".implode(' ', $createsurvey)."
\n - ".$clang->gT("Main Admin Screen")."\n
" ; - } - - if ($execresult) - { - - $anquery = "SELECT autonumber_start FROM {{surveys}} WHERE sid={$surveyid}"; + $anquery = "SELECT autonumber_start FROM {{surveys}} WHERE sid={$iSurveyID}"; if ($anresult=Yii::app()->db->createCommand($anquery)->query()->readAll()) { //if there is an autonumber_start field, start auto numbering here @@ -382,25 +355,25 @@ function activateSurvey($surveyid, $simulate = false) if ($row['autonumber_start'] > 0) { if (Yii::app()->db->driverName=='mssql' || Yii::app()->db->driverName=='sqlsrv') { - mssql_drop_primary_index('survey_'.$surveyid); - mssql_drop_constraint('id','survey_'.$surveyid); - $autonumberquery = "alter table {{survey_{$surveyid}}} drop column id "; - Yii::app()->db->createCommand($autonumberquery)->query()->readAll(); - $autonumberquery = "alter table {{survey_{$surveyid}}} add [id] int identity({$row['autonumber_start']},1)"; - Yii::app()->db->createCommand($autonumberquery)->query()->readAll(); + mssql_drop_primary_index('survey_'.$iSurveyID); + mssql_drop_constraint('id','survey_'.$iSurveyID); + $autonumberquery = "alter table {{survey_{$iSurveyID}}} drop column id "; + Yii::app()->db->createCommand($autonumberquery)->execute(); + $autonumberquery = "alter table {{survey_{$iSurveyID}}} add [id] int identity({$row['autonumber_start']},1)"; + Yii::app()->db->createCommand($autonumberquery)->execute(); } else { - $autonumberquery = "ALTER TABLE {{survey_{$surveyid}}} AUTO_INCREMENT = ".$row['autonumber_start']; + $autonumberquery = "ALTER TABLE {{survey_{$iSurveyID}}} AUTO_INCREMENT = ".$row['autonumber_start']; $result = @Yii::app()->db->createCommand($autonumberquery)->execute(); } } } } - if (isset($savetimings) && $savetimings=="TRUE") + if ($prow->savetimings == "Y") { - $timingsfieldmap = createFieldMap($surveyid,"short",false,false,getBaseLanguageFromSurveyID($surveyid)); //AJS# + $timingsfieldmap = createFieldMap($iSurveyID,"short",false,false,getBaseLanguageFromSurveyID($surveyid)); //AJS# $column['id'] = $createsurvey['id']; $column['interviewtime'] = 'FLOAT'; @@ -417,63 +390,36 @@ function activateSurvey($surveyid, $simulate = false) } $command = new CDbCommand(Yii::app()->db); - $tabname = "{{survey_{$surveyid}}}_timings"; + $tabname = "{{survey_{$iSurveyID}}}_timings"; try { $execresult = $command->createTable($tabname,$column); - $execresult = true; } catch (CDbException $e) { - echo $e->getMessage(); - $execresult = false; + return array('error'=>'timingstablecreation'); } } - - $activateoutput .= "
\n
\n"; - $activateoutput .= "
".$clang->gT("Activate Survey")." ($surveyid)
\n"; - $activateoutput .= "
".$clang->gT("Survey has been activated. Results table has been successfully created.")."


\n"; - + $aResult=array('status'=>'OK'); // create the survey directory where the uploaded files can be saved if ($createsurveydirectory) { - if (!file_exists(Yii::app()->getConfig('uploaddir') . "/surveys/" . $surveyid . "/files")) + if (!file_exists(Yii::app()->getConfig('uploaddir') . "/surveys/" . $iSurveyID . "/files")) { - if (!(mkdir(Yii::app()->getConfig('uploaddir') . "/surveys/" . $surveyid . "/files", 0777, true))) + if (!(mkdir(Yii::app()->getConfig('uploaddir') . "/surveys/" . $iSurveyID . "/files", 0777, true))) { - $activateoutput .= "
" . - $clang->gT("The required directory for saving the uploaded files couldn't be created. Please check file premissions on the /upload/surveys directory.") . "
"; + $aResult['warning']='nouploadsurveydir'; } else { - file_put_contents(Yii::app()->getConfig('uploaddir') . "/surveys/" . $surveyid . "/files/index.html", ''); + file_put_contents(Yii::app()->getConfig('uploaddir') . "/surveys/" . $iSurveyID . "/files/index.html", ''); } } } - $acquery = "UPDATE {{surveys}} SET active='Y' WHERE sid=".$surveyid; + $acquery = "UPDATE {{surveys}} SET active='Y' WHERE sid=".$iSurveyID; $acresult = Yii::app()->db->createCommand($acquery)->query(); - if (isset($surveyallowsregistration) && $surveyallowsregistration == "TRUE") - { - $activateoutput .= $clang->gT("This survey allows public registration. A token table must also be created.")."

\n"; - $activateoutput .= "getController()->createUrl("admin/tokens/index/surveyid/".$surveyid))."\" />\n"; - } - else - { - $link = Yii::app()->getController()->createUrl("admin/survey/view/surveyid/".$surveyid); - - $activateoutput .= $clang->gT("This survey is now active, and responses can be recorded.")."

\n"; - $activateoutput .= "".$clang->gT("Open-access mode").": ".$clang->gT("No invitation code is needed to complete the survey.")."
".$clang->gT("You can switch to the closed-access mode by initialising a token table with the button below.")."

\n"; - $activateoutput .= "getController()->createUrl("admin/tokens/index/surveyid/".$surveyid))."\" />\n"; - $activateoutput .= "\n"; + return $aResult; } - $activateoutput .= "

 \n"; - $lsrcOutput = true; - } - - - return $activateoutput; - -} function mssql_drop_constraint($fieldname, $tablename) { @@ -487,7 +433,7 @@ function mssql_drop_constraint($fieldname, $tablename) sys.sysobjects AS t_obj ON c_obj.parent_obj = t_obj.id INNER JOIN sys.sysconstraints AS con ON c_obj.id = con.constid INNER JOIN sys.syscolumns AS col ON t_obj.id = col.id AND con.colid = col.colid - WHERE (c_obj.xtype = 'D') AND (col.name = '$fieldname') AND (t_obj.name={{{$tablename}}})"; + WHERE (c_obj.xtype = 'D') AND (col.name = '$fieldname') AND (t_obj.name='{{{$tablename}}}')"; $result = dbExecuteAssoc($dfquery)->read(); $defaultname=$result['CONTRAINT_NAME']; if ($defaultname!=false) @@ -505,12 +451,11 @@ function mssql_drop_primary_index($tablename) // find out the constraint name of the old primary key $pkquery = "SELECT CONSTRAINT_NAME " ."FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS " - ."WHERE (TABLE_NAME = {{{$tablename}}}) AND (CONSTRAINT_TYPE = 'PRIMARY KEY')"; + ."WHERE (TABLE_NAME = '{{{$tablename}}}') AND (CONSTRAINT_TYPE = 'PRIMARY KEY')"; - $result = dbExecuteAssoc($pkquery)->read(); - $primarykey=$result['CONTSTRAINT_NAME']; - if ($primarykey!=false) + $primarykey = Yii::app()->db->createCommand($pkquery)->queryRow(false); + if ($primarykey!==false) { - modifyDatabase("","ALTER TABLE {{{$tablename}}} DROP CONSTRAINT {$primarykey}"); echo $modifyoutput; flush(); + Yii::app()->db->createCommand("ALTER TABLE {{{$tablename}}} DROP CONSTRAINT {$primarykey[0]}")->execute(); } } diff --git a/application/helpers/admin/exportresults_helper.php b/application/helpers/admin/exportresults_helper.php index a66bc72d92f..74c3ddad031 100644 --- a/application/helpers/admin/exportresults_helper.php +++ b/application/helpers/admin/exportresults_helper.php @@ -1,17 +1,17 @@ selectedColumns)) + if (empty($oOptions->selectedColumns)) { safeDie('At least one column must be selected for export.'); } - //echo $options->toString().PHP_EOL; + //echo $oOptions->toString().PHP_EOL; $writer = null; - $intSurveyId = sanitize_int($surveyId); + $iSurveyId = sanitize_int($iSurveyId); - switch ( $options->format ) { + switch ( $oOptions->format ) { case "doc": - header("Content-Disposition: attachment; filename=results-survey".$intSurveyId.".doc"); - header("Content-type: application/vnd.ms-word"); + if ($sOutputStyle=='display') + { + header("Content-Disposition: attachment; filename=results-survey".$iSurveyId.".doc"); + header("Content-type: application/vnd.ms-word"); + } $writer = new DocWriter(); break; case "xls": - $writer = new ExcelWriter(); - break; - case "csv": - header("Content-Disposition: attachment; filename=results-survey".$intSurveyId.".csv"); - header("Content-type: text/comma-separated-values; charset=UTF-8"); - $writer = new CsvWriter(); + if ($sOutputStyle=='return') + { + $sRandomFileName=Yii::app()->getConfig("tempdir"). DIRECTORY_SEPARATOR . randomChars(40); + $writer = new ExcelWriter($sRandomFileName); + } + else + { + $writer = new ExcelWriter(); + } break; case "pdf": Yii::import("application.libraries.admin.pdf", true); - $writer = new PdfWriter(); + if ($sOutputStyle=='return') + { + $sRandomFileName=Yii::app()->getConfig("tempdir") . DIRECTORY_SEPARATOR . randomChars(40); + $writer = new PdfWriter($sRandomFileName); + } + else + { + $writer = new PdfWriter(); + } break; + case "csv": default: - header("Content-Disposition: attachment; filename=results-survey".$intSurveyId.".csv"); - header("Content-type: text/comma-separated-values; charset=UTF-8"); + if ($sOutputStyle=='display') + { + header("Content-Disposition: attachment; filename=results-survey".$iSurveyId.".csv"); + header("Content-type: text/comma-separated-values; charset=UTF-8"); + } $writer = new CsvWriter(); break; } - header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); - header("Pragma: public"); + if ($sOutputStyle=='display') + { + header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); + header("Pragma: public"); + } $surveyDao = new SurveyDao(); - $survey = $surveyDao->loadSurveyById($intSurveyId); - $surveyDao->loadSurveyResults($survey, $options->responseMinRecord, $options->responseMaxRecord); + $survey = $surveyDao->loadSurveyById($iSurveyId); + $surveyDao->loadSurveyResults($survey, $oOptions->responseMinRecord, $oOptions->responseMaxRecord); - $writer->write($survey, $languageCode, $options); + $writer->write($survey, $sLanguageCode, $oOptions); $output = $writer->close(); - if ($options->format == 'csv' || $options->format == 'doc') + if (($oOptions->format == 'csv' || $oOptions->format == 'doc') && $sOutputStyle='display') { echo $output; } + if (($oOptions->format == 'xls' || $oOptions->format == 'pdf') && $sOutputStyle='return') + { + $output=file_get_contents($sRandomFileName); + unlink($sRandomFileName); + } return $output; } } @@ -142,9 +168,9 @@ class FormattingOptions /** * Acceptable values are: - * "abrev" = Abbreviated headings + * "abbreviated" = Abbreviated headings * "full" = Full headings - * "headcodes" = Question codes + * "code" = Question codes * * @var string */ @@ -291,7 +317,7 @@ public function loadSurveyResults(SurveyObj $survey, $minRecord = null, $maxReco { /* @var $recordSet ADORecordSet */ - $sql = 'SELECT * FROM {{survey_' . $survey->id . '}}'; + $sql = 'SELECT * FROM {{survey_' . $survey->id . '}} order by id'; if (!isset($minRecord) && !isset($maxRecord)) { //Neither min or max is set, load it all. @@ -497,6 +523,204 @@ public function getSubQuestionArrays($parentQuestionId) } /** +<<<<<<< HEAD +======= + * Returns the full answer for the question that matches $fieldName + * and the answer that matches the $answerCode. If a match cannot + * be made then false is returned. + * + * The name of the variable $answerCode is not strictly an answerCode + * but could also be a comment entered by a participant. + * + * @param string $fieldName + * @param string $answerCode + * @param Translator $translator + * @param string $sLanguageCode + * @return string (or false) + */ + public function getFullAnswer($fieldName, $answerCode, Translator $translator, $sLanguageCode) + { + $fullAnswer = null; + $fieldType = $this->fieldMap[$fieldName]['type']; + $question = $this->getQuestionArray($fieldName); + $questionId = $question['qid']; + $answers = $this->getAnswers($questionId); + if (array_key_exists($answerCode, $answers)) + { + $answer = $answers[$answerCode]['answer']; + } + else + { + $answer = null; + } + + //echo "\n$fieldName: $fieldType = $answerCode"; + switch ($fieldType) + { + case 'R': //RANKING TYPE + $fullAnswer = $answer; + break; + + case '1': //Array dual scale + if (mb_substr($fieldName, -1) == 0) + { + $answers = $this->getAnswers($questionId, 0); + } + else + { + $answers = $this->getAnswers($questionId, 1); + } + if (array_key_exists($answerCode, $answers)) + { + $fullAnswer = $answers[$answerCode]['answer']; + } + else + { + $fullAnswer = null; + } + break; + + case 'L': //DROPDOWN LIST + case '!': + if (mb_substr($fieldName, -5, 5) == 'other') + { + $fullAnswer = $answerCode; + } + else + { + if ($answerCode == '-oth-') + { + $fullAnswer = $translator->translate('Other', $sLanguageCode); + } + else + { + $fullAnswer = $answer; + } + } + break; + + case 'O': //DROPDOWN LIST WITH COMMENT + if (isset($answer)) + { + //This is one of the dropdown list options. + $fullAnswer = $answer; + } + else + { + //This is a comment. + $fullAnswer = $answerCode; + } + break; + + case 'Y': //YES/NO + switch ($answerCode) + { + case 'Y': + $fullAnswer = $translator->translate('Yes', $sLanguageCode); + break; + + case 'N': + $fullAnswer = $translator->translate('No', $sLanguageCode); + break; + + default: + $fullAnswer = $translator->translate('N/A', $sLanguageCode); + } + break; + + case 'G': + switch ($answerCode) + { + case 'M': + $fullAnswer = $translator->translate('Male', $sLanguageCode); + break; + + case 'F': + $fullAnswer = $translator->translate('Female', $sLanguageCode); + break; + + default: + $fullAnswer = $translator->translate('N/A', $sLanguageCode); + } + break; + + case 'M': //MULTIOPTION + case 'P': + if (mb_substr($fieldName, -5, 5) == 'other' || mb_substr($fieldName, -7, 7) == 'comment') + { + //echo "\n -- Branch 1 --"; + $fullAnswer = $answerCode; + } + else + { + switch ($answerCode) + { + case 'Y': + $fullAnswer = $translator->translate('Yes', $sLanguageCode); + break; + + case 'N': + case '': + $fullAnswer = $translator->translate('No', $sLanguageCode); + break; + + default: + //echo "\n -- Branch 2 --"; + $fullAnswer = $answerCode; + } + } + break; + + case 'C': + switch ($answerCode) + { + case 'Y': + $fullAnswer = $translator->translate('Yes', $sLanguageCode); + break; + + case 'N': + $fullAnswer = $translator->translate('No', $sLanguageCode); + break; + + case 'U': + $fullAnswer = $translator->translate('Uncertain', $sLanguageCode); + break; + } + break; + + case 'E': + switch ($answerCode) + { + case 'I': + $fullAnswer = $translator->translate('Increase', $sLanguageCode); + break; + + case 'S': + $fullAnswer = $translator->translate('Same', $sLanguageCode); + break; + + case 'D': + $fullAnswer = $translator->translate('Decrease', $sLanguageCode); + break; + } + break; + + case 'F': + case 'H': + $answers = $this->getAnswers($questionId, 0); + $fullAnswer = (isset($answers[$answerCode])) ? $answers[$answerCode]['answer'] : ""; + break; + + default: + + $fullAnswer .= $answerCode; + } + + return $fullAnswer; + } + + /** +>>>>>>> 39b5089519acbd1c950066dd62fb9f672bebcdf8 * Returns an array of possible answers to the question. If $scaleId is * specified then only answers that match the $scaleId value will be * returned. An empty array @@ -549,9 +773,9 @@ class Translator //'tid' => 'Token ID' ); - public function translate($key, $languageCode) + public function translate($key, $sLanguageCode) { - return $this->getTranslationLibrary($languageCode)->gT($key); + return $this->getTranslationLibrary($sLanguageCode)->gT($key); } /** @@ -568,16 +792,16 @@ public function translate($key, $languageCode) * survey data column. * * @param string $column - * @param string $languageCode + * @param string $sLanguageCode * @return string */ - public function translateHeading($column, $languageCode) + public function translateHeading($column, $sLanguageCode) { $key = $this->getHeaderTranslationKey($column); //echo "Column: $column, Key: $key".PHP_EOL; if ($key) { - return $this->translate($key, $languageCode); + return $this->translate($key, $sLanguageCode); } else { @@ -585,17 +809,17 @@ public function translateHeading($column, $languageCode) } } - protected function getTranslationLibrary($languageCode) + protected function getTranslationLibrary($sLanguageCode) { $library = null; - if (!array_key_exists($languageCode, $this->translations)) + if (!array_key_exists($sLanguageCode, $this->translations)) { - $library = new limesurvey_lang($languageCode); - $this->translations[$languageCode] = $library; + $library = new limesurvey_lang($sLanguageCode); + $this->translations[$sLanguageCode] = $library; } else { - $library = $this->translations[$languageCode]; + $library = $this->translations[$sLanguageCode]; } return $library; } @@ -630,10 +854,10 @@ interface IWriter * and results from the database. * * @param Survey $survey - * @param string $languagecode - * @param FormattingOptions $options + * @param string $sLanguageCode + * @param FormattingOptions $oOptions */ - public function write(SurveyObj $survey, $languageCode, FormattingOptions $options); + public function write(SurveyObj $survey, $sLanguageCode, FormattingOptions $oOptions); public function close(); } @@ -646,24 +870,24 @@ public function close(); */ abstract class Writer implements IWriter { - public $languageCode; + public $sLanguageCode; public $translator; - public function translate($key, $languageCode) + public function translate($key, $sLanguageCode) { - return $this->translator->translate($key, $languageCode); + return $this->translator->translate($key, $sLanguageCode); } - protected function translateHeading($column, $languageCode) + protected function translateHeading($column, $sLanguageCode) { - return $this->translator->translateHeading($column, $languageCode); + return $this->translator->translateHeading($column, $sLanguageCode); } - private final function initialize(SurveyObj $survey, $languageCode, FormattingOptions $options) + private final function initialize(SurveyObj $survey, $sLanguageCode, FormattingOptions $oOptions) { - $this->languageCode = $languageCode; + $this->languageCode = $sLanguageCode; $this->translator = new Translator(); - $this->init($survey, $languageCode, $options); + $this->init($survey, $sLanguageCode, $oOptions); } /** @@ -672,26 +896,27 @@ private final function initialize(SurveyObj $survey, $languageCode, FormattingOp * may need for setup. * * @param Survey $survey - * @param mixed $languageCode - * @param FormattingOptions $options + * @param mixed $sLanguageCode + * @param FormattingOptions $oOptions */ - protected function init(SurveyObj $survey, $languageCode, FormattingOptions $options) + protected function init(SurveyObj $survey, $sLanguageCode, FormattingOptions $oOptions) { //This implementation does nothing. } /** - * Returns true if, given the $options, the response should be included in the + * Returns true if, given the $oOptions, the response should be included in the * output, and false if otherwise. * * @param mixed $response - * @param FormattingOptions $options + * @param FormattingOptions $oOptions * @return boolean */ - protected function shouldOutputResponse(array $response, FormattingOptions $options) + protected function shouldOutputResponse(array $response, FormattingOptions $oOptions) { - switch ($options->responseCompletionState) + switch ($oOptions->responseCompletionState) { + default: case 'show': return true; break; @@ -704,9 +929,6 @@ protected function shouldOutputResponse(array $response, FormattingOptions $opti return isset($response['submitdate']); break; - default: - //Ut oh - safeDie('An invalid incomplete answer filter state was encountered: '.$options->responseCompletionState); } } @@ -740,7 +962,7 @@ public function getAbbreviatedHeading(SurveyObj $survey, $q) * False is returned if no matching question is found. * * @param Survey $survey - * @param FormattingOptions $options + * @param FormattingOptions $oOptions * @param string $fieldName * @return string (or false) */ @@ -785,20 +1007,20 @@ public function getCommentSubHeading() * the code that is called after all initialization is completed. * * @param Survey $survey - * @param string $languageCode - * @param FormattingOptions $options + * @param string $sLanguageCode + * @param FormattingOptions $oOptions */ - final public function write(SurveyObj $survey, $languageCode, FormattingOptions $options) + final public function write(SurveyObj $survey, $sLanguageCode, FormattingOptions $oOptions) { - $this->initialize($survey, $languageCode, $options); + $this->initialize($survey, $sLanguageCode, $oOptions); //Output the survey. $headers = array(); - foreach ($options->selectedColumns as $column) + foreach ($oOptions->selectedColumns as $column) { //Output the header. - $value = $this->translateHeading($column, $languageCode); - if(!$value) + $value = $this->translateHeading($column, $sLanguageCode); + if($value===false) { //This branch may be reached erroneously if columns are added to the LimeSurvey product //but are not updated in the Writer->headerTranslationKeys array. We should trap for this @@ -806,27 +1028,23 @@ final public function write(SurveyObj $survey, $languageCode, FormattingOptions //FIXME fix the above condition //Survey question field, $column value is a field name from the getFieldMap function. + $q = $survey->fieldMap[$column]['q']; - switch ($options->headingFormat) + switch ($oOptions->headingFormat) { - case 'abrev': + case 'abbreviated': $value = $this->getAbbreviatedHeading($survey, $q); break; - - case 'headcodes': - $value = $this->getCodeHeading($survey, $q); - break; - case 'full': $value = $this->getFullHeading($survey, $q); break; - default: - //Ut oh. - safeDie('An invalid header format option was specified: '.$options->headingFormat); + case 'code': + $value = $this->getCodeHeading($survey, $q); + break; } } - if ($options->headerSpacesToUnderscores) + if ($oOptions->headerSpacesToUnderscores) { $value = str_replace(' ', '_', $value); } @@ -842,12 +1060,12 @@ final public function write(SurveyObj $survey, $languageCode, FormattingOptions //If we shouldn't be outputting this response then we should skip the rest //of the loop and continue onto the next value. - if (!$this->shouldOutputResponse($response, $options)) + if (!$this->shouldOutputResponse($response, $oOptions)) { continue; } - foreach ($options->selectedColumns as $column) + foreach ($oOptions->selectedColumns as $column) { $value = $response[$column]; $q = $survey->fieldMap[$column]['q']; @@ -858,22 +1076,18 @@ final public function write(SurveyObj $survey, $languageCode, FormattingOptions continue; } - switch ($options->answerFormat) { - case 'short': - $elementArray[] = $q->transformResponseValue($this, $value, $options); - break; - + switch ($oOptions->answerFormat) { case 'long': - $elementArray[] = $q->transformResponseValue($this, $q->getFullAnswer($value, $this, $survey), $options); + $elementArray[] = $elementArray[] = $q->transformResponseValue($this, $q->getFullAnswer($value, $this, $survey), $oOptions); break; - default: - //Ut oh - safeDie('An invalid answer format was encountered: '.$options->answerFormat); + case 'short': + $elementArray[] = $q->transformResponseValue($this, $value, $oOptions); + break; } } - $this->outputRecord($headers, $elementArray, $options); + $this->outputRecord($headers, $elementArray, $oOptions); } } @@ -892,9 +1106,9 @@ public function stripTagsFull($string) * * @param array $headers * @param array $values - * @param FormattingOptions $options + * @param FormattingOptions $oOptions */ - abstract protected function outputRecord($headers, $values, FormattingOptions $options); + abstract protected function outputRecord($headers, $values, FormattingOptions $oOptions); } class CsvWriter extends Writer @@ -910,7 +1124,7 @@ function __construct() $this->hasOutputHeader = false; } - protected function outputRecord($headers, $values, FormattingOptions $options) + protected function outputRecord($headers, $values, FormattingOptions $oOptions) { if(!$this->hasOutputHeader) { @@ -965,7 +1179,7 @@ public function __construct() $this->isBeginning = true; } - public function init(SurveyObj $survey, $languageCode, FormattingOptions $options) + public function init(SurveyObj $survey, $sLanguageCode, FormattingOptions $oOptions) { //header("Content-Disposition: attachment; filename=results-survey".$survey->id.".doc"); //header("Content-type: application/vnd.ms-word"); @@ -985,16 +1199,16 @@ public function init(SurveyObj $survey, $languageCode, FormattingOptions $option /** * @param array $headers * @param array $values - * @param FormattingOptions $options + * @param FormattingOptions $oOptions */ - protected function outputRecord($headers, $values, FormattingOptions $options) + protected function outputRecord($headers, $values, FormattingOptions $oOptions) { - if ($options->answerFormat == 'short') + if ($oOptions->answerFormat == 'short') { //No headers at all, only output values. $this->output .= implode($this->separator, $values).PHP_EOL; } - elseif ($options->answerFormat == 'long') + elseif ($oOptions->answerFormat == 'long') { //Output each record, one per page, with a header preceding every value. if ($this->isBeginning) @@ -1058,14 +1272,11 @@ public function __construct($filename = null) Yii::import('application.libraries.admin.pear.Spreadsheet.Excel.Xlswriter', true); if (!empty($filename)) { - $this->workbook = new xlswriter; - $this->outputToFile = true; - $this->fileName = $filename; + $this->workbook = new xlswriter($filename); } else { $this->workbook = new xlswriter; - $this->outputToFile = false; } $this->separator = '~|'; @@ -1073,7 +1284,7 @@ public function __construct($filename = null) $this->rowCounter = 1; } - protected function init(SurveyObj $survey, $languageCode, FormattingOptions $options) + protected function init(SurveyObj $survey, $sLanguageCode, FormattingOptions $oOptions) { $this->workbook->send('results-survey'.$survey->id.'.xls'); $worksheetName = $survey->languageSettings[0]['surveyls_title']; @@ -1088,7 +1299,7 @@ protected function init(SurveyObj $survey, $languageCode, FormattingOptions $opt $this->currentSheet = $sheet; } - protected function outputRecord($headers, $values, FormattingOptions $options) + protected function outputRecord($headers, $values, FormattingOptions $oOptions) { if (!$this->hasOutputHeader) { @@ -1151,7 +1362,8 @@ public function __construct($filename = null) //come from the Lime Survey config files. global $pdforientation, $pdfdefaultfont, $pdffontsize; - + + Yii::import('application.libraries.admin.pdf', true); $this->pdf = new PDF($pdforientation,'mm','A4'); $this->pdf->SetFont($pdfdefaultfont, '', $pdffontsize); $this->pdf->AddPage(); @@ -1163,16 +1375,16 @@ public function __construct($filename = null) $this->rowCounter = 0; } - protected function init(SurveyObj $survey, $languageCode, FormattingOptions $options) + protected function init(SurveyObj $survey, $sLanguageCode, FormattingOptions $oOptions) { $this->surveyName = $survey->languageSettings[0]['surveyls_title']; $this->pdf->titleintopdf($this->surveyName, $survey->languageSettings[0]['surveyls_description']); } - public function outputRecord($headers, $values, FormattingOptions $options) + public function outputRecord($headers, $values, FormattingOptions $oOptions) { $this->rowCounter++; - if ($options->answerFormat == 'short') + if ($oOptions->answerFormat == 'short') { $pdfstring = ''; $this->pdf->titleintopdf($this->translate('New Record', $this->languageCode)); @@ -1182,7 +1394,7 @@ public function outputRecord($headers, $values, FormattingOptions $options) } $this->pdf->intopdf($pdfstring); } - elseif ($options->answerFormat == 'long') + elseif ($oOptions->answerFormat == 'long') { if ($this->rowCounter != 1) { @@ -1200,7 +1412,7 @@ public function outputRecord($headers, $values, FormattingOptions $options) } else { - safeDie('An invalid answer format was encountered: '.$options->answerFormat); + safeDie('An invalid answer format was encountered: '.$oOptions->answerFormat); } } diff --git a/application/helpers/admin/import_helper.php b/application/helpers/admin/import_helper.php index d99eed4c891..47ebb188946 100644 --- a/application/helpers/admin/import_helper.php +++ b/application/helpers/admin/import_helper.php @@ -9,7 +9,6 @@ * is derivative of works licensed under the GNU General Public License or * other free or open source software licenses. * See COPYRIGHT.php for copyright notices and details. -* */ @@ -404,7 +403,7 @@ function CSVImportGroup($sFullFilepath, $iNewSID) } // replace the sid - $oldsid=$grouprowdata['sid']; + $iOldSID=$grouprowdata['sid']; $grouprowdata['sid']=$iNewSID; // replace the gid or remove it if needed (it also will calculate the group order if is a new group) @@ -428,8 +427,8 @@ function CSVImportGroup($sFullFilepath, $iNewSID) $grouprowdata=array_map('convertCSVReturnToReturn', $grouprowdata); // translate internal links - $grouprowdata['group_name']=translateLinks('survey', $oldsid, $iNewSID, $grouprowdata['group_name']); - $grouprowdata['description']=translateLinks('survey', $oldsid, $iNewSID, $grouprowdata['description']); + $grouprowdata['group_name']=translateLinks('survey', $iOldSID, $iNewSID, $grouprowdata['group_name']); + $grouprowdata['description']=translateLinks('survey', $iOldSID, $iNewSID, $grouprowdata['description']); $gres = Yii::app()->db->createCommand()->insert('{{groups}}', $grouprowdata); @@ -502,9 +501,9 @@ function CSVImportGroup($sFullFilepath, $iNewSID) $questionrowdata=array_map('convertCSVReturnToReturn', $questionrowdata); // translate internal links - $questionrowdata['title']=translateLinks('survey', $oldsid, $iNewSID, $questionrowdata['title']); - $questionrowdata['question']=translateLinks('survey', $oldsid, $iNewSID, $questionrowdata['question']); - $questionrowdata['help']=translateLinks('survey', $oldsid, $iNewSID, $questionrowdata['help']); + $questionrowdata['title']=translateLinks('survey', $iOldSID, $iNewSID, $questionrowdata['title']); + $questionrowdata['question']=translateLinks('survey', $iOldSID, $iNewSID, $questionrowdata['question']); + $questionrowdata['help']=translateLinks('survey', $iOldSID, $iNewSID, $questionrowdata['help']); $newvalues=array_values($questionrowdata); $qres = Yii::app()->db->createCommand()->insert('{{questions}}', $questionrowdata); @@ -617,7 +616,7 @@ function CSVImportGroup($sFullFilepath, $iNewSID) $qres = Yii::app()->db->createCommand()->insert('{{defaultvalues}}', $insertdata); } // translate internal links - $answerrowdata['answer']=translateLinks('survey', $oldsid, $iNewSID, $answerrowdata['answer']); + $answerrowdata['answer']=translateLinks('survey', $iOldSID, $iNewSID, $answerrowdata['answer']); // Everything set - now insert it $answerrowdata = array_map('convertCSVReturnToReturn', $answerrowdata); @@ -838,14 +837,14 @@ function XMLImportGroup($sFullFilepath, $iNewSID) { $insertdata[(string)$key]=(string)$value; } - $oldsid=$insertdata['sid']; + $iOldSID=$insertdata['sid']; $insertdata['sid']=$iNewSID; $insertdata['group_order']=$newgrouporder; $oldgid=$insertdata['gid']; unset($insertdata['gid']); // save the old qid // now translate any links - $insertdata['group_name']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['group_name']); - $insertdata['description']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['description']); + $insertdata['group_name']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['group_name']); + $insertdata['description']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['description']); // Insert the new question if (isset($aGIDReplacements[$oldgid])) { @@ -876,16 +875,16 @@ function XMLImportGroup($sFullFilepath, $iNewSID) { $insertdata[(string)$key]=(string)$value; } - $oldsid=$insertdata['sid']; + $iOldSID=$insertdata['sid']; $insertdata['sid']=$iNewSID; if (!isset($aGIDReplacements[$insertdata['gid']]) || trim($insertdata['title'])=='') continue; // Skip questions with invalid group id $insertdata['gid']=$aGIDReplacements[$insertdata['gid']]; $oldqid=$insertdata['qid']; unset($insertdata['qid']); // save the old qid // now translate any links - $insertdata['title']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['title']); - $insertdata['question']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['question']); - $insertdata['help']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['help']); + $insertdata['title']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['title']); + $insertdata['question']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['question']); + $insertdata['help']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['help']); // Insert the new question if (isset($aQIDReplacements[$oldqid])) { @@ -919,9 +918,9 @@ function XMLImportGroup($sFullFilepath, $iNewSID) $insertdata['parent_qid']=$aQIDReplacements[(int)$insertdata['parent_qid']]; // remap the parent_qid // now translate any links - $insertdata['title']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['title']); - $insertdata['question']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['question']); - $insertdata['help']=translateLinks('survey', $oldsid, $iNewSID, !empty($insertdata['help']) ? $insertdata['help'] : ''); + $insertdata['title']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['title']); + $insertdata['question']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['question']); + $insertdata['help']=translateLinks('survey', $iOldSID, $iNewSID, !empty($insertdata['help']) ? $insertdata['help'] : ''); if (isset($aQIDReplacements[$oldsqid])){ $insertdata['qid']=$aQIDReplacements[$oldsqid]; } @@ -1427,7 +1426,7 @@ function CSVImportQuestion($sFullFilepath, $iNewSID, $newgid) // replace the sid $oldqid = $questionrowdata['qid']; - $oldsid = $questionrowdata['sid']; + $iOldSID = $questionrowdata['sid']; $oldgid = $questionrowdata['gid']; // Remove qid field if there is no newqid; and set it to newqid if it's set @@ -1471,8 +1470,8 @@ function CSVImportQuestion($sFullFilepath, $iNewSID, $newgid) $questionrowdata=array_map('convertCSVReturnToReturn', $questionrowdata); // translate internal links - $questionrowdata['question']=translateLinks('survey', $oldsid, $iNewSID, $questionrowdata['question']); - $questionrowdata['help']=translateLinks('survey', $oldsid, $iNewSID, $questionrowdata['help']); + $questionrowdata['question']=translateLinks('survey', $iOldSID, $iNewSID, $questionrowdata['question']); + $questionrowdata['help']=translateLinks('survey', $iOldSID, $iNewSID, $questionrowdata['help']); $newvalues=array_values($questionrowdata); if ($xssfilter) @@ -1587,7 +1586,7 @@ function CSVImportQuestion($sFullFilepath, $iNewSID, $newgid) } // translate internal links - $answerrowdata['answer']=translateLinks('survey', $oldsid, $iNewSID, $answerrowdata['answer']); + $answerrowdata['answer']=translateLinks('survey', $iOldSID, $iNewSID, $answerrowdata['answer']); // Everything set - now insert it $answerrowdata = array_map('convertCSVReturnToReturn', $answerrowdata); @@ -1752,16 +1751,16 @@ function XMLImportQuestion($sFullFilepath, $iNewSID, $newgid) { $insertdata[(string)$key]=(string)$value; } - $oldsid=$insertdata['sid']; + $iOldSID=$insertdata['sid']; $insertdata['sid']=$iNewSID; $insertdata['gid']=$newgid; $insertdata['question_order']=$newquestionorder; $oldqid=$insertdata['qid']; unset($insertdata['qid']); // save the old qid // now translate any links - $insertdata['title']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['title']); - $insertdata['question']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['question']); - $insertdata['help']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['help']); + $insertdata['title']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['title']); + $insertdata['question']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['question']); + $insertdata['help']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['help']); // Insert the new question if (isset($aQIDReplacements[$oldqid])) { @@ -1798,10 +1797,10 @@ function XMLImportQuestion($sFullFilepath, $iNewSID, $newgid) // now translate any links - $insertdata['question']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['question']); + $insertdata['question']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['question']); if (isset($insertdata['help'])) { - $insertdata['help']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['help']); + $insertdata['help']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['help']); } if (isset($aQIDReplacements[$oldsqid])){ $insertdata['qid']=$aQIDReplacements[$oldsqid]; @@ -2023,15 +2022,12 @@ function CSVImportLabelset($sFullFilepath, $options) unset($labelsetrowdata['lid']); - $newvalues=array_values($labelsetrowdata); if ($xssfilter) XSSFilterArray($newvalues); - $lsainsert = "insert INTO {{labelsets}} (".implode(',',array_keys($labelsetrowdata)).") VALUES (".implode(',',$newvalues).")"; //handle db prefix - $lsiresult= Yii::app()->db->createCommand($lsainsert)->query(); + // Insert the label set entry and get the new insert id for the labels inside this labelset + $newlid=Labelsets::model()->insertRecords($labelsetrowdata); $results['labelsets']++; - // Get the new insert id for the labels inside this labelset - $newlid=Yii::app()->db->getLastInsertID(); if ($labelsarray) { $count=0; @@ -2054,12 +2050,9 @@ function CSVImportLabelset($sFullFilepath, $options) $labelrowdata["assessment_value"]=(int)$labelrowdata["code"]; } - $newvalues=array_values($labelrowdata); if ($xssfilter) XSSFilterArray($newvalues); - $lainsert = "insert INTO {{labels}} (".implode(',',array_keys($labelrowdata)).") VALUES (".implode(',',$newvalues).")"; //handle db prefix - $liresult=Yii::app()->db->createCommand($lainsert)->query(); - + Label::model()->insertRecords($labelrowdata); $results['labels']++; } } @@ -2606,9 +2599,9 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= $sfieldorders =convertCSVRowToArray($surveyarray[0],',','"'); $sfieldcontents=convertCSVRowToArray($surveyarray[1],',','"'); $surveyrowdata=array_combine($sfieldorders,$sfieldcontents); - $oldsid=$surveyrowdata["sid"]; + $iOldSID=$surveyrowdata["sid"]; - if (!$oldsid) + if (!$iOldSID) { if ($importingfrom == "http") { @@ -2632,7 +2625,7 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= } else { - $iNewSID = GetNewSurveyID($oldsid); + $iNewSID = GetNewSurveyID($iOldSID); } @@ -2665,7 +2658,7 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= $surveyrowdata['bounce_email']=$surveyrowdata['adminemail']; if (empty($surveyrowdata['datecreated'])) {$surveyrowdata['datecreated'] = new CDbExpression('NOW()'); } - $iNewSID = Survey::insertNewSurvey($surveyrowdata, $xssfilter) or safeDie ("
".$clang->gT("Import of this survey file failed")."
{$surveyarray[0]}

\n" ); + $iNewSID = Survey::model()->insertNewSurvey($surveyrowdata) or safeDie ("
".$clang->gT("Import of this survey file failed")."
{$surveyarray[0]}

\n" ); // Now import the survey language settings $fieldorders=convertCSVRowToArray($surveylsarray[0],',','"'); @@ -2680,19 +2673,19 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= // translate internal links if ($bTranslateLinks) { - $surveylsrowdata['surveyls_title']=translateLinks('survey', $oldsid, $iNewSID, $surveylsrowdata['surveyls_title']); - $surveylsrowdata['surveyls_description']=translateLinks('survey', $oldsid, $iNewSID, $surveylsrowdata['surveyls_description']); - $surveylsrowdata['surveyls_welcometext']=translateLinks('survey', $oldsid, $iNewSID, $surveylsrowdata['surveyls_welcometext']); - $surveylsrowdata['surveyls_urldescription']=translateLinks('survey', $oldsid, $iNewSID, $surveylsrowdata['surveyls_urldescription']); - $surveylsrowdata['surveyls_email_invite']=translateLinks('survey', $oldsid, $iNewSID, $surveylsrowdata['surveyls_email_invite']); - $surveylsrowdata['surveyls_email_remind']=translateLinks('survey', $oldsid, $iNewSID, $surveylsrowdata['surveyls_email_remind']); - $surveylsrowdata['surveyls_email_register']=translateLinks('survey', $oldsid, $iNewSID, $surveylsrowdata['surveyls_email_register']); - $surveylsrowdata['surveyls_email_confirm']=translateLinks('survey', $oldsid, $iNewSID, $surveylsrowdata['surveyls_email_confirm']); + $surveylsrowdata['surveyls_title']=translateLinks('survey', $iOldSID, $iNewSID, $surveylsrowdata['surveyls_title']); + $surveylsrowdata['surveyls_description']=translateLinks('survey', $iOldSID, $iNewSID, $surveylsrowdata['surveyls_description']); + $surveylsrowdata['surveyls_welcometext']=translateLinks('survey', $iOldSID, $iNewSID, $surveylsrowdata['surveyls_welcometext']); + $surveylsrowdata['surveyls_urldescription']=translateLinks('survey', $iOldSID, $iNewSID, $surveylsrowdata['surveyls_urldescription']); + $surveylsrowdata['surveyls_email_invite']=translateLinks('survey', $iOldSID, $iNewSID, $surveylsrowdata['surveyls_email_invite']); + $surveylsrowdata['surveyls_email_remind']=translateLinks('survey', $iOldSID, $iNewSID, $surveylsrowdata['surveyls_email_remind']); + $surveylsrowdata['surveyls_email_register']=translateLinks('survey', $iOldSID, $iNewSID, $surveylsrowdata['surveyls_email_register']); + $surveylsrowdata['surveyls_email_confirm']=translateLinks('survey', $iOldSID, $iNewSID, $surveylsrowdata['surveyls_email_confirm']); } unset($surveylsrowdata['lastpage']); $surveylsrowdata['surveyls_survey_id']=$iNewSID; - $lsiresult = Surveys_languagesettings::model()->insertNewSurvey($surveylsrowdata, $xssfilter) or safeDie("
".$clang->gT("Import of this survey file failed")."
"); + $lsiresult = Surveys_languagesettings::model()->insertNewSurvey($surveylsrowdata) or safeDie("
".$clang->gT("Import of this survey file failed")."
"); } @@ -2831,7 +2824,7 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= $grouprowdata=array_combine($gafieldorders,$gacfieldcontents); //Now an additional integrity check if there are any groups not belonging into this survey - if ($grouprowdata['sid'] != $oldsid) + if ($grouprowdata['sid'] != $iOldSID) { $results['fatalerror'] = $clang->gT("A group in the CSV/SQL file is not part of the same survey. The import of the survey was stopped.")."
\n"; return $results; @@ -2852,8 +2845,8 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= // translate internal links if ($bTranslateLinks) { - $grouprowdata['group_name']=translateLinks('survey', $oldsid, $iNewSID, $grouprowdata['group_name']); - $grouprowdata['description']=translateLinks('survey', $oldsid, $iNewSID, $grouprowdata['description']); + $grouprowdata['group_name']=translateLinks('survey', $iOldSID, $iNewSID, $grouprowdata['group_name']); + $grouprowdata['description']=translateLinks('survey', $iOldSID, $iNewSID, $grouprowdata['description']); } if (isset($grouprowdata['gid'])) switchMSSQLIdentityInsert('groups',true); @@ -2929,8 +2922,8 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= // translate internal links if ($bTranslateLinks) { - $questionrowdata['question']=translateLinks('survey', $oldsid, $iNewSID, $questionrowdata['question']); - $questionrowdata['help']=translateLinks('survey', $oldsid, $iNewSID, $questionrowdata['help']); + $questionrowdata['question']=translateLinks('survey', $iOldSID, $iNewSID, $questionrowdata['question']); + $questionrowdata['help']=translateLinks('survey', $iOldSID, $iNewSID, $questionrowdata['help']); } @@ -3060,7 +3053,7 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= // translate internal links if ($bTranslateLinks) { - $answerrowdata['answer']=translateLinks('survey', $oldsid, $iNewSID, $answerrowdata['answer']); + $answerrowdata['answer']=translateLinks('survey', $iOldSID, $iNewSID, $answerrowdata['answer']); } // Everything set - now insert it $answerrowdata = array_map('convertCSVReturnToReturn', $answerrowdata); @@ -3168,7 +3161,7 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= $asrowdata["sid"]=$iNewSID; unset($asrowdata["id"]); - $result=Assesments::model()->insertRecords($asrowdata) or safeDie("Couldn't insert assessment
"); + $result=Assessments::model()->insertRecords($asrowdata) or safeDie("Couldn't insert assessment
"); unset($newgid); } @@ -3183,9 +3176,9 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= $asrowdata=array_combine($fieldorders,$fieldcontents); - $oldsid=$asrowdata["sid"]; + $iOldSID=$asrowdata["sid"]; foreach ($substitutions as $subs) { - if ($oldsid==$subs[0]) {$iNewSID=$subs[3];} + if ($iOldSID==$subs[0]) {$iNewSID=$subs[3];} } $asrowdata["sid"]=$iNewSID; @@ -3208,14 +3201,14 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= $asrowdata=array_combine($fieldorders,$fieldcontents); - $oldsid=$asrowdata["sid"]; + $iOldSID=$asrowdata["sid"]; $newqid=""; $newquotaid=""; $oldqid=$asrowdata['qid']; $oldquotaid=$asrowdata['quota_id']; foreach ($substitutions as $subs) { - if ($oldsid==$subs[0]) {$iNewSID=$subs[3];} + if ($iOldSID==$subs[0]) {$iNewSID=$subs[3];} if ($oldqid==$subs[2]) {$newqid=$subs[5];} } @@ -3299,7 +3292,7 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= $conditionrowdata["qid"]=$aQIDReplacements[$conditionrowdata["qid"]]; $conditionrowdata["cqid"]=$aQIDReplacements[$conditionrowdata["cqid"]]; $oldcfieldname=$conditionrowdata["cfieldname"]; - $conditionrowdata["cfieldname"]=str_replace($oldsid.'X'.$oldgid.'X'.$oldcqid,$iNewSID.'X'.$aGIDReplacements[$oldgid].'X'.$conditionrowdata["cqid"],$conditionrowdata["cfieldname"]); + $conditionrowdata["cfieldname"]=str_replace($iOldSID.'X'.$oldgid.'X'.$oldcqid,$iNewSID.'X'.$aGIDReplacements[$oldgid].'X'.$conditionrowdata["cqid"],$conditionrowdata["cfieldname"]); $result=Conditions::model()->insertRecords($conditionrowdata) or safeDie("Couldn't insert condition
"); @@ -3311,11 +3304,106 @@ function CSVImportSurvey($sFullFilepath,$iDesiredSurveyId=NULL,$bTranslateLinks= $importresults['importversion']=$importversion; $importresults['newsid']=$iNewSID; - $importresults['oldsid']=$oldsid; + $importresults['oldsid']=$iOldSID; return $importresults; } +function importSurveyFile($sFullFilepath, $bTranslateLinksFields, $sNewSurveyName=NULL, $DestSurveyID=NULL) +{ + $aPathInfo = pathinfo($sFullFilepath); + if (isset($aPathInfo['extension'])) + { + $sExtension = $aPathInfo['extension']; + } + else + { + $sExtension = ""; + } + if (isset($sExtension) && strtolower($sExtension) == 'csv') + { + return CSVImportSurvey($sFullFilepath, $DestSurveyID, $bTranslateLinksFields); + } + elseif (isset($sExtension) && strtolower($sExtension) == 'lss') + { + return XMLImportSurvey($sFullFilepath, null, $sNewSurveyName, $DestSurveyID, $bTranslateLinksFields); + } + elseif (isset($sExtension) && strtolower($sExtension) == 'xls') + { + return ExcelImportSurvey($sFullFilepath); + } + elseif (isset($sExtension) && strtolower($sExtension) == 'zip') // Import a survey archive + { + Yii::import("application.libraries.admin.pclzip.pclzip", true); + $pclzip = new PclZip(array('p_zipname' => $sFullFilepath)); + $aFiles = $pclzip->listContent(); + + if ($pclzip->extract(PCLZIP_OPT_PATH, Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR, PCLZIP_OPT_BY_EREG, '/(lss|lsr|lsi|lst)$/') == 0) + { + unset($pclzip); + } + // Step 1 - import the LSS file and activate the survey + foreach ($aFiles as $aFile) + { + if (pathinfo($aFile['filename'], PATHINFO_EXTENSION) == 'lss') + { + //Import the LSS file + $aImportResults = XMLImportSurvey(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename'], null, null, null, true); + // Activate the survey + Yii::app()->loadHelper("admin/activate"); + $activateoutput = activateSurvey($aImportResults['newsid']); + unlink(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename']); + break; + } + } + // Step 2 - import the responses file + foreach ($aFiles as $aFile) + { + if (pathinfo($aFile['filename'], PATHINFO_EXTENSION) == 'lsr') + { + //Import the LSS file + $aResponseImportResults = XMLImportResponses(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename'], $aImportResults['newsid'], $aImportResults['FieldReMap']); + $aImportResults = array_merge($aResponseImportResults, $aImportResults); + unlink(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename']); + break; + } + } + // Step 3 - import the tokens file - if exists + foreach ($aFiles as $aFile) + { + if (pathinfo($aFile['filename'], PATHINFO_EXTENSION) == 'lst') + { + Yii::app()->loadHelper("admin/token"); + if (createTokenTable($aImportResults['newsid'])) + $aTokenCreateResults = array('tokentablecreated' => true); + $aImportResults = array_merge($aTokenCreateResults, $aImportResults); + $aTokenImportResults = XMLImportTokens(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename'], $aImportResults['newsid']); + $aImportResults = array_merge($aTokenImportResults, $aImportResults); + unlink(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename']); + break; + } + } + // Step 4 - import the timings file - if exists + foreach ($aFiles as $aFile) + { + if (pathinfo($aFile['filename'], PATHINFO_EXTENSION) == 'lsi' && tableExists("survey_{$aImportResults['newsid']}_timings")) + { + $aTimingsImportResults = XMLImportTimings(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename'], $aImportResults['newsid'], $aImportResults['FieldReMap']); + $aImportResults = array_merge($aTimingsImportResults, $aImportResults); + unlink(Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $aFile['filename']); + break; + } + } + return $aImportResults; + } + else + { + return null; + } + +} + + /** * This function imports a LimeSurvey .lss survey XML file @@ -3383,14 +3471,10 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe $insertdata[(string)$key]=(string)$value; } - $oldsid=$insertdata['sid']; + $iOldSID=$results['oldsid']=$insertdata['sid']; if($iDesiredSurveyId!=NULL) { - $iNewSID=GetNewSurveyID($iDesiredSurveyId); - } - else - { - $iNewSID=GetNewSurveyID($oldsid); + $insertdata['wishSID']=GetNewSurveyID($iDesiredSurveyId); } if ($iDBVersion<=143) @@ -3399,25 +3483,15 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe unset($insertdata['private']); unset($insertdata['notification']); } - $insertdata['startdate']=NULL; - //Now insert the new SID and change some values - $insertdata['sid'] = $iNewSID; + + unset($insertdata['expires']); + unset($insertdata['startdate']); + //Make sure it is not set active $insertdata['active']='N'; //Set current user to be the owner $insertdata['owner_id']=Yii::app()->session['loginID']; - //Change creation date to import date - $insertdata['datecreated'] = new CDbExpression('NOW()'); - - if (isset($insertdata['expires']) && $insertdata['expires'] == '') - { - $insertdata['expires'] = NULL; - } - if (isset($insertdata['startdate']) && $insertdata['startdate'] == '') - { - $insertdata['startdate'] = NULL; - } if (isset($insertdata['bouncetime']) && $insertdata['bouncetime'] == '') { $insertdata['bouncetime'] = NULL; @@ -3428,18 +3502,11 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe $insertdata['showxquestions']=$insertdata['showXquestions']; unset($insertdata['showXquestions']); } - - switchMSSQLIdentityInsert('surveys',true); - if ($xssfilter) - XSSFilterArray($insertdata); - $iNewSID = Survey::model()->insertNewSurvey($insertdata) or safeDie($clang->gT("Error").": Failed to insert data
"); + $iNewSID = $results['newsid'] = Survey::model()->insertNewSurvey($insertdata) or safeDie($clang->gT("Error").": Failed to insert data
"); $results['surveys']++; - switchMSSQLIdentityInsert('surveys',false); } - $results['newsid']=$iNewSID; - $results['oldsid']=$oldsid; // Import survey languagesettings table =================================================================================== @@ -3460,17 +3527,17 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe { if ($sNewSurveyName == NULL) { - $insertdata['surveyls_title']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['surveyls_title']); + $insertdata['surveyls_title']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_title']); } else { - $insertdata['surveyls_title']=translateLinks('survey', $oldsid, $iNewSID, $sNewSurveyName); - } - $insertdata['surveyls_description']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['surveyls_description']); - $insertdata['surveyls_welcometext']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['surveyls_welcometext']); - $insertdata['surveyls_urldescription']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['surveyls_urldescription']); - $insertdata['surveyls_email_invite']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['surveyls_email_invite']); - $insertdata['surveyls_email_remind']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['surveyls_email_remind']); - $insertdata['surveyls_email_register']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['surveyls_email_register']); - $insertdata['surveyls_email_confirm']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['surveyls_email_confirm']); + $insertdata['surveyls_title']=translateLinks('survey', $iOldSID, $iNewSID, $sNewSurveyName); + } + $insertdata['surveyls_description']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_description']); + $insertdata['surveyls_welcometext']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_welcometext']); + $insertdata['surveyls_urldescription']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_urldescription']); + $insertdata['surveyls_email_invite']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_email_invite']); + $insertdata['surveyls_email_remind']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_email_remind']); + $insertdata['surveyls_email_register']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_email_register']); + $insertdata['surveyls_email_confirm']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_email_confirm']); } @@ -3491,15 +3558,15 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe $insertdata[(string)$key]=(string)$value; } if (!in_array($insertdata['language'],$aLanguagesSupported)) continue; - $oldsid=$insertdata['sid']; + $iOldSID=$insertdata['sid']; $insertdata['sid']=$iNewSID; $oldgid=$insertdata['gid']; unset($insertdata['gid']); // save the old qid // now translate any links if ($bTranslateInsertansTags) { - $insertdata['group_name']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['group_name']); - $insertdata['description']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['description']); + $insertdata['group_name']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['group_name']); + $insertdata['description']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['description']); } // Insert the new group if (isset($aGIDReplacements[$oldgid])) @@ -3536,7 +3603,7 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe $insertdata[(string)$key]=(string)$value; } if (!in_array($insertdata['language'],$aLanguagesSupported)) continue; - $oldsid=$insertdata['sid']; + $iOldSID=$insertdata['sid']; $insertdata['sid']=$iNewSID; $insertdata['gid']=$aGIDReplacements[$insertdata['gid']]; $oldqid=$insertdata['qid']; unset($insertdata['qid']); // save the old qid @@ -3544,8 +3611,8 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe // now translate any links if ($bTranslateInsertansTags) { - $insertdata['question']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['question']); - $insertdata['help']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['help']); + $insertdata['question']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['question']); + $insertdata['help']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['help']); } // Insert the new question if (isset($aQIDReplacements[$oldqid])) @@ -3589,8 +3656,8 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe // now translate any links if ($bTranslateInsertansTags) { - $insertdata['question']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['question']); - if (isset($insertdata['help'])) $insertdata['help']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['help']); + $insertdata['question']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['question']); + if (isset($insertdata['help'])) $insertdata['help']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['help']); } if (isset($aQIDReplacements[$oldsqid])){ $insertdata['qid']=$aQIDReplacements[$oldsqid]; @@ -3629,7 +3696,7 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe // now translate any links if ($bTranslateInsertansTags) { - $insertdata['answer']=translateLinks('survey', $oldsid, $iNewSID, $insertdata['answer']); + $insertdata['answer']=translateLinks('survey', $iOldSID, $iNewSID, $insertdata['answer']); } if ($xssfilter) XSSFilterArray($insertdata); @@ -3693,7 +3760,7 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe $results['defaultvalues']++; } } - $aOldNewFieldmap=reverseTranslateFieldNames($oldsid,$iNewSID,$aGIDReplacements,$aQIDReplacements); + $aOldNewFieldmap=reverseTranslateFieldNames($iOldSID,$iNewSID,$aGIDReplacements,$aQIDReplacements); // Import conditions --------------------------------------------------------- if(isset($xml->conditions)) @@ -3886,10 +3953,10 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe // Set survey rights Survey_permissions::model()->giveAllSurveyPermissions(Yii::app()->session['loginID'],$iNewSID); - $aOldNewFieldmap=reverseTranslateFieldNames($oldsid,$iNewSID,$aGIDReplacements,$aQIDReplacements); + $aOldNewFieldmap=reverseTranslateFieldNames($iOldSID,$iNewSID,$aGIDReplacements,$aQIDReplacements); $results['FieldReMap']=$aOldNewFieldmap; LimeExpressionManager::SetSurveyId($iNewSID); - translateInsertansTags($iNewSID,$oldsid,$aOldNewFieldmap); + translateInsertansTags($iNewSID,$iOldSID,$aOldNewFieldmap); LimeExpressionManager::RevertUpgradeConditionsToRelevance($iNewSID); LimeExpressionManager::UpgradeConditionsToRelevance($iNewSID); return $results; @@ -3899,38 +3966,36 @@ function XMLImportSurvey($sFullFilepath,$sXMLdata=NULL,$sNewSurveyName=NULL,$iDe * This function returns a new random sid if the existing one is taken, * otherwise it returns the old one. * -* @param mixed $oldsid +* @param mixed $iOldSID */ -function GetNewSurveyID($oldsid) +function GetNewSurveyID($iOldSID) { Yii::app()->loadHelper('database'); - $query = "SELECT sid FROM {{surveys}} WHERE sid=$oldsid"; + $query = "SELECT sid FROM {{surveys}} WHERE sid=$iOldSID"; - $res = Yii::app()->db->createCommand($query)->query(); - $isresult = $res->read(); + $aRow = Yii::app()->db->createCommand($query)->queryRow(); if(Yii::app()->getConfig('filterxsshtml') && Yii::app()->session['USER_RIGHT_SUPERADMIN'] != 1) $xssfilter = true; else $xssfilter = false; - //if (!is_null($isresult)) - if($res->count() > 0) + if($aRow!==false) { // Get new random ids until one is found that is not used do { $iNewSID = randomChars(5,'123456789'); $query = "SELECT sid FROM {{surveys}} WHERE sid=$iNewSID"; - $res = Yii::app()->db->createCommand($query)->query(); + $aRow = Yii::app()->db->createCommand($query)->queryRow(); } - while ($res->count()); + while ($aRow!==false); return $iNewSID; } else { - return $oldsid; + return $iOldSID; } } @@ -4202,14 +4267,14 @@ function ExcelImportSurvey($sFullFilepath) } } - $oldsid = 1; + $iOldSID = 1; if (isset($surveyinfo['sid'])) { - $oldsid = (int) $surveyinfo['sid']; + $iOldSID = (int) $surveyinfo['sid']; } // Create the survey entry - $iNewSID=GetNewSurveyID($oldsid); + $iNewSID=GetNewSurveyID($iOldSID); $surveyinfo['startdate']=NULL; $surveyinfo['sid']=$iNewSID; $surveyinfo['active']='N'; @@ -4258,10 +4323,10 @@ function ExcelImportSurvey($sFullFilepath) $baselang = $surveyinfo['language']; // the base language } - $rownumber = 1; + $rownumber = 1; foreach ($adata as $row) { - $rownumber += 1; + $rownumber += 1; $row = str_replace(chr(0xA0),' ',$row); switch($row['class']) { @@ -4332,11 +4397,11 @@ function ExcelImportSurvey($sFullFilepath) $result = Questions::model()->insertRecords($insertdata); //or safeDie ($clang->gT("Error").": Failed to insert question
"); if(!$result){ - $results['error'][] = $clang->gT("Error")." : ".$clang->gT("Could not insert question").". ".$clang->gT("Excel row number ").$rownumber." (".$qname.")"; - break; + $results['error'][] = $clang->gT("Error")." : ".$clang->gT("Could not insert question").". ".$clang->gT("Excel row number ").$rownumber." (".$qname.")"; + break; } - $newqid = $result; + $newqid = $result; if (!isset($qinfo[$qname])) { $results['questions']++; @@ -4481,7 +4546,7 @@ function ExcelImportSurvey($sFullFilepath) $result = Answers::model()->insertRecords($insertdata); // or safeDie("Error: Failed to insert answer
"); if(!$result){ - $results['error'][] = $clang->gT("Error")." : ".$clang->gT("Could not insert answer").". ".$clang->gT("Excel row number ").$rownumber; + $results['error'][] = $clang->gT("Error")." : ".$clang->gT("Could not insert answer").". ".$clang->gT("Excel row number ").$rownumber; } $results['answers']++; break; @@ -4489,12 +4554,12 @@ function ExcelImportSurvey($sFullFilepath) } - // Delete the survey if error found - if(is_array($results['error'])) - { - $result = Survey::model()->deleteSurvey($iNewSID); - } - + // Delete the survey if error found + if(is_array($results['error'])) + { + $result = Survey::model()->deleteSurvey($iNewSID); + } + return $results; } diff --git a/application/helpers/admin/label_helper.php b/application/helpers/admin/label_helper.php index d294c2fc50e..3d47ea1a314 100644 --- a/application/helpers/admin/label_helper.php +++ b/application/helpers/admin/label_helper.php @@ -139,7 +139,7 @@ function modlabelsetanswers($lid) } //unescape single quotes - $labeldata = CHttpRequest::getPost('dataToSend'); + $labeldata = Yii::app()->getRequest()->getPost('dataToSend'); $labeldata = str_replace("\'","'",$labeldata); diff --git a/application/helpers/admin/statistics_helper.php b/application/helpers/admin/statistics_helper.php index 2f861b956b8..a2a74c99b91 100644 --- a/application/helpers/admin/statistics_helper.php +++ b/application/helpers/admin/statistics_helper.php @@ -17,18 +17,21 @@ /** * * Generate a chart for a question -* @param mixed $qid ID of the question -* @param mixed $sid ID of the survey -* @param mixed $type Type of the chart to be created -* @param mixed $cache -* @param mixed $lbl -* @param mixed $gdata -* @param mixed $grawdata -* @param mixed $cache +* @param int $iQuestionID ID of the question +* @param int $iSurveyID ID of the survey +* @param mixed $type Type of the chart to be created - null produces bar chart, any other value produces pie chart +* @param array $lbl An array containing the labels for the chart items +* @param mixed $gdata An array containing the percentages for the chart items +* @param mixed $grawdata An array containing the raw count for the chart items +* @param mixed $cache An object containing [Hashkey] and [CacheFolder] * @return Name */ -function createChart($qid, $sid, $type, $lbl, $gdata, $grawdata, $cache) +function createChart($iQuestionID, $iSurveyID, $type=null, $lbl, $gdata, $grawdata, $cache) { + /* This is a lazy solution to bug #6389. A better solution would be to find out how + the "T" gets passed to this function from the statistics.js file in the first place! */ + if(substr($iSurveyID,0,1)=="T") {$iSurveyID=substr($iSurveyID,1);} + $rootdir = Yii::app()->getConfig("rootdir"); $homedir = Yii::app()->getConfig("homedir"); $homeurl = Yii::app()->getConfig("homeurl"); @@ -36,8 +39,11 @@ function createChart($qid, $sid, $type, $lbl, $gdata, $grawdata, $cache) $scriptname = Yii::app()->getConfig("scriptname"); $chartfontfile = Yii::app()->getConfig("chartfontfile"); $chartfontsize = Yii::app()->getConfig("chartfontsize"); - $language = Survey::model()->findByPk($sid)->language; + $language = Survey::model()->findByPk($iSurveyID)->language; + $statlang = new Limesurvey_lang($language); + $cachefilename = ""; + /* Set the fonts for the chart */ if ($chartfontfile=='auto') { $chartfontfile='vera.ttf'; @@ -59,13 +65,10 @@ function createChart($qid, $sid, $type, $lbl, $gdata, $grawdata, $cache) } } - $cachefilename = ""; - - if (array_sum($gdata ) > 0) + if (array_sum($gdata ) > 0) //Make sure that the percentages add up to more than 0 { $graph = ""; $p1 = ""; - $i = 0; foreach ($gdata as $data) { @@ -75,8 +78,9 @@ function createChart($qid, $sid, $type, $lbl, $gdata, $grawdata, $cache) } } + /* Totatllines is the number of entries to show in the key and we need to reduce the font + and increase the size of the chart if there are lots of them (ie more than 15) */ $totallines=$i; - if ($totallines>15) { $gheight=320+(6.7*($totallines-15)); @@ -114,20 +118,19 @@ function createChart($qid, $sid, $type, $lbl, $gdata, $grawdata, $cache) $counter++; } - if ($cache->IsInCache("graph".$sid,$DataSet->GetData())) + if ($cache->IsInCache("graph".$language.$iSurveyID,$DataSet->GetData())) { - $cachefilename=basename($cache->GetFileFromCache("graph".$sid,$DataSet->GetData())); + $cachefilename=basename($cache->GetFileFromCache("graph".$language.$iSurveyID,$DataSet->GetData())); } else { $graph = new pChart(1,1); - $graph->setFontProperties($rootdir.DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.$chartfontfile, $chartfontsize); $legendsize=$graph->getLegendBoxSize($DataSet->GetDataDescription()); if ($legendsize[1]<320) $gheight=420; else $gheight=$legendsize[1]+100; $graph = new pChart(690+$legendsize[0],$gheight); - $graph->loadColorPalette($rootdir.DIRECTORY_SEPARATOR.'styles'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.$admintheme.DIRECTORY_SEPARATOR.'limesurvey.pal'); + $graph->loadColorPalette($homedir.DIRECTORY_SEPARATOR.'styles'.DIRECTORY_SEPARATOR.$admintheme.DIRECTORY_SEPARATOR.'limesurvey.pal'); $graph->setFontProperties($rootdir.DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.$chartfontfile,$chartfontsize); $graph->setGraphArea(50,30,500,$gheight-60); $graph->drawFilledRoundedRectangle(7,7,523+$legendsize[0],$gheight-7,5,254,255,254); @@ -146,8 +149,8 @@ function createChart($qid, $sid, $type, $lbl, $gdata, $grawdata, $cache) $graph->setFontProperties($rootdir.DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.$chartfontfile, $chartfontsize); $graph->drawLegend(510,30,$DataSet->GetDataDescription(),255,255,255); - $cache->WriteToCache("graph".$sid,$DataSet->GetData(),$graph); - $cachefilename=basename($cache->GetFileFromCache("graph".$sid,$DataSet->GetData())); + $cache->WriteToCache("graph".$language.$iSurveyID,$DataSet->GetData(),$graph); + $cachefilename=basename($cache->GetFileFromCache("graph".$language.$iSurveyID,$DataSet->GetData())); unset($graph); } } //end if (bar chart) @@ -156,11 +159,11 @@ function createChart($qid, $sid, $type, $lbl, $gdata, $grawdata, $cache) else { // this block is to remove the items with value == 0 - // and an unelegant way to remove comments from List with Comments questions + // and an inelegant way to remove comments from List with Comments questions $i = 0; while (isset ($gdata[$i])) { - if ($gdata[$i] == 0 || ($qtype == "O" && substr($lbl[$i],0,strlen($statlang->gT("Comments")))==$statlang->gT("Comments"))) + if ($gdata[$i] == 0 || ($type == "O" && substr($lbl[$i],0,strlen($statlang->gT("Comments")))==$statlang->gT("Comments"))) { array_splice ($gdata, $i, 1); array_splice ($lbl, $i, 1); @@ -203,9 +206,9 @@ function createChart($qid, $sid, $type, $lbl, $gdata, $grawdata, $cache) $DataSet->AddAllSeries(); $DataSet->SetAbsciseLabelSerie("Serie2"); - if ($cache->IsInCache("graph".$sid, $DataSet->GetData())) + if ($cache->IsInCache("graph".$language.$iSurveyID, $DataSet->GetData())) { - $cachefilename=basename($cache->GetFileFromCache("graph".$sid,$DataSet->GetData())); + $cachefilename=basename($cache->GetFileFromCache("graph".$language.$iSurveyID,$DataSet->GetData())); } else { @@ -221,8 +224,8 @@ function createChart($qid, $sid, $type, $lbl, $gdata, $grawdata, $cache) $graph->drawPieGraph($DataSet->GetData(),$DataSet->GetDataDescription(),225,round($gheight/2),170,PIE_PERCENTAGE,TRUE,50,20,5); $graph->setFontProperties($rootdir."/fonts/".$chartfontfile,$chartfontsize); $graph->drawPieLegend(430,12,$DataSet->GetData(),$DataSet->GetDataDescription(),250,250,250); - $cache->WriteToCache("graph".$sid,$DataSet->GetData(),$graph); - $cachefilename=basename($cache->GetFileFromCache("graph".$sid,$DataSet->GetData())); + $cache->WriteToCache("graph".$language.$iSurveyID,$DataSet->GetData(),$graph); + $cachefilename=basename($cache->GetFileFromCache("graph".$language.$iSurveyID,$DataSet->GetData())); unset($graph); } } //end else -> pie charts @@ -256,269 +259,59 @@ function getQuestionMapData($sField, $qsid) return $d; } - -/** -* Generates statistics +/** Builds the list of addon SQL select statements +* that builds the query result set +* +* @param $allfields An array containing the names of the fields/answers we want to display in the statistics summary +* @param $fieldmap The fieldmap for the survey +* @param $language The language to use +* +* @return array $selects array of individual select statements that can be added/appended to +* the 'where' portion of a SQL statement to restrict the result set +* ie: array("`FIELDNAME`='Y'", "`FIELDNAME2`='Hello'"); * -* @param int $surveyid The survey id -* @param mixed $allfields -* @param mixed $q2show -* @param mixed $usegraph -* @param string $outputType Optional - Can be xls, html or pdf - Defaults to pdf -* @param string $pdfOutput Sets the target for the PDF output: DD=File download , F=Save file to local disk -* @param string $statlangcode Lamguage for statistics -* @param mixed $browse Show browse buttons -* @return buffer */ -function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $outputType='pdf', $pdfOutput='I',$statlangcode=null, $browse = true) -{ - //$allfields =""; - - global $rooturl, $rootdir, $homedir, $homeurl, $scriptname, - $chartfontfile, $chartfontsize, $admintheme, $pdfdefaultfont, $pdffontsize; - - //load surveytranslator helper - Yii::import('application.helpers.surveytranslator_helper', true); - - $imagedir = Yii::app()->getConfig("imagedir"); - $tempdir = Yii::app()->getConfig("tempdir"); - $tempurl = Yii::app()->getConfig("tempurl"); - $clang = Yii::app()->lang; - - - $astatdata = array(); - - // Used for getting coordinates for google maps - $agmapdata = array(); - - //pick the best font file if font setting is 'auto' - if (is_null($statlangcode)) - { - $statlang = getBaseLanguageFromSurveyID($surveyid); - } - else - { - $statlang = new Limesurvey_lang($statlangcode); - } - - $fieldmap=createFieldMap($surveyid, "full", false, false, $statlang->getlangcode()); - - /* - * this variable is used in the function shortencode() which cuts off a question/answer title - * after $maxchars and shows the rest as tooltip (in html mode) - */ - $maxchars = 13; - //we collect all the html-output within this variable - $statisticsoutput =''; - /** - * $outputType: html || pdf || - */ - /** - * get/set Survey Details - */ - - //no survey ID? -> come and get one - if (!isset($surveyid)) {$surveyid=returnGlobal('sid');} - - //Get an array of codes of all available languages in this survey - $surveylanguagecodes = Survey::model()->findByPk($surveyid)->additionalLanguages; - $surveylanguagecodes[] = Survey::model()->findByPk($surveyid)->language; - - // Set language for questions and answers to base language of this survey - $language=$statlangcode; - - if ($usegraph==1) - { - //for creating graphs we need some more scripts which are included here - require_once(APPPATH.'/third_party/pchart/pchart/pChart.class'); - require_once(APPPATH.'/third_party/pchart/pchart/pData.class'); - require_once(APPPATH.'/third_party/pchart/pchart/pCache.class'); - $MyCache = new pCache($tempdir.'/'); - } - - if($q2show=='all' ) - { - $summarySql=" SELECT gid, parent_qid, qid, type " - ." FROM {{questions}} WHERE parent_qid=0" - ." AND sid=$surveyid "; - - $summaryRs = Yii::app()->db->createCommand($summarySql)->query()->readAll(); - - foreach($summaryRs as $field) - { - $myField = $surveyid."X".$field['gid']."X".$field['qid']; - - // Multiple choice get special treatment - if ($field['type'] == "M") {$myField = "M$myField";} - if ($field['type'] == "P") {$myField = "P$myField";} - //numerical input will get special treatment (arihtmetic mean, standard derivation, ...) - if ($field['type'] == "N") {$myField = "N$myField";} - - if ($field['type'] == "|") {$myField = "|$myField";} - - if ($field['type'] == "Q") {$myField = "Q$myField";} - // textfields get special treatment - if ($field['type'] == "S" || $field['type'] == "T" || $field['type'] == "U"){$myField = "T$myField";} - //statistics for Date questions are not implemented yet. - if ($field['type'] == "D") {$myField = "D$myField";} - if ($field['type'] == "F" || $field['type'] == "H") - { - //Get answers. We always use the answer code because the label might be too long elsewise - $query = "SELECT code, answer FROM {{answers}} WHERE qid='".$field['qid']."' AND scale_id=0 AND language='{$language}' ORDER BY sortorder, answer"; - $result = Yii::app()->db->createCommand($query)->query(); - $counter2=0; - - //check all the answers - foreach ($result->readAll() as $row) - { - $row=array_values($row); - $myField = "$myField{$row[0]}"; - } - //$myField = "{$surveyid}X{$flt[1]}X{$flt[0]}{$row[0]}[]"; - - - } - if($q2show=='all') - $summary[]=$myField; - - //$allfields[]=$myField; - } - } - else - { - // This gets all the 'to be shown questions' from the POST and puts these into an array - if (!is_array($q2show)) - $summary=returnGlobal('summary'); - else - $summary = $q2show; - - //print_r($_POST); - //if $summary isn't an array we create one - if (isset($summary) && !is_array($summary)) - { - $summary = explode("+", $summary); - } - } - - /* Some variable depend on output type, actually : only line feed */ - switch($outputType) - { - case 'xls': - $linefeed = "\n"; - break; - case 'pdf': - $linefeed = "\n"; - break; - case 'html': - $linefeed = "
\n"; - break; - default: - - break; - } - - /** - * pdf Config - */ - if($outputType=='pdf') - { - //require_once('classes/tcpdf/config/lang/eng.php'); - global $l; - $l['w_page'] = $statlang->gT("Page",'unescaped'); - //require_once('classes/tcpdf/mypdf.php'); - Yii::import('application.libraries.admin.pdf', true); - // create new PDF document - $pdf = new Pdf(); - $pdf->SetFont($pdfdefaultfont,'',$pdffontsize); - - $surveyInfo = getSurveyInfo($surveyid,$language); - - // set document information - $pdf->SetCreator(PDF_CREATOR); - $pdf->SetAuthor('LimeSurvey'); - $pdf->SetTitle('Statistic survey '.$surveyid); - $pdf->SetSubject($surveyInfo['surveyls_title']); - $pdf->SetKeywords('LimeSurvey, Statistics, Survey '.$surveyid.''); - $pdf->SetDisplayMode('fullpage', 'two'); - - // set header and footer fonts - $pdf->setHeaderFont(Array($pdfdefaultfont, '', PDF_FONT_SIZE_MAIN)); - $pdf->setFooterFont(Array($pdfdefaultfont, '', PDF_FONT_SIZE_DATA)); - - // set default header data - $pdf->SetHeaderData("statistics.png", 10, $statlang->gT("Quick statistics",'unescaped') , $statlang->gT("Survey")." ".$surveyid." '".flattenText($surveyInfo['surveyls_title'],false,true,'UTF-8')."'"); - - - // set default monospaced font - $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); - - //set margins - $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT); - $pdf->SetHeaderMargin(PDF_MARGIN_HEADER); - $pdf->SetFooterMargin(PDF_MARGIN_FOOTER); - - //set auto page breaks - $pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM); +function buildSelects($allfields, $surveyid, $language) { - //set image scale factor - $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); + //Create required variables + $selects=array(); + $aQuestionMap=array(); - //set some language-dependent strings - $pdf->setLanguageArray($l); - } - if($outputType=='xls') + $fieldmap=createFieldMap($surveyid, "full", false, false, $language); + foreach ($fieldmap as $field) { - /** - * Initiate the Spreadsheet_Excel_Writer - */ - Yii::import('application.libraries.admin.pear.Spreadsheet.Excel.Xlswriter', true); - if($pdfOutput=='F') - $workbook = new Xlswriter($tempdir.'/statistic-survey'.$surveyid.'.xls'); - else - $workbook = new Xlswriter(); - - $workbook->setVersion(8); - // Inform the module that our data will arrive as UTF-8. - // Set the temporary directory to avoid PHP error messages due to open_basedir restrictions and calls to tempnam("", ...) - if (!empty($tempdir)) { - $workbook->setTempDir($tempdir); - } - if ($pdfOutput!='F') - $workbook->send('statistic-survey'.$surveyid.'.xls'); - - // Creating the first worksheet - $sheet =& $workbook->addWorksheet(utf8_decode('results-survey'.$surveyid)); - $sheet->setInputEncoding('utf-8'); - $sheet->setColumn(0,20,20); - $separator="~|"; - /**XXX*/ + if(isset($field['qid']) && $field['qid']!='') + $aQuestionMap[]=$field['sid'].'X'.$field['gid'].'X'.$field['qid']; } - /** - * Start generating - */ // creates array of post variable names for (reset($_POST); $key=key($_POST); next($_POST)) { $postvars[]=$key;} - $aQuestionMap=array(); - foreach ($fieldmap as $field) - { - $q = $field['q']; - if(isset($q->id) && $q->id!='') - $aQuestionMap[]=$q->surveyid.'X'.$q->gid.'X'.$q->id; - } - /* * Iterate through postvars to create "nice" data for SQL later. * * Remember there might be some filters applied which have to be put into an SQL statement + * + * This foreach iterates through the name ($key) of each post value and builds a SELECT + * statement out of it. It returns an array called $selects[] which will have a select query + * for each filter chosen. ie: $select[0]="`74X71X428EXP` ='Y'"; + * + * This array is used later to build the overall query used to limit the number of responses + * */ if(isset($postvars)) - foreach ($postvars as $pv) { //Only do this if there is actually a value for the $pv - if (in_array($pv, $allfields) || in_array(substr($pv,1),$aQuestionMap) || in_array($pv,$aQuestionMap) || (($pv[0]=='D' || $pv[0]=='N' || $pv[0]=='K') && in_array(substr($pv,1,strlen($pv)-2),$aQuestionMap))) + if ( + in_array($pv, $allfields) || in_array(substr($pv,1),$aQuestionMap) || in_array($pv,$aQuestionMap) + || ( + ( + $pv[0]=='D' || $pv[0]=='N' || $pv[0]=='K' + ) + && in_array(substr($pv,1,strlen($pv)-2),$aQuestionMap) + ) + ) { $firstletter=substr($pv,0,1); /* @@ -558,28 +351,24 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, //create a list out of the $pv array list($lsid, $lgid, $lqid) = explode("X", $pv); - $aquery="SELECT title FROM {{questions}} WHERE parent_qid=$lqid AND language='{$language}' and scale_id=0 ORDER BY question_order"; - $aresult=Yii::app()->db->createCommand($aquery)->query(); - - // go through every possible answer - foreach ($aresult->readAll() as $arow) + $aresult=Questions::model()->findAll(array('order'=>'question_order', 'condition'=>'parent_qid=:parent_qid AND scale_id=0', 'params'=>array(":parent_qid"=>$lqid))); + foreach ($aresult as $arow) { - $arow=array_values($arow); // only add condition if answer has been chosen - if (in_array($arow[0], $_POST[$pv])) + if (in_array($arow['title'], $_POST[$pv])) { - $mselects[]=Yii::app()->db->quoteColumnName(substr($pv, 1, strlen($pv)).$arow[0])." = 'Y'"; + $mselects[]=Yii::app()->db->quoteColumnName(substr($pv, 1, strlen($pv)).$arow['title'])." = 'Y'"; } } + /* If there are mutliple conditions generated from this multiple choice question, join them using the boolean "OR" */ if ($mselects) { $thismulti=implode(" OR ", $mselects); $selects[]="($thismulti)"; - $mselects = ""; + unset($mselects); } } - //N - Numerical Input //K - Multiple Numerical Input elseif ($firstletter == "N" || $firstletter == "K") @@ -695,240 +484,102 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, } } } - else - { - $statisticsoutput .= ""; - } - } //end foreach -> loop through filter options to create SQL - //count number of answers - $query = "SELECT count(*) FROM {{survey_$surveyid}}"; - - //if incompleted answers should be filtert submitdate has to be not null - if (incompleteAnsFilterState() == "inc") {$query .= " WHERE submitdate is null";} - elseif (incompleteAnsFilterState() == "filter") {$query .= " WHERE submitdate is not null";} - $result = Yii::app()->db->createCommand($query)->query(); - - //$total = total number of answers - $row=$result->read(); $total=reset($row); - - //are there any filters that have to be taken care of? - if (isset($selects) && $selects) - { - //filter incomplete answers? - if (incompleteAnsFilterState() == "filter" || incompleteAnsFilterState() == "inc") {$query .= " AND ";} - - else {$query .= " WHERE ";} - - //add filter criteria to SQL - $query .= implode(" AND ", $selects); + return $selects; } +/** +* Builds an array containing information about this particular question/answer combination +* +* @param string $rt The code passed from the statistics form listing the field/answer (SGQA) combination to be displayed +* @param mixed $language The language to present output in +* @param mixed $surveyid The survey id +* @param string $outputType +* +* @output array $output An array containing "alist"=>A list of answers to the question in the form of an array ($alist array +* contains an array for every field to be displayed - with the Actual Question Code/Title, The text (flattened) +* of the question, and the fieldname where the data is stored. +* "qtitle"=>The title of the question, +* "qquestion"=>The description of the question, +* "qtype"=>The question type code +*/ +function buildOutputList($rt, $language, $surveyid, $outputType, $sql) { + + //Set up required variables + $alist=array(); + $qtitle=""; + $qquestion=""; + $qtype=""; + $statlangcode = getBaseLanguageFromSurveyID($surveyid); + $statlang = new Limesurvey_lang($statlangcode); + $firstletter = substr($rt, 0, 1); + $fieldmap=createFieldMap($surveyid, "full", false, false, $language); + $sDatabaseType = Yii::app()->db->getDriverName(); + $statisticsoutput=""; - //get me some data Scotty - $result=Yii::app()->db->createCommand($query)->query(); - - //put all results into $results - $row=$result->read(); $results=reset($row); - - if ($total) - { - $percent=sprintf("%01.2f", ($results/$total)*100); - - } + /* Some variable depend on output type, actually : only line feed */ switch($outputType) { - case "xls": - $xlsRow = 0; - $sheet->write($xlsRow,0,$statlang->gT("Number of records in this query:",'unescaped')); - $sheet->write($xlsRow,1,$results); - ++$xlsRow; - $sheet->write($xlsRow,0,$statlang->gT("Total records in survey:",'unescaped')); - $sheet->write($xlsRow,1,$total); - - if($total) - { - ++$xlsRow; - $sheet->write($xlsRow,0,$statlang->gT("Percentage of total:",'unescaped')); - $sheet->write($xlsRow,1,$percent."%"); - } - - break; + case 'xls': case 'pdf': - - // add summary to pdf - $array = array(); - //$array[] = array($statlang->gT("Results"),""); - $array[] = array($statlang->gT("Number of records in this query:",'unescaped'), $results); - $array[] = array($statlang->gT("Total records in survey:",'unescaped'), $total); - - if($total) - $array[] = array($statlang->gT("Percentage of total:",'unescaped'), $percent."%"); - - $pdf->addPage('P','A4'); - - $pdf->Bookmark($pdf->delete_html($statlang->gT("Results",'unescaped')), 0, 0); - $pdf->titleintopdf($statlang->gT("Results",'unescaped'),$statlang->gT("Survey",'unescaped')." ".$surveyid); - $pdf->tableintopdf($array); - - $pdf->addPage('P','A4'); - + $linefeed = "\n"; break; case 'html': - - $statisticsoutput .= "
\n\n" - ."\t\n" - ."\t' - ."\n" - ."\t' - ."\n"; - - //only calculate percentage if $total is set - if ($total) - { - $percent=sprintf("%01.2f", ($results/$total)*100); - $statisticsoutput .= "\t' - ."\n"; - } - $statisticsoutput .="
".$statlang->gT("Results")."
".$statlang->gT("Number of records in this query:").'$results
".$statlang->gT("Total records in survey:").'$total
".$statlang->gT("Percentage of total:").'$percent%
\n"; - + $linefeed = "
\n"; break; default: - - break; } - //put everything from $selects array into a string connected by AND - if (isset ($selects) && $selects) {$sql=implode(" AND ", $selects);} - - elseif (!empty($newsql)) {$sql = $newsql;} - - if (!isset($sql) || !$sql) {$sql="NULL";} - - //only continue if we have something to output - if ($results > 0) - { - if($outputType=='html' && $browse === true) - { - //add a buttons to browse results - $statisticsoutput .= "
\n" - ."\t\t

" - ."\t\t\t\n" - ."\t\t\t\n" - ."\t\t\t\n" - ."\t\t\t\n" - ."\t\t

" - ."\t\t
\n"; - } - } //end if (results > 0) - - //Show Summary results - if (isset($summary) && $summary) - { - //let's run through the survey - $runthrough=$summary; - - //START Chop up fieldname and find matching questions - - //GET LIST OF LEGIT QIDs FOR TESTING LATER - $lq = "SELECT DISTINCT qid FROM {{questions}} WHERE sid=$surveyid and parent_qid=0"; - $lr = Yii::app()->db->createCommand($lq)->query(); - - //loop through the IDs - foreach ($lr->readAll() as $lw) - { - //this creates an array of question id's' - $legitqids[] = $lw['qid']; - } - - - //loop through all selected questions - foreach ($runthrough as $rt) - { - $firstletter = substr($rt, 0, 1); - // 1. Get answers for question ############################################################## - - //M - Multiple choice, therefore multiple fields + //M - Multiple choice, therefore multiple fields - one for each answer if ($firstletter == "M" || $firstletter == "P") { //get SGQ data list($qsid, $qgid, $qqid) = explode("X", substr($rt, 1, strlen($rt)), 3); //select details for this question - $nquery = "SELECT title, type, question, parent_qid, other FROM {{questions}} WHERE language='{$language}' AND parent_qid=0 AND qid='$qqid'"; - $nresult = Yii::app()->db->createCommand($nquery)->query(); - - //loop through question data - foreach ($nresult->readAll() as $nrow) - { - $nrow=array_values($nrow); - $qtitle=$nrow[0]; - $qtype=$nrow[1]; - $qquestion=flattenText($nrow[2]); - $qlid=$nrow[3]; - $qother=$nrow[4]; - } + $nresult = Questions::model()->find('language=:language AND parent_qid=0 AND qid=:qid', array(':language'=>$language, ':qid'=>$qqid)); + $qtitle=$nresult->title; + $qtype=$nresult->type; + $qquestion=flattenText($nresult->question); + $qlid=$nresult->parent_qid; + $qother=$nresult->other; //1. Get list of answers - $query="SELECT title, question FROM {{questions}} WHERE parent_qid='$qqid' AND language='{$language}' and scale_id=0 ORDER BY question_order"; - $result=Yii::app()->db->createCommand($query)->query(); - - //loop through multiple answers - foreach ($result->readAll() as $row) + $result=Questions::model()->findAll(array('order'=>'question_order', + 'condition'=>'language=:language AND parent_qid=:qid AND scale_id=0', + 'params'=>array(':language'=>$language, ':qid'=>$qqid) + )); + foreach ($result as $row) { - $row=array_values($row); - $mfield=substr($rt, 1, strlen($rt))."$row[0]"; - - //create an array containing answer code, answer and fieldname(??) - $alist[]=array("$row[0]", flattenText($row[1]), $mfield); + $mfield=substr($rt, 1, strlen($rt)).$row['title']; + $alist[]=array($row['title'], flattenText($row['question']), $mfield); } - //check "other" field. is it set? + //Add the "other" answer if it exists if ($qother == "Y") { $mfield=substr($rt, 1, strlen($rt))."other"; - - //create an array containing answer code, answer and fieldname(??) $alist[]=array($statlang->gT("Other"), $statlang->gT("Other"), $mfield); } } - - //S - Short Free Text - //T - Long Free Text + //S - Short Free Text and T - Long Free Text elseif ($firstletter == "T" || $firstletter == "S") //Short and long text { - //search for key $fld = substr($rt, 1, strlen($rt)); $q=$fieldmap[$fld]['q']; - //get SGQA IDs - $qsid=$q->surveyid; - $qgid=$q->gid; - $qqid=$q->id; - - list($qanswer, $qlid)=isset($q->aid) ? explode("_", $q->aid) : array("", ""); - //get SGQ data - //list($qsid, $qgid, $qqid) = explode("X", substr($rt, 1, strlen($rt)), 3); - //get question data - $nquery = "SELECT title, type, question, other, parent_qid FROM {{questions}} WHERE parent_qid=0 AND qid='$qqid' AND language='{$language}'"; - $nresult = Yii::app()->db->createCommand($nquery)->query(); - - //loop through question data - foreach ($nresult->readAll() as $nrow) - { - $nrow=array_values($nrow); - $qtitle=flattenText($nrow[0]); - $qtype=$nrow[1]; - $qquestion=flattenText($nrow[2]); - $nlid=$nrow[4]; - } + $nresult = Questions::model()->find('language=:language AND parent_qid=0 AND qid=:qid', array(':language'=>$language, ':qid'=>$fielddata['qid'])); + $qtitle=$nresult->title; + $qtype=$nresult->type; + $qquestion=flattenText($nresult->question); + $qlid=$nresult->parent_qid; $mfield=substr($rt, 1, strlen($rt)); @@ -940,53 +591,41 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $alist[]=array("NoAnswer", $statlang->gT("No answer"), $mfield); } - - //Multiple short text + //Q - Multiple short text elseif ($firstletter == "Q") { + //Build an array of legitimate qid's for testing later + $qidquery = Questions::model()->findAll("sid=:surveyid AND parent_qid=0", array(":surveyid"=>$surveyid)); + foreach ($qidquery as $row) { $legitqids[] = $row['qid']; } //get SGQ data list($qsid, $qgid, $qqid) = explode("X", substr($rt, 1, strlen($rt)), 3); - //separating another ID $tmpqid=substr($qqid, 0, strlen($qqid)-1); - //check if we have legid QIDs. if not create them by substringing + //check if we have a QID that actually exists. if not create them by substringing. Note that + //all of this is due to the fact that when we create a field for an subquestion, we don't seperate + //the question id from the subquestion id - and this is a weird, backwards way of doing that. while (!in_array ($tmpqid,$legitqids)) $tmpqid=substr($tmpqid, 0, strlen($tmpqid)-1); - //length of QID - $qidlength=strlen($tmpqid); - + $iQuestionIDlength=strlen($tmpqid); //we somehow get the answer code (see SQL later) from the $qqid - $qaid=substr($qqid, $qidlength, strlen($qqid)-$qidlength); + $qaid=substr($qqid, $iQuestionIDlength, strlen($qqid)-$iQuestionIDlength); - //get some question data - $nquery = "SELECT title, type, question, other FROM {{questions}} WHERE qid='".substr($qqid, 0, $qidlength)."' AND parent_qid=0 AND language='{$language}'"; - $nresult = Yii::app()->db->createCommand($nquery)->query(); + //get question data + $nresult = Questions::model()->find('language=:language AND parent_qid=0 AND qid=:qid', array(':language'=>$language, ':qid'=>substr($qqid, 0, $iQuestionIDlength))); + $qtitle=$nresult->title; + $qtype=$nresult->type; + $qquestion=flattenText($nresult->question); //more substrings $count = substr($qqid, strlen($qqid)-1); - //loop through question data - foreach ($nresult->readAll() as $nrow) - { - $nrow=array_values($nrow); - $qtitle=flattenText($nrow[0]).'-'.$count; - $qtype=$nrow[1]; - $qquestion=flattenText($nrow[2]); - } - //get answers - $qquery = "SELECT title as code, question as answer FROM {{questions}} WHERE parent_qid='".substr($qqid, 0, $qidlength)."' AND title='$qaid' AND language='{$language}' ORDER BY question_order"; - $qresult=Yii::app()->db->createCommand($qquery)->query(); - - //loop through answer data - foreach ($qresult->readAll() as $qrow) - { - $qrow=array_values($qrow); - //store each answer here - $atext=flattenText($qrow[1]); - } - + $nresult = Questions::model()->find(array('order'=>'question_order', + 'condition'=>'language=:language AND parent_qid=:parent_qid AND title=:title', + 'params'=>array(':language'=>$language, ':parent_qid'=>substr($qqid, 0, $iQuestionIDlength), ':title'=>$qaid) + )); + $atext=flattenText($nresult->question); //add this to the question title $qtitle .= " [$atext]"; @@ -1001,8 +640,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $alist[]=array("NoAnswer", $statlang->gT("No answer"), $mfield); } - - //RANKING OPTION THEREFORE CONFUSING + //RANKING OPTION elseif ($firstletter == "R") { //getting the needed IDs somehow @@ -1043,20 +681,12 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, list($qsid, $qgid, $qqid) = explode("X", substr($rt, 1, strlen($rt)), 3); //select details for this question - $nquery = "SELECT title, type, question, parent_qid, other FROM {{questions}} WHERE language='{$language}' AND parent_qid=0 AND qid='$qqid'"; - $nresult = Yii::app()->db->createCommand($nquery)->query(); - - //loop through question data - foreach ($nresult->readAll() as $nrow) - { - $nrow=array_values($nrow); - $qtitle=$nrow[0]; - $qtype=$nrow[1]; - $qquestion=flattenText($nrow[2]); - $qlid=$nrow[3]; - $qother=$nrow[4]; - } - + $nresult = Questions::model()->find('language=:language AND parent_qid=0 AND qid=:qid', array(':language'=>$language, ':qid'=>substr($qqid, 0, $iQuestionIDlength))); + $qtitle=$nresult->title; + $qtype=$nresult->type; + $qquestion=flattenText($nresult->question); + $qlid=$nresult->parent_qid; + $qother=$nresult->other; /* 4) Average size of file per respondent 5) Average no. of files @@ -1092,7 +722,6 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, foreach ($result->readAll() as $row) { - $json = $row['json']; $phparray = json_decode($json); @@ -1146,7 +775,6 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, break; case 'pdf': - $headPDF = array(); $tablePDF = array(); $footPDF = array(); @@ -1202,6 +830,9 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, //multiple numerical input if($firstletter == "K") { + //Build an array of legitimate qid's for testing later + $qidquery = Questions::model()->findAll("sid=:surveyid AND parent_qid=0", array(":surveyid"=>$surveyid)); + foreach ($qidquery as $row) { $legitqids[] = $row['qid']; } // This is a multiple numerical question so we need to strip of the answer id to find the question title $tmpqid=substr($qqid, 0, strlen($qqid)-1); @@ -1210,25 +841,27 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $tmpqid=substr($tmpqid, 0, strlen($tmpqid)-1); //check lenght of ID - $qidlength=strlen($tmpqid); + $iQuestionIDlength=strlen($tmpqid); //get answer ID from qid - $qaid=substr($qqid, $qidlength, strlen($qqid)-$qidlength); + $qaid=substr($qqid, $iQuestionIDlength, strlen($qqid)-$iQuestionIDlength); //get question details from DB - $nquery = "SELECT title, type, question, qid, parent_qid + $nresult=Questions::model()->findAll('parent_qid=0 AND qid=:qid AND language=:language', array(':qid'=>substr($qqid, 0, $iQuestionIDlength), ':language'=>$language)); + /* $nquery = "SELECT title, type, question, qid, parent_qid FROM {{questions}} - WHERE parent_qid=0 AND qid='".substr($qqid, 0, $qidlength)."' + WHERE parent_qid=0 AND qid='".substr($qqid, 0, $iQuestionIDlength)."' AND language='{$language}'"; - $nresult = Yii::app()->db->createCommand($nquery)->query(); + $nresult = Yii::app()->db->createCommand($nquery)->query(); */ } //probably question type "N" = numerical input else { + $nresult=Questions::model()->findAll('parent_qid=0 AND qid=:qid AND language=:language', array(':qid'=>$qqid, ':language'=>$language)); //we can use the qqid without any editing - $nquery = "SELECT title, type, question, qid, parent_qid FROM {{questions}} WHERE parent_qid=0 AND qid='$qqid' AND language='{$language}'"; - $nresult = Yii::app()->db->createCommand($nquery)->query(); + /* $nquery = "SELECT title, type, question, qid, parent_qid FROM {{questions}} WHERE parent_qid=0 AND qid='$qqid' AND language='{$language}'"; + $nresult = Yii::app()->db->createCommand($nquery)->query(); */ } //loop through results @@ -1311,7 +944,6 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $fieldname=substr($rt, 1, strlen($rt)); //special treatment for MS SQL databases - $sDatabaseType = Yii::app()->db->getDriverName(); if ($sDatabaseType == 'mssql' || $sDatabaseType == 'sqlsrv') { //standard deviation @@ -1370,10 +1002,10 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, if ($sql != "NULL") {$query .= " AND $sql";} //execute query - $result=Yii::app()->db->createCommand($query)->query(); + $result=Yii::app()->db->createCommand($query)->queryAll(); //get calculated data - foreach ($nresult->readAll() as $row) + foreach ($result as $row) { //put translation of mean and calculated data into $showem array $showem[]=array($statlang->gT("Sum"), $row['sum']); @@ -1429,10 +1061,24 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, //no more comment from Mazi regarding the calculation + /* IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT */ + /* IF YOU DON'T UNDERSTAND WHAT QUARTILES ARE DO NOT MODIFY THIS CODE */ + /* Quartiles and Median values are NOT related to average, and the sum is irrelevent */ + // Calculating only makes sense with more than one result if ($medcount>1) { //1ST QUARTILE (Q1) + /* L=(1/4)(n+1), U=(3/4)(n+1) */ + /* Minitab linear interpolation between the two + closest data points. Minitab would let L = 2.5 and find the value half way between the + 2nd and 3rd data points. In our example, that would be (4+9)/2 = + 6.5. Similarly, the upper quartile value would be half way between + the 7th and 8th data points, which would be (49+64)/2 = 56.5. If L + were 2.25, Minitab would find the value one fourth of the way + between the 2nd and 3rd data points and if L were 2.75, Minitab + would find the value three fourths of the way between the 2nd and + 3rd data points. */ $q1=(1/4)*($medcount+1); $q1b=(int)((1/4)*($medcount+1)); $q1c=$q1b-1; @@ -1442,36 +1088,31 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, // fix if there are too few values to evaluate. if ($q1c<0) {$q1c=0;} - if ($q1 != $q1b) + if ($q1 != $q1b) //The value will be between two of the individual results { - //ODD NUMBER $query = $querystarter . " ORDER BY ".Yii::app()->db->quoteColumnName($fieldname)."*1 "; - $result=Yii::app()->db->createCommand($query)->limit(2, $q1c)->query(); - - foreach ($result->readAll() as $row) + $result = Yii::app()->db->createCommand($query)->query(); + $i=0; + foreach ($result as $row) { - if ($total == 0) {$total=$total-$row[$fieldname];} - - else {$total=$total+$row[$fieldname];} - - $lastnumber=$row[$fieldname]; + if($row[$fieldname]) {$i++;} + if($i==$q1c) {$secondlastnumber=$row[$fieldname];} + if($i==$q1b) {$lastnumber=$row[$fieldname];} } - - $q1total=$lastnumber-((1-$q1diff)*$total); - - if ($q1total < $minimum) {$q1total=$minimum;} + $q1total=$lastnumber-((1-$q1diff)*$secondlastnumber); + //if ($q3total < $maximum) {$q1total=$maximum;} //What the? If the 3rd quartiel is higher than the highest, then make the 1st quartile the highest? This makes no sense! $showem[]=array($statlang->gT("1st quartile (Q1)"), $q1total); } else { - //EVEN NUMBER $query = $querystarter . " ORDER BY ".Yii::app()->db->quoteColumnName($fieldname)."*1 "; - $result=Yii::app()->db->createCommand($query)->limit(1, $q1c)->query(); + $result = Yii::app()->db->createCommand($query)->query(); - foreach ($result->readAll() as $row) + foreach ($result as $row) { - $showem[]=array($statlang->gT("1st quartile (Q1)"), $row[$fieldname]); + if($row[$fieldname]) {$i++;} + if($i==$q1b) {$showem[]=array($statlang->gT("1st quartile (Q1)"), $row[$fieldname]);} } } @@ -1488,22 +1129,31 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, { //remainder $query = $querystarter . " ORDER BY ".Yii::app()->db->quoteColumnName($fieldname)."*1 "; - $result=Yii::app()->db->createCommand($query)->limit(2, $medianc)->query(); + $result=Yii::app()->db->createCommand($query)->query(); - foreach ($result->readAll() as $row) {$total=$total+$row[$fieldname];} + $i=0; + foreach ($result as $row) { + if($row[$fieldname]) {$i++;} + if($i==$medianc) {$secondlastnumber=$row[$fieldname];} + if($i==$medianb) {$lastnumber=$row[$fieldname];} - $showem[]=array($statlang->gT("2nd quartile (Median)"), $total/2); } + $mediantotal=$lastnumber-((1-$mediandiff)*$secondlastnumber); + //if ($q3total < $maximum) {$q1total=$maximum;} //What the? If the 3rd quartiel is higher than the highest, then make the 1st quartile the highest? This makes no sense! + + $showem[]=array($statlang->gT("2nd quartile (Median)"), $mediantotal); + + } else { - //EVEN NUMBER $query = $querystarter . " ORDER BY ".Yii::app()->db->quoteColumnName($fieldname)."*1 "; - $result = Yii::app()->db->createCommand($query)->limit(1, $medianc-1)->query(); + $result = Yii::app()->db->createCommand($query)->query(); - foreach ($result->readAll() as $row) + foreach ($result as $row) { - $showem[]=array($statlang->gT("Median value"), $row[$fieldname]); + if($row[$fieldname]) {$i++;} + if($i==$medianb) {$showem[]=array($statlang->gT("2nd quartile (Median)"), $row[$fieldname]);} } } @@ -1511,39 +1161,46 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, //3RD QUARTILE (Q3) - $q3=(3/4)*($medcount+1); - $q3b=(int)((3/4)*($medcount+1)); - $q3c=$q3b-1; + /* L=(1/4)(n+1), U=(3/4)(n+1) */ + /* Minitab linear interpolation between the two + closest data points. Minitab would let L = 2.5 and find the value half way between the + 2nd and 3rd data points. In our example, that would be (4+9)/2 = + 6.5. Similarly, the upper quartile value would be half way between + the 7th and 8th data points, which would be (49+64)/2 = 56.5. If L + were 2.25, Minitab would find the value one fourth of the way + between the 2nd and 3rd data points and if L were 2.75, Minitab + would find the value three fourths of the way between the 2nd and + 3rd data points. */ + $q3=(3/4)*($medcount+1); //Find the 75th percentile according to count of items + $q3b=(int)((3/4)*($medcount+1)); //The int version of $q3 + $q3c=$q3b-1; //The number before the int version of $q3 $q3diff=$q3-$q3b; - if ($q3 != $q3b) + if ($q3 != $q3b) //The value will be between two of the individual results { $query = $querystarter . " ORDER BY ".Yii::app()->db->quoteColumnName($fieldname)."*1 "; - $result = Yii::app()->db->createCommand($query)->limit(2,$q3c)->query(); - - foreach ($result->readAll() as $row) + $result = Yii::app()->db->createCommand($query)->query(); + $i=0; + foreach ($result as $row) { - if ($total == 0) {$total=$total-$row[$fieldname];} - - else {$total=$total+$row[$fieldname];} - - $lastnumber=$row[$fieldname]; + if($row[$fieldname]) {$i++;} + if($i==$q3c) {$secondlastnumber=$row[$fieldname];} + if($i==$q3b) {$lastnumber=$row[$fieldname];} } - $q3total=$lastnumber-((1-$q3diff)*$total); - - if ($q3total < $maximum) {$q1total=$maximum;} + $q3total=$lastnumber-((1-$q3diff)*$secondlastnumber); + //if ($q3total < $maximum) {$q1total=$maximum;} //What the? If the 3rd quartiel is higher than the highest, then make the 1st quartile the highest? This makes no sense! $showem[]=array($statlang->gT("3rd quartile (Q3)"), $q3total); } - else { $query = $querystarter . " ORDER BY ".Yii::app()->db->quoteColumnName($fieldname)."*1"; - $result = Yii::app()->db->createCommand($query)->limit(1, $q3c); + $result = Yii::app()->db->createCommand($query)->query(); - foreach ($result->readAll() as $row) + foreach ($result as $row) { - $showem[]=array($statlang->gT("3rd quartile (Q3)"), $row[$fieldname]); + if($row[$fieldname]) {$i++;} + if($i==$q3b) {$showem[]=array($statlang->gT("3rd quartile (Q3)"), $row[$fieldname]);} } } @@ -1620,7 +1277,14 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, ."\t\t\t".sprintf($statlang->gT("Q1 and Q3 calculated using %s"), "".$statlang->gT("minitab method")."") ."\n" ."\t\t\n" - ."\t\n\n"; + ."\t\n"; + $statisticsoutput .= "\t\n" + ."\t\t + \n"; + $statisticsoutput .= " +
"; + $statisticsoutput .= "\n"; break; default: @@ -1695,21 +1359,16 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, */ } - // NICE SIMPLE SINGLE OPTION ANSWERS else { //search for key $q=$fieldmap[$rt]['q']; - //print_r($fielddata); //get SGQA IDs $qsid=$q->surveyid; $qqid=$q->id; $qanswer=$q->aid; - - //question type $qtype=$fielddata['type']; - //get question data $nquery = "SELECT title, type, question, qid, parent_qid, other FROM {{questions}} WHERE qid='{$q->id}' AND parent_qid=0 and language='{$language}'"; $nresult = Yii::app()->db->createCommand($nquery)->query(); @@ -1826,8 +1485,8 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, { $qrow=array_values($qrow); $fquery = "SELECT * FROM {{answers}} WHERE qid='{$qiqid}' AND scale_id=0 AND code = '{$licode}' AND language='{$language}'ORDER BY sortorder, code"; - $fresult = dbExecuteAssoc($fquery); - foreach ($result->readAll() as $frow) + $fresult = Yii::app()->db->createCommand($fquery)->query(); + foreach ($fresult->readAll() as $frow) { $alist[]=array($frow['code'], $frow['answer']); $ltext=$frow['answer']; @@ -1839,33 +1498,32 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $qtitle .= "($qanswer)"; break; - case ":": //Array (Multiple Flexi) (Numbers) - $qidattributes=getQuestionAttributeValues($qiqid); - if (trim($qidattributes['multiflexible_max'])!='') { - $maxvalue=$qidattributes['multiflexible_max']; + $aQuestionAttributes=getQuestionAttributeValues($qiqid); + if (trim($aQuestionAttributes['multiflexible_max'])!='') { + $maxvalue=$aQuestionAttributes['multiflexible_max']; } else { $maxvalue=10; } - if (trim($qidattributes['multiflexible_min'])!='') + if (trim($aQuestionAttributes['multiflexible_min'])!='') { - $minvalue=$qidattributes['multiflexible_min']; + $minvalue=$aQuestionAttributes['multiflexible_min']; } else { $minvalue=1; } - if (trim($qidattributes['multiflexible_step'])!='') + if (trim($aQuestionAttributes['multiflexible_step'])!='') { - $stepvalue=$qidattributes['multiflexible_step']; + $stepvalue=$aQuestionAttributes['multiflexible_step']; } else { $stepvalue=1; } - if ($qidattributes['multiflexible_checkbox']!=0) { + if ($aQuestionAttributes['multiflexible_checkbox']!=0) { $minvalue=0; $maxvalue=1; $stepvalue=1; @@ -1887,13 +1545,13 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $qresult=Yii::app()->db->createCommand($qquery)->query(); //loop through answers - foreach ($result->readAll() as $qrow) + foreach ($qresult->readAll() as $qrow) { $qrow=array_values($qrow); //this question type uses its own labels $fquery = "SELECT * FROM {{answers}} WHERE qid='{$qiqid}' AND scale_id=0 AND language='{$language}'ORDER BY sortorder, code"; - $fresult = dbExecuteAssoc($fquery); + $fresult = Yii::app()->db->createCommand($fquery)->query(); //add code and title to results for outputting them later foreach ($fresult->readAll() as $frow) @@ -1947,10 +1605,11 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $sSubquestionQuery = "SELECT question FROM {{questions}} WHERE parent_qid='$qiqid' AND title='$qanswer' AND language='{$language}' ORDER BY question_order"; $questionDesc = Yii::app()->db->createCommand($sSubquestionQuery)->query()->read(); - $sSubquestion = flattenText($questionDesc["question"]); + $sSubquestion = flattenText($questionDesc['question']); //get question attributes - $qidattributes=getQuestionAttributeValues($qqid); + $aQuestionAttributes=getQuestionAttributeValues($qqid); + //check last character -> label 1 if (substr($rt,-1,1) == 0) @@ -1959,9 +1618,9 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $fquery = "SELECT * FROM {{answers}} WHERE qid='{$qqid}' AND scale_id=0 AND language='{$language}' ORDER BY sortorder, code"; //header available? - if (trim($qidattributes['dualscale_headerA'][$language])!='') { + if (trim($aQuestionAttributes['dualscale_headerA'][$language])!='') { //output - $labelheader= "[".$qidattributes['dualscale_headerA'][$language]."]"; + $labelheader= "[".$aQuestionAttributes['dualscale_headerA'][$language]."]"; } //no header @@ -1981,9 +1640,9 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $fquery = "SELECT * FROM {{answers}} WHERE qid='{$qqid}' AND scale_id=1 AND language='{$language}' ORDER BY sortorder, code"; //header available? - if (trim($qidattributes['dualscale_headerB'][$language])!='') { + if (trim($aQuestionAttributes['dualscale_headerB'][$language])!='') { //output - $labelheader= "[".$qidattributes['dualscale_headerB'][$language]."]"; + $labelheader= "[".$aQuestionAttributes['dualscale_headerB'][$language]."]"; } //no header @@ -2044,26 +1703,50 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, //put data into array $alist[]=array("", $statlang->gT("No answer")); - } //end else -> single option answers - - //foreach ($alist as $al) {$statisticsoutput .= "$al[0] - $al[1]
";} //debugging line - //foreach ($fvalues as $fv) {$statisticsoutput .= "$fv | ";} //debugging line + } + return array("alist"=>$alist, "qtitle"=>$qtitle, "qquestion"=>$qquestion, "qtype"=>$qtype, "statisticsoutput"=>$statisticsoutput); +} +/** +* displayResults builds html output to display the actual results from a survey +* +* @param mixed $outputs +* @param INT $results The number of results being displayed overall +* @param mixed $rt +* @param mixed $outputType +* @param mixed $surveyid +* @param mixed $sql +* @param mixed $usegraph +*/ +function displayResults($outputs, $results, $rt, $outputType, $surveyid, $sql, $usegraph, $browse, $pdf) { + + /* Set up required variables */ + $TotalCompleted = 0; //Count of actually completed answers + $statlangcode = getBaseLanguageFromSurveyID($surveyid); + $statlang = new Limesurvey_lang($statlangcode); + $statisticsoutput=""; + $sDatabaseType = Yii::app()->db->getDriverName(); + $tempdir = Yii::app()->getConfig("tempdir"); + $tempurl = Yii::app()->getConfig("tempurl"); + $firstletter = substr($rt, 0, 1); + $astatdata=array(); - //2. Collect and Display results ####################################################################### - if (isset($alist) && $alist) //Make sure there really is an answerlist, and if so: + if ($usegraph==1) { + //for creating graphs we need some more scripts which are included here + require_once(APPPATH.'/third_party/pchart/pchart/pChart.class'); + require_once(APPPATH.'/third_party/pchart/pchart/pData.class'); + require_once(APPPATH.'/third_party/pchart/pchart/pCache.class'); + $MyCache = new pCache($tempdir.'/'); + } - - // this will count the answers considered completed - $TotalCompleted = 0; switch($outputType) { case 'xls': - $xlsTitle = sprintf($statlang->gT("Field summary for %s"),html_entity_decode($qtitle,ENT_QUOTES,'UTF-8')); - $xlsDesc = html_entity_decode($qquestion,ENT_QUOTES,'UTF-8'); + $xlsTitle = sprintf($statlang->gT("Field summary for %s"),html_entity_decode($outputs['qtitle'],ENT_QUOTES,'UTF-8')); + $xlsDesc = html_entity_decode($outputs['qquestion'],ENT_QUOTES,'UTF-8'); ++$xlsRow; ++$xlsRow; @@ -2079,8 +1762,8 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, break; case 'pdf': - $sPDFQuestion=flattenText($qquestion,false,true); - $pdfTitle = $pdf->delete_html(sprintf($statlang->gT("Field summary for %s"),html_entity_decode($qtitle,ENT_QUOTES,'UTF-8'))); + $sPDFQuestion=flattenText($outputs['qquestion'],false,true); + $pdfTitle = $pdf->delete_html(sprintf($statlang->gT("Field summary for %s"),html_entity_decode($outputs['qtitle'],ENT_QUOTES,'UTF-8'))); $titleDesc = $sPDFQuestion; $pdf->addPage('P','A4'); @@ -2096,12 +1779,12 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, ."\t" //headline - .sprintf($statlang->gT("Field summary for %s"),$qtitle)."" + .sprintf($statlang->gT("Field summary for %s"),$outputs['qtitle'])."" ."\n" ."\t" //question title - .$qquestion."\n" + .$outputs['qquestion']."\n" ."\t\n\t\t"; break; default: @@ -2112,16 +1795,16 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, echo ''; //loop thorugh the array which contains all answer data - foreach ($alist as $al) + foreach ($outputs['alist'] as $al) { - //picks out alist that come from the multiple list above + //picks out answer list ($outputs['alist']/$al)) that come from the multiple list above if (isset($al[2]) && $al[2]) { - //handling for "other" option + //handling for "other" option if ($al[0] == $statlang->gT("Other")) { - if($qtype=='!' || $qtype=='L') + if($outputs['qtype']=='!' || $outputs['qtype']=='L') { // It is better for single choice question types to filter on the number of '-oth-' entries, than to // just count the number of 'other' values - that way with failing Javascript the statistics don't get messed up @@ -2143,8 +1826,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, * S = short free text * Q = multiple short text */ - - elseif ($qtype == "U" || $qtype == "T" || $qtype == "S" || $qtype == "Q" || $qtype == ";") + elseif ($outputs['qtype'] == "U" || $outputs['qtype'] == "T" || $outputs['qtype'] == "S" || $outputs['qtype'] == "Q" || $outputs['qtype'] == ";") { $sDatabaseType = Yii::app()->db->getDriverName(); @@ -2161,7 +1843,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $query .= ($sDatabaseType == "mysql")? Yii::app()->db->quoteColumnName($al[2])." = '')" : " (".Yii::app()->db->quoteColumnName($al[2])." LIKE ''))"; } } - elseif ($qtype == "O") + elseif ($outputs['qtype'] == "O") { $query = "SELECT count(*) FROM {{survey_$surveyid}} WHERE ( "; $query .= ($sDatabaseType == "mysql")? Yii::app()->db->quoteColumnName($al[2])." <> '')" : " (".Yii::app()->db->quoteColumnName($al[2])." NOT LIKE ''))"; @@ -2181,7 +1863,6 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $query .= " 'Y'"; } } - } //end if -> alist set else @@ -2255,15 +1936,16 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, //"other" handling //"Answers" means that we show an option to list answer to "other" text field - elseif ($al[0] === $statlang->gT("Other") || $al[0] === "Answers" || ($qtype === "O" && $al[0] === $statlang->gT("Comments")) || $qtype === "P") + elseif ($al[0] === $statlang->gT("Other") || $al[0] === "Answers" || ($outputs['qtype'] === "O" && $al[0] === $statlang->gT("Comments")) || $outputs['qtype'] === "P") { - if ($qtype == "P") $ColumnName_RM = $al[2]."comment"; + if ($outputs['qtype'] == "P") $ColumnName_RM = $al[2]."comment"; else $ColumnName_RM = $al[2]; - if ($qtype=='O') { + if ($outputs['qtype']=='O') { $TotalCompleted -=$row[0]; } $fname="$al[1]"; - if ($browse===true) $fname .= " "; + if ($browse===true) $fname .= " "; } /* @@ -2274,7 +1956,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, * S = short free text * Q = multiple short text */ - elseif ($qtype == "S" || $qtype == "U" || $qtype == "T" || $qtype == "Q") + elseif ($outputs['qtype'] == "S" || $outputs['qtype'] == "U" || $outputs['qtype'] == "T" || $outputs['qtype'] == "Q") { $headPDF = array(); $headPDF[] = array($statlang->gT("Answer"),$statlang->gT("Count"),$statlang->gT("Percentage")); @@ -2283,9 +1965,8 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, if ($al[0] == "Answers") { $fname= "$al[1]"; - if ($browse===true) $fname .= " "; + if ($browse===true) $fname .= " "; } elseif ($al[0] == "NoAnswer") { @@ -2306,7 +1987,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, { if(!isset($showheadline) || $showheadline != false) { - if($qtype == "5" || $qtype == "A") + if($outputs['qtype'] == "5" || $outputs['qtype'] == "A") { switch($outputType) { @@ -2345,7 +2026,6 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, break; } - $showheadline = false; } else @@ -2353,7 +2033,6 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, switch($outputType) { case 'xls': - $headXLS = array(); $headXLS[] = array($statlang->gT("Answer"),$statlang->gT("Count"),$statlang->gT("Percentage")); @@ -2381,7 +2060,6 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, break; default: - break; } @@ -2394,7 +2072,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $fname="$al[1] ($al[0])"; //these question types get special treatment by Yii::app()->getConfig('showaggregateddata') - if($qtype == "5" || $qtype == "A") + if($outputs['qtype'] == "5" || $outputs['qtype'] == "A") { //put non-edited data in here because $row will be edited later $grawdata[]=$row[0]; @@ -2549,15 +2227,15 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, } //end foreach -> loop through answer data //no filtering of incomplete answers and NO multiple option questions - //if ((incompleteAnsFilterState() != "filter") and ($qtype != "M") and ($qtype != "P")) + //if ((incompleteAnsFilterState() != "filter") and ($outputs['qtype'] != "M") and ($outputs['qtype'] != "P")) //error_log("TIBO ".print_r($showaggregated_indice_table,true)); - if (($qtype != "M") and ($qtype != "P")) + if (($outputs['qtype'] != "M") and ($outputs['qtype'] != "P")) { //is the checkbox "Don't consider NON completed responses (only works when Filter incomplete answers is Disable)" checked? - //if (isset($_POST["noncompleted"]) and ($_POST["noncompleted"] == "on") && (isset(Yii::app()->getConfig('showaggregateddata')) && Yii::app()->getConfig('showaggregateddata') == 0)) + //if (isset($_POST[''noncompleted']) and ($_POST['noncompleted'] == "on") && (isset(Yii::app()->getConfig('showaggregateddata')) && Yii::app()->getConfig('showaggregateddata') == 0)) // TIBO: TODO WE MUST SKIP THE FOLLOWING SECTION FOR TYPE A and 5 when // showaggreagated data is set and set to 1 - if (isset($_POST["noncompleted"]) and ($_POST["noncompleted"] == "on") ) + if (isset($_POST['noncompleted']) and ($_POST['noncompleted'] == "on") ) { //counter $i=0; @@ -2661,10 +2339,20 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, * 3 (25%) = percentage */ $statisticsoutput .= "\t\n\t\t" . $label[$i] ."\n" - ."\t\t\n" + ."\t\t\n"; + /* + * If there is a "browse" button in this label, let's make sure there's an extra row afterwards + * to store the columnlist + * + * */ + if(strpos($label[$i], "class='statisticsbrowsebutton'")) + { + $extraline=" +
\n"; + } //output absolute number of records - ."\t\t" . $grawdata[$i] . "\n"; + $statisticsoutput .= "\t\t" . $grawdata[$i] . "\n"; //no data @@ -2697,14 +2385,16 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $gdata[$i] = 0; //check if we have to adjust ouput due to Yii::app()->getConfig('showaggregateddata') setting - if(Yii::app()->getConfig('showaggregateddata') == 1 && ($qtype == "5" || $qtype == "A")) + if(Yii::app()->getConfig('showaggregateddata') == 1 && ($outputs['qtype'] == "5" || $outputs['qtype'] == "A")) { $statisticsoutput .= "\t\t"; } - elseif ($qtype == "S" || $qtype == "U" || $qtype == "T" || $qtype == "Q") + elseif ($outputs['qtype'] == "S" || $outputs['qtype'] == "U" || $outputs['qtype'] == "T" || $outputs['qtype'] == "Q") { - $statisticsoutput .= "\n\t\n"; + $statisticsoutput .= "\n\t"; } + $statisticsoutput .= "\n"; //Close the row + if(isset($extraline)) {$statisticsoutput .= $extraline;} break; default: @@ -2718,7 +2408,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, else { //check if data should be aggregated - if(Yii::app()->getConfig('showaggregateddata') == 1 && ($qtype == "5" || $qtype == "A")) + if(Yii::app()->getConfig('showaggregateddata') == 1 && ($outputs['qtype'] == "5" || $outputs['qtype'] == "A")) { //mark that we have done soemthing special here $aggregated = true; @@ -3102,6 +2792,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $statisticsoutput .= "\t\t"; //end output per line. there has to be a whitespace within the table cell to display correctly $statisticsoutput .= "\t\t \n\t\n"; + if(isset($extraline)) {$statisticsoutput .= $extraline;} break; default: @@ -3120,6 +2811,9 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $itemcounter++; + //Clear extraline + unset($extraline); + } //end while //only show additional values when this setting is enabled @@ -3128,7 +2822,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, //it's only useful to calculate standard deviation and arithmetic means for question types //5 = 5 Point Scale //A = Array (5 Point Choice) - if($qtype == "5" || $qtype == "A") + if($outputs['qtype'] == "5" || $outputs['qtype'] == "A") { $stddev = 0; $am = 0; @@ -3270,10 +2964,10 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, //PCHART has to be enabled and we need some data if ($usegraph == 1) { $bShowGraph = $aattr["statistics_showgraph"] == "1"; - $bAllowPieChart = ($qtype != "M" && $qtype != "P"); + $bAllowPieChart = ($outputs['qtype'] != "M" && $outputs['qtype'] != "P"); $bAllowMap = (isset($aattr["location_mapservice"]) && $aattr["location_mapservice"] == "1"); $bShowMap = ($bAllowMap && $aattr["statistics_showmap"] == "1"); - $bShowPieChart = ($bAllowPieChart && $aattr["statistics_graphtype"] == "1"); + $bShowPieChart = ($bAllowPieChart && (isset($aattr["statistics_graphtype"]) && $aattr["statistics_graphtype"] == "1")); $astatdata[$rt] = array( 'id' => $rt, @@ -3284,11 +2978,13 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, 'sp' => $bShowPieChart ); - Yii::app()->session['stats'][$rt] = array( + $stats=Yii::app()->session['stats']; + $stats[$rt]=array( 'lbl' => $lbl, 'gdata' => $gdata, 'grawdata' => $grawdata ); + Yii::app()->session['stats'] = $stats; if (array_sum($gdata)>0 && $bShowGraph == true) { @@ -3312,7 +3008,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $pdf->AddPage('P','A4'); $pdf->titleintopdf($pdfTitle,$titleDesc); - $pdf->Image($tempdir."/".$cachefilename, 0, 70, 180, 0, '', $homeurl."/admin.php?sid=$surveyid", 'B', true, 150,'C',false,false,0,true); + $pdf->Image($tempdir."/".$cachefilename, 0, 70, 180, 0, '', Yii::app()->getController()->createUrl("admin/survey/view/surveyid/".$surveyid), 'B', true, 150,'C',false,false,0,true); break; case 'html': @@ -3341,39 +3037,401 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, //close table/output if($outputType=='html') { - if ($usegraph) { + if ($usegraph==1) { $sImgUrl = Yii::app()->getConfig('adminimageurl'); $statisticsoutput .= "
" - ."" - ."" - ."" - ."" - ."" - ."" + ."" + ."" + ."" + ."" + ."" + ."" ."
"; } $statisticsoutput .= "
\n"; } - } //end if -> collect and display results - - + return array("statisticsoutput"=>$statisticsoutput, "pdf"=>$pdf, "astatdata"=>$astatdata); - //delete data - unset($gdata); - unset($grawdata); - unset($label); - unset($lbl); - unset($lblrtl); - unset($lblout); - unset($justcode); - unset ($alist); - - } // end foreach -> loop through all questions +} - //output +/** +* Generates statistics +* +* @param int $surveyid The survey id +* @param mixed $allfields +* @param mixed $q2show +* @param mixed $usegraph +* @param string $outputType Optional - Can be xls, html or pdf - Defaults to pdf +* @param string $pdfOutput Sets the target for the PDF output: DD=File download , F=Save file to local disk +* @param string $statlangcode Lamguage for statistics +* @param mixed $browse Show browse buttons +* @return buffer +*/ +function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, $outputType='pdf', $pdfOutput='I',$statlangcode=null, $browse = true) +{ + global $pdfdefaultfont, $pdffontsize; + + $astatdata=array(); //astatdata generates data for the output page's javascript so it can rebuild graphs on the fly + + //load surveytranslator helper + Yii::import('application.helpers.surveytranslator_helper', true); + + $statisticsoutput = ""; //This string carries all the actual HTML code to print. + $imagedir = Yii::app()->getConfig("imagedir"); + $tempdir = Yii::app()->getConfig("tempdir"); + $tempurl = Yii::app()->getConfig("tempurl"); + $clang = Yii::app()->lang; + $pdf=array(); //Make sure $pdf exists - it will be replaced with an object if a $pdf is actually being created + + + // Used for getting coordinates for google maps + $agmapdata = array(); + + //pick the best font file if font setting is 'auto' + if (is_null($statlangcode)) + { + $statlangcode = getBaseLanguageFromSurveyID($surveyid); + } + else + { + $statlang = new Limesurvey_lang($statlangcode); + } + + /* + * this variable is used in the function shortencode() which cuts off a question/answer title + * after $maxchars and shows the rest as tooltip (in html mode) + */ + $maxchars = 13; + //we collect all the html-output within this variable + $statisticsoutput =''; + /** + * $outputType: html || pdf || + */ + /** + * get/set Survey Details + */ + + //no survey ID? -> come and get one + if (!isset($surveyid)) {$surveyid=returnGlobal('sid');} + + //Get an array of codes of all available languages in this survey + $surveylanguagecodes = Survey::model()->findByPk($surveyid)->additionalLanguages; + $surveylanguagecodes[] = Survey::model()->findByPk($surveyid)->language; + + $fieldmap=createFieldMap($surveyid, "full", false, false, $statlang->getlangcode()); + + // Set language for questions and answers to base language of this survey + $language=$statlangcode; + + if($q2show=='all' ) + { + $summarySql=" SELECT gid, parent_qid, qid, type " + ." FROM {{questions}} WHERE parent_qid=0" + ." AND sid=$surveyid "; + + $summaryRs = Yii::app()->db->createCommand($summarySql)->query()->readAll(); + + foreach($summaryRs as $field) + { + $myField = $surveyid."X".$field['gid']."X".$field['qid']; + + // Multiple choice get special treatment + if ($field['type'] == "M") {$myField = "M$myField";} + if ($field['type'] == "P") {$myField = "P$myField";} + //numerical input will get special treatment (arihtmetic mean, standard derivation, ...) + if ($field['type'] == "N") {$myField = "N$myField";} + + if ($field['type'] == "|") {$myField = "|$myField";} + + if ($field['type'] == "Q") {$myField = "Q$myField";} + // textfields get special treatment + if ($field['type'] == "S" || $field['type'] == "T" || $field['type'] == "U"){$myField = "T$myField";} + //statistics for Date questions are not implemented yet. + if ($field['type'] == "D") {$myField = "D$myField";} + if ($field['type'] == "F" || $field['type'] == "H") + { + //Get answers. We always use the answer code because the label might be too long elsewise + $query = "SELECT code, answer FROM {{answers}} WHERE qid='".$field['qid']."' AND scale_id=0 AND language='{$language}' ORDER BY sortorder, answer"; + $result = Yii::app()->db->createCommand($query)->query(); + $counter2=0; + + //check all the answers + foreach ($result->readAll() as $row) + { + $row=array_values($row); + $myField = "$myField{$row[0]}"; + } + //$myField = "{$surveyid}X{$flt[1]}X{$flt[0]}{$row[0]}[]"; + + + } + if($q2show=='all') + $summary[]=$myField; + + //$allfields[]=$myField; + } + } + else + { + // This gets all the 'to be shown questions' from the POST and puts these into an array + if (!is_array($q2show)) + $summary=returnGlobal('summary'); + else + $summary = $q2show; + + //print_r($_POST); + //if $summary isn't an array we create one + if (isset($summary) && !is_array($summary)) + { + $summary = explode("+", $summary); + } + } + + /** + * pdf Config + */ + if($outputType=='pdf') + { + //require_once('classes/tcpdf/config/lang/eng.php'); + global $l; + $l['w_page'] = $statlang->gT("Page",'unescaped'); + //require_once('classes/tcpdf/mypdf.php'); + Yii::import('application.libraries.admin.pdf', true); + // create new PDF document + $pdf = new Pdf(); + $pdf->SetFont($pdfdefaultfont,'',$pdffontsize); + + $surveyInfo = getSurveyInfo($surveyid,$language); + + // set document information + $pdf->SetCreator(PDF_CREATOR); + $pdf->SetAuthor('LimeSurvey'); + $pdf->SetTitle('Statistic survey '.$surveyid); + $pdf->SetSubject($surveyInfo['surveyls_title']); + $pdf->SetKeywords('LimeSurvey, Statistics, Survey '.$surveyid.''); + $pdf->SetDisplayMode('fullpage', 'two'); + + // set header and footer fonts + $pdf->setHeaderFont(Array($pdfdefaultfont, '', PDF_FONT_SIZE_MAIN)); + $pdf->setFooterFont(Array($pdfdefaultfont, '', PDF_FONT_SIZE_DATA)); + + // set default header data + $pdf->SetHeaderData("statistics.png", 10, $statlang->gT("Quick statistics",'unescaped') , $statlang->gT("Survey")." ".$surveyid." '".flattenText($surveyInfo['surveyls_title'],false,true,'UTF-8')."'"); + + + // set default monospaced font + $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); + + //set margins + $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT); + $pdf->SetHeaderMargin(PDF_MARGIN_HEADER); + $pdf->SetFooterMargin(PDF_MARGIN_FOOTER); + + //set auto page breaks + $pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM); + + //set image scale factor + $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); + + //set some language-dependent strings + $pdf->setLanguageArray($l); + } + if($outputType=='xls') + { + /** + * Initiate the Spreadsheet_Excel_Writer + */ + Yii::import('application.libraries.admin.pear.Spreadsheet.Excel.Xlswriter', true); + if($pdfOutput=='F') + $workbook = new Xlswriter($tempdir.'/statistic-survey'.$surveyid.'.xls'); + else + $workbook = new Xlswriter(); + + $workbook->setVersion(8); + // Inform the module that our data will arrive as UTF-8. + // Set the temporary directory to avoid PHP error messages due to open_basedir restrictions and calls to tempnam("", ...) + if (!empty($tempdir)) { + $workbook->setTempDir($tempdir); + } + if ($pdfOutput!='F') + $workbook->send('statistic-survey'.$surveyid.'.xls'); + + // Creating the first worksheet + $sheet =& $workbook->addWorksheet(utf8_decode('results-survey'.$surveyid)); + $sheet->setInputEncoding('utf-8'); + $sheet->setColumn(0,20,20); + $separator="~|"; + /**XXX*/ + } + /** + * Start generating + */ + + + + $selects=buildSelects($allfields, $surveyid, $language); + + //count number of answers + $query = "SELECT count(*) FROM {{survey_$surveyid}}"; + + //if incompleted answers should be filtert submitdate has to be not null + if (incompleteAnsFilterState() == "inc") {$query .= " WHERE submitdate is null";} + elseif (incompleteAnsFilterState() == "filter") {$query .= " WHERE submitdate is not null";} + $result = Yii::app()->db->createCommand($query)->query(); + + //$total = total number of answers + $row=$result->read(); $total=reset($row); + + //are there any filters that have to be taken care of? + if (isset($selects) && $selects) + { + //filter incomplete answers? + if (incompleteAnsFilterState() == "filter" || incompleteAnsFilterState() == "inc") {$query .= " AND ";} + + else {$query .= " WHERE ";} + + //add filter criteria to SQL + $query .= implode(" AND ", $selects); + } + + + //get me some data Scotty + $result=Yii::app()->db->createCommand($query)->query(); + + //put all results into $results + $row=$result->read(); $results=reset($row); + + if ($total) + { + $percent=sprintf("%01.2f", ($results/$total)*100); + + } + switch($outputType) + { + case "xls": + $xlsRow = 0; + $sheet->write($xlsRow,0,$statlang->gT("Number of records in this query:",'unescaped')); + $sheet->write($xlsRow,1,$results); + ++$xlsRow; + $sheet->write($xlsRow,0,$statlang->gT("Total records in survey:",'unescaped')); + $sheet->write($xlsRow,1,$total); + + if($total) + { + ++$xlsRow; + $sheet->write($xlsRow,0,$statlang->gT("Percentage of total:",'unescaped')); + $sheet->write($xlsRow,1,$percent."%"); + } + + break; + case 'pdf': + + // add summary to pdf + $array = array(); + //$array[] = array($statlang->gT("Results"),""); + $array[] = array($statlang->gT("Number of records in this query:",'unescaped'), $results); + $array[] = array($statlang->gT("Total records in survey:",'unescaped'), $total); + + if($total) + $array[] = array($statlang->gT("Percentage of total:",'unescaped'), $percent."%"); + + $pdf->addPage('P','A4'); + + $pdf->Bookmark($pdf->delete_html($statlang->gT("Results",'unescaped')), 0, 0); + $pdf->titleintopdf($statlang->gT("Results",'unescaped'),$statlang->gT("Survey",'unescaped')." ".$surveyid); + $pdf->tableintopdf($array); + + $pdf->addPage('P','A4'); + + break; + case 'html': + + $statisticsoutput .= "
\n\n" + ."\t\n" + ."\t' + ."\n" + ."\t' + ."\n"; + + //only calculate percentage if $total is set + if ($total) + { + $percent=sprintf("%01.2f", ($results/$total)*100); + $statisticsoutput .= "\t' + ."\n"; + } + $statisticsoutput .="
".$statlang->gT("Results")."
".$statlang->gT("Number of records in this query:").'$results
".$statlang->gT("Total records in survey:").'$total
".$statlang->gT("Percentage of total:").'$percent%
\n"; + + break; + default: + + + break; + } + + //put everything from $selects array into a string connected by AND + //This string ($sql) can then be passed on to other functions so you can + //browse these results + if (isset ($selects) && $selects) {$sql=implode(" AND ", $selects);} + + elseif (!empty($newsql)) {$sql = $newsql;} + + if (!isset($sql) || !$sql) {$sql="NULL";} + + //only continue if we have something to output + if ($results > 0) + { + if($outputType=='html' && $browse === true) + { + //add a buttons to browse results + $statisticsoutput .= "
\n" + ."\t\t

" + ."\t\t\t\n" + ."\t\t\t\n" + ."\t\t\t\n" + ."\t\t\t\n" + ."\t\t

" + ."\t\t
\n"; + } + } //end if (results > 0) + + /* Show Summary results + * The $summary array contains each fieldname that we want to display statistics for + * + * */ + + if (isset($summary) && $summary) + { + //let's run through the survey + $runthrough=$summary; + + //START Chop up fieldname and find matching questions + + //loop through all selected questions + foreach ($runthrough as $rt) + { + + //Step 1: Get information about this response field (SGQA) for the summary + $outputs=buildOutputList($rt, $language, $surveyid, $outputType, $sql); + $statisticsoutput .= $outputs['statisticsoutput']; + //2. Collect and Display results ####################################################################### + if (isset($outputs['alist']) && $outputs['alist']) //Make sure there really is an answerlist, and if so: + { + $display=displayResults($outputs, $results, $rt, $outputType, $surveyid, $sql, $usegraph, $browse, $pdf); + $statisticsoutput .= $display['statisticsoutput']; + $astatdata = array_merge($astatdata, $display['astatdata']); + } //end if -> collect and display results + + + //Delete Build Outputs data + unset($outputs); + unset($display); + } // end foreach -> loop through all questions + + //output if($outputType=='html') $statisticsoutput .= "
 \n"; @@ -3408,7 +3466,7 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, break; case 'html': - $statisticsoutput .= "" + $statisticsoutput .= "\n" .""; return $statisticsoutput; @@ -3421,7 +3479,6 @@ function generate_statistics($surveyid, $allfields, $q2show='all', $usegraph=0, } - /** * Simple function to square a value * diff --git a/application/helpers/admin/token_helper.php b/application/helpers/admin/token_helper.php index 0a4d24d833e..353ebc03d1b 100644 --- a/application/helpers/admin/token_helper.php +++ b/application/helpers/admin/token_helper.php @@ -23,20 +23,21 @@ */ function createTokenTable($iSurveyID, $aAttributeFields=array()) { + Yii::app()->loadHelper('database'); $fields = array( 'tid' => 'pk', - 'participant_id' => 'VARCHAR(50)', - 'firstname' => 'VARCHAR(40)', - 'lastname' => 'VARCHAR(40)', + 'participant_id' => 'varchar(50)', + 'firstname' => 'varchar(40)', + 'lastname' => 'varchar(40)', 'email' => 'text', 'emailstatus' => 'text', - 'token' => 'VARCHAR(35)', - 'language' => 'VARCHAR(25)', - 'blacklisted' => 'CHAR(17)', - 'sent' => "VARCHAR(17) DEFAULT 'N'", - 'remindersent' => "VARCHAR(17) DEFAULT 'N'", + 'token' => 'varchar(35)', + 'language' => 'varchar(25)', + 'blacklisted' => 'varchar(17)', + 'sent' => "varchar(17) DEFAULT 'N'", + 'remindersent' => "varchar(17) DEFAULT 'N'", 'remindercount' => 'integer DEFAULT 0', - 'completed' => "VARCHAR(17) DEFAULT 'N'", + 'completed' => "varchar(17) DEFAULT 'N'", 'usesleft' => 'integer DEFAULT 1', 'validfrom' => 'datetime', 'validuntil' => 'datetime', @@ -47,7 +48,7 @@ function createTokenTable($iSurveyID, $aAttributeFields=array()) $fields[$sAttributeField]='string'; } try{ - Yii::app()->db->createCommand()->createTable("{{tokens_".intval($iSurveyID)."}}", $fields); + createTable("{{tokens_".intval($iSurveyID)."}}", $fields); return true; } catch(Exception $e) { return false; diff --git a/application/helpers/common_helper.php b/application/helpers/common_helper.php index 0993a954271..f7e0e9e1866 100644 --- a/application/helpers/common_helper.php +++ b/application/helpers/common_helper.php @@ -386,7 +386,7 @@ function getQuestions($surveyid,$gid,$selectedqid) { $clang = Yii::app()->lang; $s_lang = Survey::model()->findByPk($surveyid)->language; - $qrows = Questions::model()->findAllByAttributes(array('sid' => $surveyid, 'gid' => $gid, 'language' => $s_lang, 'parent_qid' => 0)); + $qrows = Questions::model()->findAllByAttributes(array('sid' => $surveyid, 'gid' => $gid, 'language' => $s_lang, 'parent_qid' => 0),array('order'=>'question_order')); if (!isset($sQuestionselecter)) {$sQuestionselecter="";} foreach ($qrows as $qrow) @@ -1464,12 +1464,7 @@ function getQuestion($fieldcode) foreach($fields as $field) { $q=$field['q']; - //try { - //echo 'test'; if($q->id==$qid && $q->surveyid==$sid && $q->gid==$gid) return $q; - //} catch(Exception $e) { - // var_dump($q);die(); - //} } return false; } @@ -1728,22 +1723,26 @@ function stripComments($comment, $email, $replace=''){ } -function validateTemplateDir($templatename) +function validateTemplateDir($sTemplateName) { $usertemplaterootdir = Yii::app()->getConfig('usertemplaterootdir'); $standardtemplaterootdir = Yii::app()->getConfig('standardtemplaterootdir'); - $defaulttemplate = Yii::app()->getConfig('defaulttemplate'); - if (is_dir("$usertemplaterootdir/{$templatename}/")) + $sDefaultTemplate = Yii::app()->getConfig('defaulttemplate'); + if (is_dir("$usertemplaterootdir/{$sTemplateName}/")) { - return $templatename; + return $sTemplateName; } - elseif (is_dir("$standardtemplaterootdir/{$templatename}/")) + elseif (is_dir("$standardtemplaterootdir/{$sTemplateName}/")) { - return $templatename; + return $sTemplateName; } - elseif (is_dir("$usertemplaterootdir/{$defaulttemplate}/")) + elseif (is_dir("$standardtemplaterootdir/{$sDefaultTemplate}/")) { - return $defaulttemplate; + return $sDefaultTemplate; + } + elseif (is_dir("$usertemplaterootdir/{$sDefaultTemplate}/")) + { + return $sDefaultTemplate; } else { @@ -2115,7 +2114,7 @@ function buildLabelSetCheckSumArray() /**$query = "SELECT lid FROM ".db_table_name('labelsets')." ORDER BY lid"; */ - $result = Labelsets::getLID();//($query) or safeDie("safe_died collecting labelset ids
$query
"); //Checked) + $result = Labelsets::model()->getLID();//($query) or safeDie("safe_died collecting labelset ids
$query
"); //Checked) $csarray=array(); foreach($result as $row) { @@ -2217,6 +2216,14 @@ function questionAttributes() "help"=>$clang->gT('Set the percentage width of the answer column (1-100)'), "caption"=>$clang->gT('Answer width')); + $qattributes["repeat_headings"]=array( + 'category'=>$clang->gT('Display'), + 'sortorder'=>100, + 'inputtype'=>'integer', + 'default'=>'', + "help"=>$clang->gT('Repeat headings every X subquestions (Set to 0 to deactivate heading repeat, deactivate minimum repeat headings from config).'), + "caption"=>$clang->gT('Repeat headers')); + $qattributes["array_filter"]=array( 'category'=>$clang->gT('Logic'), 'sortorder'=>100, @@ -2628,7 +2635,7 @@ function questionAttributes() $qattributes["numbers_only"]=array( 'category'=>$clang->gT('Other'), - 'sortorder'=>100, + 'sortorder'=>150, 'inputtype'=>'singleselect', 'options'=>array( 0=>$clang->gT('No'), @@ -2641,7 +2648,7 @@ function questionAttributes() $qattributes['show_totals'] = array( 'category' => $clang->gT('Other'), - 'sortorder' => 100, + 'sortorder' => 151, 'inputtype' => 'singleselect', 'options' => array( 'X' => $clang->gT('Off'), @@ -2656,7 +2663,7 @@ function questionAttributes() $qattributes['show_grand_total'] = array( 'category' => $clang->gT('Other'), - 'sortorder' => 100, + 'sortorder' => 152, 'inputtype' => 'singleselect', 'options' => array( 0 => $clang->gT('No'), @@ -2745,6 +2752,34 @@ function questionAttributes() "help"=>$clang->gT('Present answers in random order'), "caption"=>$clang->gT('Random answer order')); + $qattributes["showpopups"]=array( + 'category'=>$clang->gT('Display'), + 'sortorder'=>110, + 'inputtype'=>'singleselect', + 'options'=>array(0=>$clang->gT('No'), + 1=>$clang->gT('Yes')), + 'default'=>1, + "caption"=>$clang->gT('Show javascript alert'), + "help"=>$clang->gT('Show an alert if answers exceeds the number of max answers')); + $qattributes["samechoiceheight"]=array( + 'category'=>$clang->gT('Display'), + 'sortorder'=>120, + 'inputtype'=>'singleselect', + 'options'=>array(0=>$clang->gT('No'), + 1=>$clang->gT('Yes')), + 'default'=>1, + "caption"=>$clang->gT('Same height for all choice'), + "help"=>$clang->gT('Force each choice to have the same height')); + $qattributes["samelistheight"]=array( + 'category'=>$clang->gT('Display'), + 'sortorder'=>121, + 'inputtype'=>'singleselect', + 'options'=>array(0=>$clang->gT('No'), + 1=>$clang->gT('Yes')), + 'default'=>1, + "caption"=>$clang->gT('Same height for lists'), + "help"=>$clang->gT('Force the choice list and the rank list to have the same height')); + $qattributes["parent_order"]=array( 'category'=>$clang->gT('Display'), 'sortorder'=>100, @@ -2888,6 +2923,24 @@ function questionAttributes() "help"=>$clang->gT("Set a specific SPSS export scale type for this question"), "caption"=>$clang->gT('SPSS export scale type')); + $qattributes["choice_title"]=array( + 'category'=>$clang->gT('Other'), + 'sortorder'=>200, + "inputtype"=>"text", + 'i18n'=>true, + 'default'=>"", + "help"=>sprintf($clang->gT("Replace choice header (default: \"%s\")",'js'),$clang->gT("Your Choices")), + "caption"=>$clang->gT("Choice header")); + + $qattributes["rank_title"]=array( + 'category'=>$clang->gT('Other'), + 'sortorder'=>201, + "inputtype"=>"text", + 'i18n'=>true, + 'default'=>"", + "help"=>sprintf($clang->gT("Replace rank header (default: \"%s\")",'js'),$clang->gT("Your Ranking")), + "caption"=>$clang->gT("Rank header")); + //Timer attributes $qattributes["time_limit"]=array( 'category'=>$clang->gT('Timer'), @@ -3374,7 +3427,6 @@ function SendEmailMessage($body, $subject, $to, $from, $sitename, $ishtml=false, ob_end_clean(); } $maildebugbody=$mail->Body; - //if(!$sent) var_dump($maildebug); return $sent; } @@ -3673,7 +3725,7 @@ function createPassword() for ($i=0; $i<$password_length; $i++) { - $passwd .= $pwchars[floor(rand(0,strlen($pwchars)-1))]; + $passwd .= $pwchars[(int)floor(rand(0,strlen($pwchars)-1))]; } return $passwd; } @@ -3767,7 +3819,7 @@ function incompleteAnsFilterState() { global $filterout_incomplete_answers; $letsfilter=''; - $letsfilter = returnGlobal('filterinc'); //read get/post filterinc + $letsfilter = returnGlobal('completionstate'); //read get/post completionstate // first let's initialize the incompleteanswers session variable @@ -3780,14 +3832,8 @@ function incompleteAnsFilterState() Yii::app()->session['incompleteanswers'] = $filterout_incomplete_answers; } - if (Yii::app()->session['incompleteanswers']=='filter') { - return "filter"; //COMPLETE ANSWERS ONLY - } - elseif (Yii::app()->session['incompleteanswers']=='show') { - return false; //ALL ANSWERS - } - elseif (Yii::app()->session['incompleteanswers']=='incomplete') { - return "inc"; //INCOMPLETE ANSWERS ONLY + if (Yii::app()->session['incompleteanswers']=='complete' || Yii::app()->session['incompleteanswers']=='all' || Yii::app()->session['incompleteanswers']=='incomplete') { + return Yii::app()->session['incompleteanswers']; } else { // last resort is to prevent filtering @@ -3950,7 +3996,7 @@ function hasTemplateManageRights($userid, $templatefolder) { $criteria = new CDbCriteria; $criteria->addColumnCondition(array('uid' => $userid)); $criteria->addSearchCondition('folder', $templatefolder); - $query=Templates_rights_model::model()->find($criteria); + $query=Templates_rights::model()->find($criteria); //if ($result->RecordCount() == 0) return false; if (is_null($query)) return false; @@ -4334,14 +4380,14 @@ function cleanTempDirectory() $dir = Yii::app()->getConfig('tempdir').'/'; $dp = opendir($dir) or show_error('Could not open temporary directory'); while ($file = readdir($dp)) { - if (is_file($dir.$file) && (filemtime($dir.$file)) < (strtotime('-1 days')) && $file!='index.html' && $file!='.gitignore' && $file!='readme.txt' && $file!='..' && $file!='.' && $file!='.svn') { + if (is_file($dir.$file) && (filemtime($dir.$file)) < (strtotime('-1 days')) && $file!='index.html' && $file!='.gitignore' && $file!='readme.txt') { @unlink($dir.$file); } } $dir= Yii::app()->getConfig('tempdir').'/uploads/'; $dp = opendir($dir) or die ('Could not open temporary directory'); while ($file = readdir($dp)) { - if (is_file($dir.$file) && (filemtime($dir.$file)) < (strtotime('-1 days')) && $file!='index.html' && $file!='.gitignore' && $file!='readme.txt' && $file!='..' && $file!='.' && $file!='.svn') { + if (is_file($dir.$file) && (filemtime($dir.$file)) < (strtotime('-1 days')) && $file!='index.html' && $file!='.gitignore' && $file!='readme.txt') { @unlink($dir.$file); } } @@ -4495,30 +4541,33 @@ function getTokenData($surveyid, $token) * * @param mixed $sTemplateName */ -function getTemplatePath($sTemplateName) +function getTemplatePath($sTemplateName = false) { + if (!$sTemplateName) + { + $sTemplateName=Yii::app()->getConfig('defaulttemplate'); // if $sTemplateName is NULL or false or "" + } if (isStandardTemplate($sTemplateName)) { - return Yii::app()->getConfig("standardtemplaterootdir").'/'.$sTemplateName; + return Yii::app()->getConfig("standardtemplaterootdir").DIRECTORY_SEPARATOR.$sTemplateName; } else { - if (file_exists(Yii::app()->getConfig("usertemplaterootdir").'/'.$sTemplateName)) + if (is_dir(Yii::app()->getConfig("usertemplaterootdir").DIRECTORY_SEPARATOR.$sTemplateName)) { - return Yii::app()->getConfig("usertemplaterootdir").'/'.$sTemplateName; + return Yii::app()->getConfig("usertemplaterootdir").DIRECTORY_SEPARATOR.$sTemplateName; } - elseif (file_exists(Yii::app()->getConfig("usertemplaterootdir").'/'.Yii::app()->getConfig('defaulttemplate'))) + elseif (isStandardTemplate(Yii::app()->getConfig('defaulttemplate'))) { - return Yii::app()->getConfig("usertemplaterootdir").'/'.Yii::app()->getConfig('defaulttemplate'); + return Yii::app()->getConfig("standardtemplaterootdir").DIRECTORY_SEPARATOR.$sTemplateName; } - elseif (file_exists(Yii::app()->getConfig("standardtemplaterootdir").'/'.Yii::app()->getConfig('defaulttemplate'))) + elseif (file_exists(Yii::app()->getConfig("usertemplaterootdir").DIRECTORY_SEPARATOR.Yii::app()->getConfig('defaulttemplate'))) { - return Yii::app()->getConfig("standardtemplaterootdir").'/'.Yii::app()->getConfig('defaulttemplate'); + return Yii::app()->getConfig("usertemplaterootdir").DIRECTORY_SEPARATOR.Yii::app()->getConfig('defaulttemplate'); } else { - - return Yii::app()->getConfig("standardtemplaterootdir").'/default'; + return Yii::app()->getConfig("standardtemplaterootdir").DIRECTORY_SEPARATOR.'default'; } } } @@ -4607,7 +4656,7 @@ function getXMLWriter() { /** -* Returns true when a token can not be used (either doesn't exist or has less then one usage left +* Returns true when a token can not be used (either doesn't exist, has less then one usage left ) * * @param mixed $tid Token */ @@ -4616,7 +4665,6 @@ function usedTokens($token, $surveyid) $utresult = true; Tokens_dynamic::sid($surveyid); $query=Tokens_dynamic::model()->findAllByAttributes(array("token"=>$token)); - if (count($query) > 0) { $row = $query[0]; if ($row->usesleft > 0) $utresult = false; @@ -4725,6 +4773,8 @@ function getQuotaCompletedCount($iSurveyId, $quotaid) function getFullResponseTable($iSurveyID, $iResponseID, $sLanguageCode, $bHonorConditions=false) { $aFieldMap = createFieldMap($iSurveyID,'full',false,false,$sLanguageCode); //AJS# + $oLanguage = new Limesurvey_lang($sLanguageCode); + //Get response data $idrow = Survey_dynamic::model($iSurveyID)->findByAttributes(array('id'=>$iResponseID)); @@ -4775,7 +4825,7 @@ function getFullResponseTable($iSurveyID, $iResponseID, $sLanguageCode, $bHonorC } else { - $answer = getExtendedAnswer($iSurveyID,$q->fieldname, $idrow[$q->fieldname],$sLanguageCode); + $answer = getExtendedAnswer($iSurveyID,$q->fieldname, $idrow[$q->fieldname],$oLanguage); $aResultTable[$q->fieldname]=array($question,'',$answer); continue; } @@ -4783,7 +4833,7 @@ function getFullResponseTable($iSurveyID, $iResponseID, $sLanguageCode, $bHonorC } else { - $answer=getExtendedAnswer($iSurveyID,$q->fieldname, $idrow[$q->fieldname],$sLanguageCode); + $answer=getExtendedAnswer($iSurveyID,$q->fieldname, $idrow[$q->fieldname],$oLanguage); $aResultTable[$fname['fieldname']]=array($question,'',$answer); continue; } @@ -4796,7 +4846,7 @@ function getFullResponseTable($iSurveyID, $iResponseID, $sLanguageCode, $bHonorC if (isset($fname['subquestion2'])) $subquestion .= "[{$fname['subquestion2']}]"; - $answer = getExtendedAnswer($iSurveyID,$q->fieldname, $idrow[$q->fieldname],$sLanguageCode); + $answer = getExtendedAnswer($iSurveyID,$q->fieldname, $idrow[$q->fieldname],$oLanguage); $aResultTable[$q->fieldname]=array('',$subquestion,$answer); } return $aResultTable; @@ -4942,7 +4992,7 @@ function translateInsertansTags($newsid,$oldsid,$fieldnames) # translate 'quotals_urldescrip' and 'quotals_url' INSERTANS tags in quota_languagesettings $sql = "SELECT quotals_id, quotals_urldescrip, quotals_url from {{quota_languagesettings}} qls, {{quota}} q WHERE sid=".$newsid." AND q.id=qls.quotals_quota_id AND (quotals_urldescrip LIKE '%{$oldsid}X%' OR quotals_url LIKE '%{$oldsid}X%')"; - $res = dbExecuteAssoc($sql) or safeDie("Can't read quota table in transInsertAns"); // Checked + $result = dbExecuteAssoc($sql) or safeDie("Can't read quota table in transInsertAns"); // Checked foreach ($result->readAll() as $qentry) { @@ -6420,7 +6470,7 @@ function ellipsize($str, $max_length, $position = 1, $ellipsis = '…') $str = trim(strip_tags($str)); // Is the string long enough to ellipsize? - if (strlen($str) <= $max_length) + if (strlen($str) <= $max_length+3) { return $str; } diff --git a/application/helpers/database_helper.php b/application/helpers/database_helper.php index 9e9503bd165..bae7090650c 100644 --- a/application/helpers/database_helper.php +++ b/application/helpers/database_helper.php @@ -171,7 +171,7 @@ function dbRandom() $srandom= 0 + lcg_value()*(abs(1)); break; } - + return $srandom; } @@ -209,3 +209,32 @@ function dbGetTablesLike($table) { return (array) Yii::app()->db->createCommand(dbSelectTablesLike("{{{$table}}}"))->queryAll(); } + +/** +* Creates a table using the YII DB Schema function but properly handles custom field types for the various DB types +* +* @param mixed $sTableName +* @param mixed $aColumns +* @param mixed $aOptions +*/ +function createTable($sTableName, $aColumns, $aOptions=null) +{ + $sDBDriverName=Yii::app()->db->getDriverName(); + + if ($sDBDriverName=='sqlsrv' || $sDBDriverName=='mssql') + { + foreach ($aColumns as $sName=>&$sType) + { + $sType=str_replace('text','varchar(max)',$sType); + $sType=str_replace('binary','text',$sType); + } + } + if ($sDBDriverName=='pgsql') + { + foreach ($aColumns as $sName=>&$sType) + { + $sType=str_replace('varchar','character varying',$sType); + } + } + Yii::app()->db->createCommand()->createTable($sTableName,$aColumns,$aOptions); +} diff --git a/application/helpers/export_helper.php b/application/helpers/export_helper.php index b915aebe5ca..7446da8ea8d 100644 --- a/application/helpers/export_helper.php +++ b/application/helpers/export_helper.php @@ -466,14 +466,14 @@ function surveyGetXMLStructure($iSurveyID, $xmlwriter, $exclude=array()) $platform = Yii::app()->db->getDriverName(); if ($platform == 'mssql' || $platform =='sqlsrv') { - $query="SELECT qa.qid, qa.attribute, cast(qa.value as varchar(4000)) as value + $query="SELECT qa.qid, qa.attribute, cast(qa.value as varchar(4000)) as value, qa.language FROM {{question_attributes}} qa JOIN {{questions}} q ON q.qid = qa.qid AND q.sid={$iSurveyID} - where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, cast(qa.value as varchar(4000))"; + where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, cast(qa.value as varchar(4000)), qa.language"; } else { - $query="SELECT qa.qid, qa.attribute, qa.value + $query="SELECT qa.qid, qa.attribute, qa.value, qa.language FROM {{question_attributes}} qa JOIN {{questions}} q ON q.qid = qa.qid AND q.sid={$iSurveyID} - where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, qa.value"; + where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, qa.value, qa.language"; } buildXMLFromQuery($xmlwriter,$query,'question_attributes'); @@ -663,65 +663,11 @@ function QueXMLFixedArray($array) * @return bool|string Text of item to skip to otherwise false if nothing to skip to * @author Adam Zammit * @since 2010-10-28 +* @TODO Correctly handle conditions in a database agnostic way */ function QueXMLSkipTo($qid,$value,$cfieldname = "") { - global $iSurveyID, $quexmllang; - $qlang = new limesurvey_lang($quexmllang); - - $zeros = "0000000000"; - - $Query = "SELECT q.*," . concat("RIGHT(" . concat($zeros,'g.gid') . ",10)","RIGHT(". concat($zeros,'q.question_order') .",10)") ." as globalorder - FROM {{questions}} as q, {{questions}} as q2, {{groups}} as g, {{groups}} as g2 - WHERE q.parent_qid = 0 - AND q2.parent_qid = 0 - AND q.sid=$iSurveyID - AND q2.sid=$iSurveyID - AND q2.qid = $qid - AND g2.gid =q2.gid - AND g.gid = q.gid - AND " . concat("RIGHT(" . concat($zeros,'g.gid') . ",10)","RIGHT(". concat($zeros,'q.question_order') .",10)") ." > " . concat("RIGHT(" . concat($zeros,'g2.gid') . ",10)","RIGHT(". concat($zeros,'q2.question_order') .",10)") ." - ORDER BY globalorder"; - - $QueryResult = Yii::app()->db->createCommand($Query)->query(); - - $nextqid=""; - $nextorder=""; - - $Row = $QueryResult->read(); - if ($Row) - { - $nextqid = $Row['qid']; - $nextorder = $Row['globalorder']; - } - else - return false; - - - $Query = "SELECT q.* - FROM {{questions}} as q - JOIN {{groups}} as g ON (g.gid = q.gid) - LEFT JOIN {{conditions}} as c ON (c.cqid = '$qid' AND c.qid = q.qid AND c.method LIKE '==' AND c.value NOT LIKE '$value' $cfieldname) - WHERE q.sid = $iSurveyID - AND q.parent_qid = 0 - AND " . concat("RIGHT(" . concat($zeros,'g.gid') . ",10)","RIGHT(". concat($zeros,'q.question_order') .",10)") ." >= $nextorder - AND c.cqid IS NULL - ORDER BY " . concat("RIGHT(" . concat($zeros,'g.gid') . ",10)","RIGHT(". concat($zeros,'q.question_order') .",10)"); - - - $QueryResult = Yii::app()->db->createCommand($Query)->query(); - - $Row = $QueryResult->read(); - if ($Row) - { - if ($nextqid == $Row['qid']) - return false; - else - return $Row['title']; - } - else - return $qlang->gT("End"); - + return false; } /** @@ -1518,14 +1464,14 @@ function groupGetXMLStructure($xml,$gid) $platform = Yii::app()->db->getDriverName(); if ($platform == 'mssql' || $platform =='sqlsrv') { - $query="SELECT qa.qid, qa.attribute, cast(qa.value as varchar(4000)) as value + $query="SELECT qa.qid, qa.attribute, cast(qa.value as varchar(4000)) as value, qa.language FROM {{question_attributes}} qa JOIN {{questions}} q ON q.qid = qa.qid AND q.sid={$iSurveyID} and q.gid={$gid} - where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, cast(qa.value as varchar(4000))"; + where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, cast(qa.value as varchar(4000)), qa.language"; } else { - $query="SELECT qa.qid, qa.attribute, qa.value + $query="SELECT qa.qid, qa.attribute, qa.value, qa.language FROM {{question_attributes}} qa JOIN {{questions}} q ON q.qid = qa.qid AND q.sid={$iSurveyID} and q.gid={$gid} - where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, qa.value"; + where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, qa.value, qa.language"; } buildXMLFromQuery($xml,$query,'question_attributes'); @@ -1551,25 +1497,14 @@ function questionExport($action, $iSurveyID, $gid, $qid) $fn = "limesurvey_question_$qid.lsq"; $xml = getXMLWriter(); - if($action=='exportstructureLsrcCsvQuestion') - { - include_once(APPPATH.'/remotecontrol/lsrc.config.php'); - //Select title as Filename and save - $question = Questions::model()->findByAttributes(array('sid' => $iSurveyID, 'gid' => $gid, 'qid' => $qid)); - $questionTitle = $question->title; - $xml->openURI('remotecontrol/'.$queDir.substr($questionTitle,0,20).".lsq"); - } - else - { - header("Content-Type: text/html/force-download"); - header("Content-Disposition: attachment; filename=$fn"); - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); - header("Pragma: cache"); - // HTTP/1.0 - $xml->openURI('php://output'); - } + header("Content-Type: text/html/force-download"); + header("Content-Disposition: attachment; filename=$fn"); + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); + header("Pragma: cache"); + // HTTP/1.0 + $xml->openURI('php://output'); $xml->setIndent(true); $xml->startDocument('1.0', 'UTF-8'); @@ -1619,14 +1554,14 @@ function questionGetXMLStructure($xml,$gid,$qid) $platform = Yii::app()->db->getDriverName(); if ($platform == 'mssql' || $platform =='sqlsrv') { - $query="SELECT qa.qid, qa.attribute, cast(qa.value as varchar(4000)) as value + $query="SELECT qa.qid, qa.attribute, cast(qa.value as varchar(4000)) as value, qa.language FROM {{question_attributes}} qa JOIN {{questions}} q ON q.qid = qa.qid AND q.sid={$iSurveyID} and q.qid={$qid} - where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, cast(qa.value as varchar(4000))"; + where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, cast(qa.value as varchar(4000)), qa.language"; } else { - $query="SELECT qa.qid, qa.attribute, qa.value + $query="SELECT qa.qid, qa.attribute, qa.value, qa.language FROM {{question_attributes}} qa JOIN {{questions}} q ON q.qid = qa.qid AND q.sid={$iSurveyID} and q.qid={$qid} - where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, qa.value"; + where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, qa.value, qa.language"; } buildXMLFromQuery($xml,$query); diff --git a/application/helpers/expressions/em_core_helper.php b/application/helpers/expressions/em_core_helper.php index 2d1a82636ac..d37180f1830 100644 --- a/application/helpers/expressions/em_core_helper.php +++ b/application/helpers/expressions/em_core_helper.php @@ -29,7 +29,7 @@ class ExpressionManager { // These are the allowable suffixes for variables - each represents an attribute of a variable. - private static $RDP_regex_var_attr = 'code|gid|grelevance|gseq|jsName|mandatory|NAOK|qid|qseq|question|readWrite|relevanceStatus|relevance|rowdivid|sgqa|shown|type|valueNAOK|value'; + static $RDP_regex_var_attr = 'code|gid|grelevance|gseq|jsName|mandatory|NAOK|qid|qseq|question|readWrite|relevanceStatus|relevance|rowdivid|sgqa|shown|type|valueNAOK|value'; // These three variables are effectively static once constructed private $RDP_ExpressionRegex; @@ -80,9 +80,9 @@ function __construct() $RDP_regex_inc_dec = '\+\+|--'; $RDP_regex_binary = '[+*/-]'; $RDP_regex_compare = '<=|<|>=|>|==|!=|\ble\b|\blt\b|\bge\b|\bgt\b|\beq\b|\bne\b'; - $RDP_regex_assign = '=|\+=|-=|\*=|/='; + $RDP_regex_assign = '='; // '=|\+=|-=|\*=|/='; $RDP_regex_sgqa = '(?:INSERTANS:)?[0-9]+X[0-9]+X[0-9]+[A-Z0-9_]*\#?[01]?(?:\.(?:' . ExpressionManager::$RDP_regex_var_attr . '))?'; - $RDP_regex_word = '(?:TOKEN:)?(?:[A-Z][A-Z0-9_]*)?(?:\.(?:' . ExpressionManager::$RDP_regex_var_attr . '))?'; + $RDP_regex_word = '(?:TOKEN:)?(?:[A-Z][A-Z0-9_]*)?(?:\.(?:[A-Z][A-Z0-9_]*))*(?:\.(?:' . ExpressionManager::$RDP_regex_var_attr . '))?'; $RDP_regex_number = '[0-9]+\.?[0-9]*|\.[0-9]+'; $RDP_regex_andor = '\band\b|\bor\b|&&|\|\|'; $RDP_regex_lcb = '{'; @@ -163,6 +163,8 @@ function __construct() 'checkdate' => array('checkdate', 'checkdate', $this->gT('Returns true(1) if it is a valid date in gregorian calendar'), 'bool checkdate(month,day,year)', 'http://www.php.net/manual/en/function.checkdate.php', 3), 'cos' => array('cos', 'Math.cos', $this->gT('Cosine'), 'number cos(number)', 'http://www.php.net/manual/en/function.cos.php', 1), 'count' => array('exprmgr_count', 'LEMcount', $this->gT('Count the number of answered questions in the list'), 'number count(arg1, arg2, ... argN)', '', -1), +'countif' => array('exprmgr_countif', 'LEMcountif', $this->gT('Count the number of answered questions in the list equal the first argument'), 'number countif(matches, arg1, arg2, ... argN)', '', -2), +'countifop' => array('exprmgr_countifop', 'LEMcountifop', $this->gT('Count the number of answered questions in the list which pass the critiera (arg op value)'), 'number countifop(op, value, arg1, arg2, ... argN)', '', -3), 'date' => array('date', 'date', $this->gT('Format a local date/time'), 'string date(format [, timestamp=time()])', 'http://www.php.net/manual/en/function.date.php', 1,2), 'exp' => array('exp', 'Math.exp', $this->gT('Calculates the exponent of e'), 'number exp(number)', 'http://www.php.net/manual/en/function.exp.php', 1), 'fixnum' => array('exprmgr_fixnum', 'LEMfixnum', $this->gT('Display numbers with comma as decimal separator, if needed'), 'string fixnum(number)', '', 1), @@ -221,6 +223,7 @@ function __construct() 'strtoupper' => array('strtoupper', 'LEMstrtoupper', $this->gT('Make a string uppercase'), 'string strtoupper(string)', 'http://www.php.net/manual/en/function.strtoupper.php', 1), 'substr' => array('substr', 'substr', $this->gT('Return part of a string'), 'string substr(string, start [, length])', 'http://www.php.net/manual/en/function.substr.php', 2,3), 'sum' => array('array_sum', 'LEMsum', $this->gT('Calculate the sum of values in an array'), 'number sum(arg1, arg2, ... argN)', '', -2), +'sumifop' => array('exprmgr_sumifop', 'LEMsumifop', $this->gT('Sum the values of answered questions in the list which pass the critiera (arg op value)'), 'number sumifop(op, value, arg1, arg2, ... argN)', '', -3), 'tan' => array('tan', 'Math.tan', $this->gT('Tangent'), 'number tan(arg)', 'http://www.php.net/manual/en/function.tan.php', 1), 'time' => array('time', 'time', $this->gT('Return current UNIX timestamp'), 'number time()', 'http://www.php.net/manual/en/function.time.php', 0), 'trim' => array('trim', 'trim', $this->gT('Strip whitespace (or other characters) from the beginning and end of a string'), 'string trim(string [, charlist])', 'http://www.php.net/manual/en/function.trim.php', 1,2), @@ -1310,7 +1313,10 @@ public function GetJavaScriptEquivalentOfExpression() { if (!preg_match("/^.*\.(NAOK|relevanceStatus)$/", $var)) { - $nonNAvarsUsed[] = $var; + if ($this->GetVarAttribute($var,'jsName','') != '') + { + $nonNAvarsUsed[] = $var; + } } } $mainClause = implode('', $stringParts); @@ -1752,6 +1758,7 @@ public function ProcessBooleanExpression($expr,$groupSeq=-1,$questionSeq=-1) $this->groupSeq = $groupSeq; $this->questionSeq = $questionSeq; + $expr = $this->ExpandThisVar($expr); $status = $this->RDP_Evaluate($expr); if (!$status) { return false; // if there are errors in the expression, hide it? @@ -1820,6 +1827,7 @@ public function sProcessStringContainingExpressions($src, $questionNum=0, $numRe $this->groupSeq = $groupSeq; $result = $src; $prettyPrint = ''; + $errors = array(); for($i=1;$i<=$numRecursionLevels;++$i) { @@ -1829,8 +1837,10 @@ public function sProcessStringContainingExpressions($src, $questionNum=0, $numRe { $prettyPrint = $this->prettyPrintSource; } + $errors = array_merge($errors, $this->RDP_errs); } $this->prettyPrintSource = $prettyPrint; // ensure that if doing recursive substition, can get original source to pretty print + $this->RDP_errs = $errors; return $result; } @@ -1858,7 +1868,8 @@ public function sProcessStringContainingExpressionsHelper($src, $questionNum, $s } else { ++$this->substitutionNum; - if ($this->RDP_Evaluate(substr($stringPart[0],1,-1))) + $expr = $this->ExpandThisVar(substr($stringPart[0],1,-1)); + if ($this->RDP_Evaluate($expr)) { $resolvedPart = $this->GetResult(); } @@ -1886,7 +1897,7 @@ public function sProcessStringContainingExpressionsHelper($src, $questionNum, $s 'raw' => $stringPart[0], 'result' => $resolvedPart, 'vars' => implode('|',$jsVarsUsed), - 'js' => $this->GetJavaScriptFunctionForReplacement($questionNum, $idName, substr($stringPart[0],1,-1)), + 'js' => $this->GetJavaScriptFunctionForReplacement($questionNum, $idName, $expr), ); } else @@ -1901,6 +1912,30 @@ public function sProcessStringContainingExpressionsHelper($src, $questionNum, $s return $result; // recurse in case there are nested ones, avoiding infinite loops? } + /** + * If the equation contains refernece to this, expand to comma separated list if needed. + * @param type $eqn + */ + function ExpandThisVar($src) + { + $splitter = '(?:\b(?:self|that))(?:\.(?:[A-Z0-9_]+))*'; + $parts = preg_split("/(" . $splitter . ")/i",$src,-1,(PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)); + $result = ''; + foreach ($parts as $part) + { + if (preg_match("/" . $splitter . "/",$part)) + { + $result .= LimeExpressionManager::GetAllVarNamesForQ($this->questionSeq,$part); + } + else + { + $result .= $part; + } + } + + return $result; + } + /** * Get info about all elements needed for dynamic tailoring * @return @@ -3125,6 +3160,7 @@ static function UnitTestEvaluator() $pre .= "\n\n"; print $pre; @@ -3215,6 +3251,92 @@ function exprmgr_count($args) return $j; } +/** + * Count the number of answered questions (non-empty) which match the first argument + * @param $args + * @return int + */ +function exprmgr_countif($args) +{ + $j=0; // keep track of how many non-null values seen + $match = array_shift($args); + foreach ($args as $arg) + { + if ($arg == $match) { + ++$j; + } + } + return $j; +} + +/** + * Count the number of answered questions (non-empty) which meet the criteria (arg op value) + * @param $args + * @return int + */ +function exprmgr_countifop($args) +{ + $j=0; + $op = array_shift($args); + $value = array_shift($args); + foreach ($args as $arg) + { + switch($op) + { + case '==': case 'eq': if ($arg == $value) { ++$j; } break; + case '>=': case 'ge': if ($arg >= $value) { ++$j; } break; + case '>': case 'gt': if ($arg > $value) { ++$j; } break; + case '<=': case 'le': if ($arg <= $value) { ++$j; } break; + case '<': case 'lt': if ($arg < $value) { ++$j; } break; + case '!=': case 'ne': if ($arg != $value) { ++$j; } break; + case 'RX': + try { + if (@preg_match($value, $arg)) + { + ++$j; + } + } + catch (Exception $e) { } + break; + } + } + return $j; +} + +/** + * Sum of values of answered questions which meet the criteria (arg op value) + * @param $args + * @return int + */ +function exprmgr_sumifop($args) +{ + $result=0; + $op = array_shift($args); + $value = array_shift($args); + foreach ($args as $arg) + { + switch($op) + { + case '==': case 'eq': if ($arg == $value) { $result += $arg; } break; + case '>=': case 'ge': if ($arg >= $value) { $result += $arg; } break; + case '>': case 'gt': if ($arg > $value) { $result += $arg; } break; + case '<=': case 'le': if ($arg <= $value) { $result += $arg; } break; + case '<': case 'lt': if ($arg < $value) { $result += $arg; } break; + case '!=': case 'ne': if ($arg != $value) { $result += $arg; } break; + case 'RX': + try { + if (@preg_match($value, $arg)) + { + $result += $arg; + } + } + catch (Exception $e) { } + break; + } + } + return $result; +} + /** * If $test is true, return $ok, else return $error * @param $test diff --git a/application/helpers/expressions/em_manager_helper.php b/application/helpers/expressions/em_manager_helper.php index 24f2531534b..e480fac0816 100644 --- a/application/helpers/expressions/em_manager_helper.php +++ b/application/helpers/expressions/em_manager_helper.php @@ -630,6 +630,11 @@ class LimeExpressionManager { * @var type */ private $qid2exclusiveAuto = array(); + /** + * Array of values to be updated + * @var type + */ + private $updatedValues = array(); /** * A private constructor; prevents direct creation of object @@ -814,6 +819,7 @@ public static function ConvertConditionsToRelevance($surveyId=NULL, $qid=NULL) $_qid = $row['qid']; $_scenario = $row['scenario']; $_cqid = $row['cqid']; + $_subqid = -1; $relAndList = array(); $relOrList = array(); $scenarios = array(); @@ -830,24 +836,34 @@ public static function ConvertConditionsToRelevance($surveyId=NULL, $qid=NULL) $relOrList = array(); $_scenario = $row['scenario']; $_cqid = $row['cqid']; + $_subqid = -1; } if ($row['cqid'] != $_cqid) { $relAndList[] = '(' . implode(' or ', $relOrList) . ')'; $relOrList = array(); $_cqid = $row['cqid']; + $_subqid = -1; } // fix fieldnames if ($row['class'] == '') { $fieldname = substr($row['cfieldname'],1,-1); // {TOKEN:xxxx} + $subqid = $fieldname; $value = $row['value']; } else { $q = createQuestion($row['class']); $newrow = $q->prepareConditions($row); $fieldname = $newrow['cfieldname'] . '.NAOK'; $value = $newrow['matchvalue']; + $subqid = $newrow['subqid']; + } + if ($_subqid != -1 && $_subqid != $subqid) + { + $relAndList[] = '(' . implode(' or ', $relOrList) . ')'; + $relOrList = array(); } + $_subqid = $subqid; // fix values if (preg_match('/^@\d+X\d+X\d+.*@$/',$value)) { @@ -874,7 +890,7 @@ public static function ConvertConditionsToRelevance($surveyId=NULL, $qid=NULL) else { // Conditions uses ' ' to mean not answered, but internally it is really stored as ''. Fix this - if ($value === '" "') { + if ($value === '" "' || $value == '""') { if ($row['method'] == '==') { $relOrList[] = "is_empty(" . $fieldname . ")"; @@ -1049,7 +1065,24 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) $cascadedAFE = array_reverse($cascadedAFE); $subqs = $qinfo['subqs']; + if ($type == 'R') { + $subqs = array(); + foreach ($this->qans[$qinfo['qid']] as $k=>$v) + { + $_code = explode('~',$k); + $subqs[] = array( + 'rowdivid'=>$qinfo['sgqa'] . $_code[1], + 'sqsuffix'=>'_' . $_code[1], + ); + } + } + $last_rowdivid = '--'; foreach ($subqs as $sq) { + if ($sq['rowdivid'] == $last_rowdivid) + { + continue; + } + $last_rowdivid = $sq['rowdivid']; $af_names = array(); $afe_names = array(); switch ($type) @@ -1067,46 +1100,129 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) case 'P': //Multiple choice with comments checkbox + text case 'K': //MULTIPLE NUMERICAL QUESTION case 'Q': //MULTIPLE SHORT TEXT - if ($this->sgqaNaming) - { +// case 'R': //Ranking +// if ($this->sgqaNaming) +// { foreach ($cascadedAF as $_caf) { $sgq = ((isset($this->qcode2sgq[$_caf])) ? $this->qcode2sgq[$_caf] : $_caf); - $sgq .= substr($sq['sqsuffix'],1); - if (isset($this->knownVars[$sgq])) + $fqid = explode('X',$sgq); + if (!isset($fqid[2])) { - $af_names[] = $sgq . '.NAOK'; + continue; } + $fqid = $fqid[2]; + if ($this->q2subqInfo[$fqid]['type'] == 'R') + { + $rankables = array(); + foreach ($this->qans[$fqid] as $k=>$v) + { + $rankable = explode('~',$k); + $rankables[] = '_' . $rankable[1]; } - foreach ($cascadedAFE as $_cafe) + if (array_search($sq['sqsuffix'],$rankables) === false) { - $sgq = ((isset($this->qcode2sgq[$_cafe])) ? $this->qcode2sgq[$_cafe] : $_cafe); - $sgq .= substr($sq['sqsuffix'],1); - if (isset($this->knownVars[$sgq])) + continue; + } + } + $fsqs = array(); + foreach ($this->q2subqInfo[$fqid]['subqs'] as $fsq) { - $afe_names[] = $sgq . '.NAOK'; + if ($this->q2subqInfo[$fqid]['type'] == 'R') + { + // we know the suffix exists + $fsqs[] = '(' . $sgq . $fsq['csuffix'] . ".NAOK == '" . substr($sq['sqsuffix'],1) . "')"; } + else if ($this->q2subqInfo[$fqid]['type'] == ':' && isset($this->qattr[$fqid]['multiflexible_checkbox']) && $this->qattr[$fqid]['multiflexible_checkbox']=='1') + { + if ($fsq['sqsuffix'] == $sq['sqsuffix']) + { + $fsqs[] = $sgq . $fsq['csuffix'] . '.NAOK=="1"'; } } else { - foreach ($cascadedAF as $_caf) + if ($fsq['sqsuffix'] == $sq['sqsuffix']) { - $sgq = $_caf . $sq['sqsuffix']; - if (isset($this->knownVars[$sgq])) + $fsqs[] = '!is_empty(' . $sgq . $fsq['csuffix'] . '.NAOK)'; + } + } + } + if (count($fsqs) > 0) { - $af_names[] = $sgq . '.NAOK'; + $af_names[] = '(' . implode(' or ', $fsqs) . ')'; } } foreach ($cascadedAFE as $_cafe) { - $sgq = $_cafe . $sq['sqsuffix']; - if (isset($this->knownVars[$sgq])) + $sgq = ((isset($this->qcode2sgq[$_cafe])) ? $this->qcode2sgq[$_cafe] : $_cafe); + $fqid = explode('X',$sgq); + if (!isset($fqid[2])) { - $afe_names[] = $sgq . '.NAOK'; + continue; } + $fqid = $fqid[2]; + if ($this->q2subqInfo[$fqid]['type'] == 'R') + { + $rankables = array(); + foreach ($this->qans[$fqid] as $k=>$v) + { + $rankable = explode('~',$k); + $rankables[] = '_' . $rankable[1]; } + if (array_search($sq['sqsuffix'],$rankables) === false) + { + continue; } + } + $fsqs = array(); + foreach ($this->q2subqInfo[$fqid]['subqs'] as $fsq) + { + if ($this->q2subqInfo[$fqid]['type'] == 'R') + { + // we know the suffix exists + $fsqs[] = '(' . $sgq . $fsq['csuffix'] . ".NAOK != '" . substr($sq['sqsuffix'],1) . "')"; + } + else if ($this->q2subqInfo[$fqid]['type'] == ':' && isset($this->qattr[$fqid]['multiflexible_checkbox']) && $this->qattr[$fqid]['multiflexible_checkbox']=='1') + { + if ($fsq['sqsuffix'] == $sq['sqsuffix']) + { + $fsqs[] = $sgq . $fsq['csuffix'] . '.NAOK!="1"'; + } + } + else + { + if ($fsq['sqsuffix'] == $sq['sqsuffix']) + { + $fsqs[] = 'is_empty(' . $sgq . $fsq['csuffix'] . '.NAOK)'; + } + } + } + if (count($fsqs) > 0) + { + $afe_names[] = '(' . implode(' and ', $fsqs) . ')'; + } + } +// } +// else // TODO - implement qcode naming for this +// { +// foreach ($cascadedAF as $_caf) +// { +// $sgq = $_caf . $sq['sqsuffix']; +// if (isset($this->knownVars[$sgq])) +// { +// $af_names[] = $sgq . '.NAOK'; +// } +// } +// foreach ($cascadedAFE as $_cafe) +// { +// $sgq = $_cafe . $sq['sqsuffix']; +// if (isset($this->knownVars[$sgq])) +// { +// $afe_names[] = $sgq . '.NAOK'; +// } +// } +// } break; default: break; @@ -1118,7 +1234,7 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) $afs_eqn = ''; if (count($af_names) > 0) { - $afs_eqn .= implode(' != "" && ', $af_names) . ' != ""'; + $afs_eqn .= implode(' && ', $af_names); } if (count($afe_names) > 0) { @@ -1126,7 +1242,7 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) { $afs_eqn .= ' && '; } - $afs_eqn .= implode(' == "" && ', array_unique($afe_names)) . ' == ""'; + $afs_eqn .= implode(' && ', $afe_names); } $subQrels[] = array( @@ -1250,8 +1366,16 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) } switch ($type) { + case ':': //ARRAY (Multi Flexi) 1 to 10 + case 'A': //ARRAY (5 POINT CHOICE) radio-buttons + case 'B': //ARRAY (10 POINT CHOICE) radio-buttons + case 'C': //ARRAY (YES/UNCERTAIN/NO) radio-buttons + case 'E': //ARRAY (Increase/Same/Decrease) radio-buttons + case 'F': //ARRAY (Flexible) - Row Format case 'M': //Multiple choice checkbox case 'P': //Multiple choice with comments checkbox + text + case 'K': //MULTIPLE NUMERICAL QUESTION + case 'Q': //MULTIPLE SHORT TEXT if ($this->sgqaNaming) { $sq_name = $qinfo['sgqa'] . trim($exclusive_option) . '.NAOK'; @@ -1269,7 +1393,7 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) 'qtype' => $type, 'type' => 'exclude_all_others', 'rowdivid' => $sq['rowdivid'], - 'eqn' => '(' . $sq_name . ' == "")', + 'eqn' => 'is_empty(' . $sq_name . ')', 'qid' => $questionNum, 'sgqa' => $qinfo['sgqa'], ); @@ -1298,6 +1422,7 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) switch ($type) { case 'M': //Multiple choice checkbox + case 'P': //Multiple choice with comments checkbox + text if ($this->sgqaNaming) { $sq_name = substr($sq['jsVarName'],4); @@ -1325,7 +1450,7 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) if (count($sq_names) > 0) { $relpart = "sum(" . implode(".relevanceStatus, ", $sq_names) . ".relevanceStatus)"; $checkedpart = "count(" . implode(".NAOK, ", $sq_names) . ".NAOK)"; - $eoRelevantAndUnchecked = "(" . $eoVarName . ".relevanceStatus && " . $eoVarName . "=='')"; + $eoRelevantAndUnchecked = "(" . $eoVarName . ".relevanceStatus && is_empty(" . $eoVarName . "))"; $eoEqn = "(" . $eoRelevantAndUnchecked . " && (" . $relpart . " == " . $checkedpart . "))"; $this->em->ProcessBooleanExpression($eoEqn, $qinfo['gseq'], $qinfo['qseq']); @@ -1391,6 +1516,7 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) case 'K': //MULTIPLE NUMERICAL QUESTION case 'Q': //MULTIPLE SHORT TEXT case 'M': //Multiple choice checkbox + case 'R': //RANKING STYLE if ($this->sgqaNaming) { $sq_name = substr($sq['jsVarName'],4) . '.NAOK'; @@ -1412,10 +1538,6 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) } } break; - case 'R': //RANKING STYLE - // TODO - does not have sub-questions, so how should this be done? - // Current JavaScript works fine, but can't use expression value - break; default: break; } @@ -1432,7 +1554,7 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) 'qtype' => $type, 'type' => 'min_answers', 'class' => 'num_answers', - 'eqn' => '(count(' . implode(', ', $sq_names) . ') >= (' . $min_answers . '))', + 'eqn' => 'if(is_empty('.$min_answers.'),1,(count(' . implode(', ', $sq_names) . ') >= (' . $min_answers . ')))', 'qid' => $questionNum, ); } @@ -1480,6 +1602,7 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) case 'K': //MULTIPLE NUMERICAL QUESTION case 'Q': //MULTIPLE SHORT TEXT case 'M': //Multiple choice checkbox + case 'R': //RANKING STYLE if ($this->sgqaNaming) { $sq_name = substr($sq['jsVarName'],4) . '.NAOK'; @@ -1501,10 +1624,6 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) } } break; - case 'R': //RANKING STYLE - // TODO - does not have sub-questions, so how should this be done? - // Current JavaScript works fine, but can't use expression value - break; default: break; } @@ -1521,7 +1640,7 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) 'qtype' => $type, 'type' => 'max_answers', 'class' => 'num_answers', - 'eqn' => '(count(' . implode(', ', $sq_names) . ') <= (' . $max_answers . '))', + 'eqn' => '(if(is_empty('.$max_answers.'),1,count(' . implode(', ', $sq_names) . ') <= (' . $max_answers . ')))', 'qid' => $questionNum, ); } @@ -2005,13 +2124,12 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) $sgqa = $qinfo['sgqa']; switch ($type) { - // TODO oddly, the other field has value of 0 when empty instead of "", so cheating and looking for strlen > 1 case '!': //List - dropdown case 'L': //LIST drop-down/radio-button list - $eqn = "(" . $sgqa . ".NAOK!='-oth-' || (" . $sgqa . ".NAOK=='-oth-' && strlen(trim(" . $sgqa . "other.NAOK))>1))"; + $eqn = "(" . $sgqa . ".NAOK!='-oth-' || (" . $sgqa . ".NAOK=='-oth-' && !is_empty(trim(" . $sgqa . "other.NAOK))))"; break; case 'P': //Multiple choice with comments checkbox + text - $eqn = "(is_empty(trim(" . $sgqa . "other.NAOK)) || (!is_empty(trim(" . $sgqa . "other.NAOK)) && strlen(trim(" . $sgqa . "othercomment.NAOK))>1))"; + $eqn = "(is_empty(trim(" . $sgqa . "other.NAOK)) || (!is_empty(trim(" . $sgqa . "other.NAOK)) && !is_empty(trim(" . $sgqa . "othercomment.NAOK))))"; break; default: break; @@ -2159,11 +2277,19 @@ public function _CreateSubQLevelRelevanceAndValidationEqns($onlyThisQseq=NULL) $sq_name = NULL; switch ($type) { + case 'A': //ARRAY (5 POINT CHOICE) radio-buttons + case 'B': //ARRAY (10 POINT CHOICE) radio-buttons + case 'C': //ARRAY (YES/UNCERTAIN/NO) radio-buttons + case 'E': //ARRAY (Increase/Same/Decrease) radio-buttons + case 'F': //ARRAY (Flexible) - Row Format case 'K': //MULTIPLE NUMERICAL QUESTION case 'Q': //MULTIPLE SHORT TEXT case ';': //ARRAY (Multi Flexi) Text case ':': //ARRAY (Multi Flexi) 1 to 10 + case 'M': //Multiple choice checkbox case 'N': //NUMERICAL QUESTION TYPE + case 'P': //Multiple choice with comments checkbox + text + case 'R': //RANKING STYLE case 'S': //SHORT FREE TEXT case 'T': //LONG FREE TEXT case 'U': //HUGE FREE TEXT @@ -2776,7 +2902,7 @@ private function setVariableAndTokenMappingsForExpressionManager($surveyid,$forc } $this->qid2code[$questionNum] = $codeList; - $readWrite = 'N'; + $readWrite = 'Y'; $ansArray = $q->getAnswerArray($this); @@ -2846,7 +2972,7 @@ private function setVariableAndTokenMappingsForExpressionManager($surveyid,$forc $varName = $q->title . '_' . $q->aid; $question = $q->sq; // $question = $q->text . ': ' . $q->sq; - if ($type != 'H' && $type != 'R') { + if ($type != 'H') { if ($type == 'P' && preg_match("/comment$/", $sgqa)) { // $rowdivid = substr($sgqa,0,-7); } @@ -2901,7 +3027,7 @@ private function setVariableAndTokenMappingsForExpressionManager($surveyid,$forc switch($type) { case 'R': //RANKING STYLE - $jsVarName_on = 'fvalue_' . $fieldNameParts[2]; + $jsVarName_on = 'answer' . $sgqa; $jsVarName = 'java' . $sgqa; break; case 'D': //DATE @@ -3577,6 +3703,133 @@ static function GetLastPrettyPrintExpression() return $LEM->em->GetLastPrettyPrintExpression(); } + /** + * Expand "self.suffix" and "that.qcode.suffix" into canonical list of variable names + * @param type $qseq + * @param type $varname + */ + static function GetAllVarNamesForQ($qseq,$varname) + { + $LEM =& LimeExpressionManager::singleton(); + + $parts = explode('.',$varname); + $qroot = ''; + $suffix = ''; + $sqpatts = array(); + $nosqpatts = array(); + $sqpatt = ''; + $nosqpatt = ''; + $comments = ''; + + if ($parts[0] == 'self') + { + $type = 'self'; + } + else + { + $type = 'that'; + array_shift($parts); + if (isset($parts[0])) + { + $qroot = $parts[0]; + } + else + { + return $varname; + } + } + array_shift($parts); + + if (count($parts) > 0) + { + if (preg_match('/^' . ExpressionManager::$RDP_regex_var_attr . '$/',$parts[count($parts)-1])) + { + $suffix = '.' . $parts[count($parts)-1]; + array_pop($parts); + } + } + + foreach($parts as $part) + { + if ($part == 'nocomments') + { + $comments = 'N'; + } + else if ($part == 'comments') + { + $comments = 'Y'; + } + else if (preg_match('/^sq_.+$/',$part)) + { + $sqpatts[] = substr($part,3); + } + else if (preg_match('/^nosq_.+$/',$part)) + { + $nosqpatts[] = substr($part,5); + } + else + { + return $varname; // invalid + } + } + $sqpatt = implode('|',$sqpatts); + $nosqpatt = implode('|',$nosqpatts); + $vars = array(); + + foreach ($LEM->knownVars as $kv) + { + if ($type == 'self') + { + if (!isset($kv['qseq']) || $kv['qseq'] != $qseq || trim($kv['sgqa']) == '') + { + continue; + } + } + else + { + if (!isset($kv['rootVarName']) || $kv['rootVarName'] != $qroot) + { + continue; + } + } + if ($comments != '') + { + if ($comments == 'Y' && !preg_match('/comment$/',$kv['sgqa'])) + { + continue; + } + if ($comments == 'N' && preg_match('/comment$/',$kv['sgqa'])) + { + continue; + } + } + $sgq = $LEM->sid . 'X' . $kv['gid'] . 'X' . $kv['qid']; + $ext = substr($kv['sgqa'],strlen($sgq)); + + if ($sqpatt != '') + { + if (!preg_match('/'.$sqpatt.'/',$ext)) + { + continue; + } + } + if ($nosqpatt != '') + { + if (preg_match('/'.$nosqpatt.'/',$ext)) + { + continue; + } + } + + $vars[] = $kv['sgqa'] . $suffix; + } + if (count($vars) > 0) + { + return implode(',',$vars); + } + return $varname; // invalid + } + /** * Should be first function called on each page - sets/clears internally needed variables * @param $allOnOnePage - true if StartProcessingGroup will be called multiple times on this page - does some optimizatinos @@ -3594,6 +3847,11 @@ static function StartProcessingPage($allOnOnePage=false,$initializeVars=false) $LEM->surveyOptions['hyperlinkSyntaxHighlighting']=true; // this will be temporary - should be reset in running survey $LEM->qid2exclusiveAuto=array(); + $surveyinfo = (isset($LEM->sid) ? getSurveyInfo($LEM->sid) : null); + if (isset($surveyinfo['assessments']) && $surveyinfo['assessments']=='Y') + { + $LEM->surveyOptions['assessments']=true; + } // $LEM->runtimeTimings[] = array(__METHOD__,(microtime(true) - $now)); $LEM->initialized=true; @@ -3673,8 +3931,63 @@ static function StartSurvey($surveyid,$surveyMode='group',$options=NULL,$forceRe if (isset($_SESSION[$LEM->sessid]['startingValues']) && is_array($_SESSION[$LEM->sessid]['startingValues']) && count($_SESSION[$LEM->sessid]['startingValues']) > 0) { - $startingValues = $_SESSION[$LEM->sessid]['startingValues']; - $LEM->_UpdateValuesInDatabase($startingValues); + $startingValues = array(); + foreach ($_SESSION[$LEM->sessid]['startingValues'] as $k=>$value) + { + if (isset($LEM->knownVars[$k])) + { + $knownVar = $LEM->knownVars[$k]; + } + else if (isset($LEM->qcode2sgqa[$k])) + { + $knownVar = $LEM->knownVars[$LEM->qcode2sgqa[$k]]; + } + else if (isset($LEM->tempVars[$k])) + { + $knownVar = $LEM->tempVar[$k]; + } + else + { + continue; + } + if (!isset($knownVar['jsName'])) + { + continue; + } + switch ($knownVar['type']) + { + case 'D': //DATE + if (trim($value)=="") + { + $value = NULL; + } + else + { + $dateformatdatat=getDateFormatData($LEM->surveyOptions['surveyls_dateformat']); + $datetimeobj = new Date_Time_Converter($value, $dateformatdatat['phpdate']); + $value=$datetimeobj->convert("Y-m-d"); + } + break; + case 'N': //NUMERICAL QUESTION TYPE + case 'K': //MULTIPLE NUMERICAL QUESTION + if (trim($value)=="") { + $value = NULL; + } + else { + $value = sanitize_float($value); + } + break; + case '|': //File Upload + $value=NULL; // can't upload a file via GET + break; + } + $_SESSION[$LEM->sessid][$knownVar['sgqa']] = $value; + $LEM->updatedValues[$knownVar['sgqa']]=array( + 'type'=>$knownVar['type'], + 'value'=>$value, + ); + } + $LEM->_UpdateValuesInDatabase(NULL); } return array( @@ -3689,6 +4002,7 @@ static function NavigateBackwards() $LEM =& LimeExpressionManager::singleton(); $LEM->ParseResultCache=array(); // to avoid running same test more than once for a given group + $LEM->updatedValues = array(); switch ($LEM->surveyMode) { @@ -3821,6 +4135,7 @@ static function NavigateForwards($force=false) { $LEM =& LimeExpressionManager::singleton(); $LEM->ParseResultCache=array(); // to avoid running same test more than once for a given group + $LEM->updatedValues = array(); switch ($LEM->surveyMode) { @@ -4038,6 +4353,9 @@ static function NavigateForwards($force=false) { */ private function _UpdateValuesInDatabase($updatedValues, $finished=false) { + // TODO - now that using $this->updatedValues, may be able to remove local copies of it (unless needed by other sub-systems) + $updatedValues = $this->updatedValues; + $message = ''; $_SESSION[$this->sessid]['datestamp']=dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i:s", $this->surveyOptions['timeadjust']); if ($this->surveyOptions['active'] && !isset($_SESSION[$this->sessid]['srid'])) @@ -4142,6 +4460,12 @@ private function _UpdateValuesInDatabase($updatedValues, $finished=false) } // otherwise will already be in yyyy-mm-dd format after ProcessCurrentResponses() break; + case '|': //File upload + // This block can be removed once we require 5.3 or later + if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) { + $val=addslashes($val); + } + break; case 'N': //NUMERICAL QUESTION TYPE case 'K': //MULTIPLE NUMERICAL QUESTION if (trim($val)=='') { @@ -4270,6 +4594,7 @@ static function JumpTo($seq,$preview=false,$processPOST=true,$force=false,$chang } $LEM->ParseResultCache=array(); // to avoid running same test more than once for a given group + $LEM->updatedValues = array(); --$seq; // convert to 0-based numbering switch ($LEM->surveyMode) @@ -4380,8 +4705,10 @@ static function JumpTo($seq,$preview=false,$processPOST=true,$force=false,$chang else { // display new group + if(!$preview){ // Save only if not in preview mode $message .= $LEM->_UpdateValuesInDatabase($updatedValues,false); $LEM->runtimeTimings[] = array(__METHOD__,(microtime(true) - $now)); + } $LEM->lastMoveResult = array( 'finished'=>false, 'message'=>$message, @@ -5362,6 +5689,7 @@ function _ValidateQuestion($questionSeq) { $_SESSION[$LEM->sessid][$sgqa] = NULL; $updatedValues[$sgqa] = NULL; + $LEM->updatedValues[$sgqa] = NULL; } } else if ($qInfo['type'] == '*') @@ -5371,10 +5699,13 @@ function _ValidateQuestion($questionSeq) $sgqa = $LEM->qid2code[$qid]; // there will be only one, since Equation // Store the result of the Equation in the SESSION $_SESSION[$LEM->sessid][$sgqa] = $result; - $updatedValues[$sgqa] = array( + $_update = array( 'type'=>'*', 'value'=>$result, ); + $updatedValues[$sgqa] = $_update; + $LEM->updatedValues[$sgqa] = $_update; + if (($LEM->debugLevel & LEM_DEBUG_VALIDATION_DETAIL) == LEM_DEBUG_VALIDATION_DETAIL) { $prettyPrintEqn = $LEM->em->GetPrettyPrintString(); @@ -5386,6 +5717,7 @@ function _ValidateQuestion($questionSeq) // NULL irrelevant sub-questions $_SESSION[$LEM->sessid][$sq] = NULL; $updatedValues[$sq] = NULL; + $LEM->updatedValues[$sq]= NULL; } // Regardless of whether relevant or hidden, if there is a default value and $_SESSION[$LEM->sessid][$sgqa] is NULL, then use the default value in $_SESSION, but don't write to database @@ -5787,14 +6119,14 @@ static function GetRelevanceAndTailoringJavaScript() $relChangeVars[] = " relChange" . $arg['qid'] . "=false;\n"; // detect change in relevance status - if (($relevance == '' || $relevance == '1') && count($tailorParts) == 0 && count($subqParts) == 0 && count($subqValidations) == 0 && count($validationEqns) == 0) + if (($relevance == '' || $relevance == '1' || ($arg['result'] == true && $arg['numJsVars']==0)) && count($tailorParts) == 0 && count($subqParts) == 0 && count($subqValidations) == 0 && count($validationEqns) == 0) { // Only show constitutively true relevances if there is tailoring that should be done. $relParts[] = "$('#relevance" . $arg['qid'] . "').val('1'); // always true\n"; $GalwaysRelevant[$arg['gseq']] = true; continue; } - $relevance = ($relevance == '') ? '1' : $relevance; + $relevance = ($relevance == '' || ($arg['result'] == true && $arg['numJsVars']==0)) ? '1' : $relevance; $relParts[] = "\nif (" . $relevance . ")\n{\n"; //////////////////////////////////////////////////////////////////////// // DO ALL ARRAY FILTERING FIRST - MAY AFFECT VALIDATION AND TAILORING // @@ -5805,6 +6137,7 @@ static function GetRelevanceAndTailoringJavaScript() * $afHide - if true, then use jQuery.show(). If false, then disable/enable the row */ $afHide = (isset($LEM->qattr[$arg['qid']]['array_filter_style']) ? ($LEM->qattr[$arg['qid']]['array_filter_style'] == '0') : true); + $inputSelector = (($arg['type'] == 'R') ? '' : ' :input:not(:hidden)'); foreach ($subqParts as $sq) { $rowdividList[$sq['rowdivid']] = $sq['result']; @@ -5816,15 +6149,15 @@ static function GetRelevanceAndTailoringJavaScript() } else { - $relParts[] = " $('#javatbd" . $sq['rowdivid'] . " :input:not(:hidden)').removeAttr('disabled');\n"; + $relParts[] = " $('#javatbd" . $sq['rowdivid'] . "$inputSelector').removeAttr('disabled');\n"; } if ($sq['isExclusiveJS'] != '') { $relParts[] = " if ( " . $sq['isExclusiveJS'] . " ) {\n"; - $relParts[] = " $('#javatbd" . $sq['rowdivid'] . " :input:not(:hidden)').attr('disabled','disabled');\n"; + $relParts[] = " $('#javatbd" . $sq['rowdivid'] . "$inputSelector').attr('disabled','disabled');\n"; $relParts[] = " }\n"; $relParts[] = " else {\n"; - $relParts[] = " $('#javatbd" . $sq['rowdivid'] . " :input:not(:hidden)').removeAttr('disabled');\n"; + $relParts[] = " $('#javatbd" . $sq['rowdivid'] . "$inputSelector').removeAttr('disabled');\n"; $relParts[] = " }\n"; } $relParts[] = " relChange" . $arg['qid'] . "=true;\n"; @@ -5835,23 +6168,23 @@ static function GetRelevanceAndTailoringJavaScript() if ($sq['irrelevantAndExclusiveJS'] != '') { $relParts[] = " if ( " . $sq['irrelevantAndExclusiveJS'] . " ) {\n"; - $relParts[] = " $('#javatbd" . $sq['rowdivid'] . " :input:not(:hidden)').attr('disabled','disabled');\n"; + $relParts[] = " $('#javatbd" . $sq['rowdivid'] . "$inputSelector').attr('disabled','disabled');\n"; $relParts[] = " }\n"; $relParts[] = " else {\n"; - $relParts[] = " $('#javatbd" . $sq['rowdivid'] . " :input:not(:hidden)').removeAttr('disabled');\n"; + $relParts[] = " $('#javatbd" . $sq['rowdivid'] . "$inputSelector').removeAttr('disabled');\n"; if ($afHide) { $relParts[] = " $('#javatbd" . $sq['rowdivid'] . "').hide();\n"; } else { - $relParts[] = " $('#javatbd" . $sq['rowdivid'] . " :input:not(:hidden)').attr('disabled','disabled');\n"; + $relParts[] = " $('#javatbd" . $sq['rowdivid'] . "$inputSelector').attr('disabled','disabled');\n"; } $relParts[] = " }\n"; } else { - $relParts[] = " $('#javatbd" . $sq['rowdivid'] . " :input:not(:hidden)').attr('disabled','disabled');\n"; + $relParts[] = " $('#javatbd" . $sq['rowdivid'] . "$inputSelector').attr('disabled','disabled');\n"; } } else @@ -5862,7 +6195,7 @@ static function GetRelevanceAndTailoringJavaScript() } else { - $relParts[] = " $('#javatbd" . $sq['rowdivid'] . " :input:not(:hidden)').attr('disabled','disabled');\n"; + $relParts[] = " $('#javatbd" . $sq['rowdivid'] . "$inputSelector').attr('disabled','disabled');\n"; } } $relParts[] = " relChange" . $arg['qid'] . "=true;\n"; @@ -5902,7 +6235,7 @@ static function GetRelevanceAndTailoringJavaScript() if ($_veq['subqValidSelector'] == '') { continue; } - $isValid = $LEM->em->ProcessBooleanExpression($_veq['subqValidEqn']); + $isValid = $LEM->em->ProcessBooleanExpression($_veq['subqValidEqn'],$arg['gseq'],$LEM->questionId2questionSeq[$arg['qid']]); $_sqValidVars = $LEM->em->GetJSVarsUsed(); $allJsVarsUsed = array_merge($allJsVarsUsed,$_sqValidVars); $valJsVarsUsed = array_merge($valJsVarsUsed,$_sqValidVars); @@ -5941,7 +6274,7 @@ static function GetRelevanceAndTailoringJavaScript() $_hasOtherValidation = true; } - $_isValid = $LEM->em->ProcessBooleanExpression($validationEqn); + $_isValid = $LEM->em->ProcessBooleanExpression($validationEqn,$arg['gseq'],$LEM->questionId2questionSeq[$arg['qid']]); $_vars = $LEM->em->GetJSVarsUsed(); $allJsVarsUsed = array_merge($allJsVarsUsed,$_vars); $valJsVarsUsed = array_merge($valJsVarsUsed,$_vars); @@ -6042,7 +6375,7 @@ static function GetRelevanceAndTailoringJavaScript() $relParts[] = " $('#question" . $arg['qid'] . "').hide();\n"; } else { - if (!($relevance == '' || $relevance == '1')) + if (!($relevance == '' || $relevance == '1' || ($arg['result'] == true && $arg['numJsVars']==0))) { // In such cases, PHP will make the question visible by default. By not forcing a re-show(), template.js can hide questions with impunity $relParts[] = " $('#question" . $arg['qid'] . "').show();\n"; @@ -6070,7 +6403,7 @@ static function GetRelevanceAndTailoringJavaScript() $relParts[] = " $('#relevance" . $arg['qid'] . "').val('1');\n"; $relParts[] = "}\n"; - if (!($relevance == '' || $relevance == '1')) + if (!($relevance == '' || $relevance == '1' || ($arg['result'] == true && $arg['numJsVars']==0))) { if (!isset($dynamicQinG[$arg['gseq']])) { @@ -6356,6 +6689,34 @@ static function GetRelevanceAndTailoringJavaScript() foreach ($undeclaredJsVars as $jsVar) { // TODO - is different type needed for text? Or process value to striphtml? + if ($jsVar == '') continue; + $jsParts[] = "\n"; + } + } + else + { + // For all-in-one mode, declare the always-hidden variables, since qanda will not be called for them. + foreach ($LEM->knownVars as $key=>$knownVar) + { + if (!is_numeric($key[0])) { + continue; + } + if ($knownVar['jsName'] == '') { + continue; + } + if ($knownVar['hidden']) + { + $jsVar = $knownVar['jsName']; + $undeclaredJsVars[] = $jsVar; + $sgqa = $knownVar['sgqa']; + $codeValue = (isset($_SESSION[$LEM->sessid][$sgqa])) ? $_SESSION[$LEM->sessid][$sgqa] : ''; + $undeclaredVal[$jsVar] = $codeValue; + } + } + + $undeclaredJsVars = array_unique($undeclaredJsVars); + foreach ($undeclaredJsVars as $jsVar) + { if ($jsVar == '') continue; $jsParts[] = "\n"; } @@ -6745,7 +7106,7 @@ public function gT($string) // eventually replace this with i8n if (isset(Yii::app()->lang)) { - return Yii::app()->lang->gT($string); + return htmlspecialchars(Yii::app()->lang->gT($string),ENT_QUOTES); } else { @@ -6802,8 +7163,17 @@ private static function getConditionsForEM($surveyid=NULL, $qid=NULL) ." from {{conditions}} as c" .", {{questions}} as q" ." where ". $where - ." c.cqid = 0 and c.qid = q.qid" - ." order by sid, qid, scenario, cqid, cfieldname, value"; + ." c.cqid = 0 and c.qid = q.qid"; + + $databasetype = Yii::app()->db->getDriverName(); + if ($databasetype=='mssql') + { + $query .= " order by sid, c.qid, scenario, cqid, cfieldname, value"; + } + else + { + $query .= " order by sid, qid, scenario, cqid, cfieldname, value"; + } $data = dbExecuteAssoc($query); @@ -6891,7 +7261,7 @@ private function getQuestionAttributesForEM($surveyid=NULL,$qid=NULL, $lang=NULL $databasetype = Yii::app()->db->getDriverName(); if ($databasetype=='mssql' || $databasetype=="sqlsrv") { - $query = "select distinct a.qid, a.attribute, CAST(a.value as varchar) as value"; + $query = "select distinct a.qid, a.attribute, CAST(a.value as varchar(max)) as value"; } else { @@ -7035,7 +7405,7 @@ static function ProcessCurrentResponses() $type = $qinfo['info']['type']; if ($relevant && $grelevant && $sqrelevant) { - if ($qinfo['info']['hidden']) + if ($qinfo['info']['hidden'] && !isset($_POST[$sq])) { $value = (isset($_SESSION['survey_'.$LEM->sessid][$sq]) ? $_SESSION['survey_'.$LEM->sessid][$sq] : ''); // if always hidden, use the default value, if any } @@ -7107,18 +7477,22 @@ static function ProcessCurrentResponses() break; } $_SESSION[$LEM->sessid][$sq] = $value; - $updatedValues[$sq] = array ( + $_update = array ( 'type'=>$type, 'value'=>$value, ); + $updatedValues[$sq] = $_update; + $LEM->updatedValues[$sq] = $_update; } else { // irrelevant, so database will be NULLed separately // Must unset the value, rather than setting to '', so that EM can re-use the default value as needed. unset($_SESSION[$LEM->sessid][$sq]); - $updatedValues[$sq] = array ( + $_update = array ( 'type'=>$type, 'value'=>NULL, ); + $updatedValues[$sq] = $_update; + $LEM->updatedValues[$sq] = $_update; } } } @@ -7443,38 +7817,61 @@ public static function SetVariableValue($op,$name,$value) $LEM->tempVars[$name]['code'] -= $value; break; } - return $LEM->tempVars[$name]['code']; + $_result = $LEM->tempVars[$name]['code']; + $_SESSION[$LEM->sessid][$name] = $_result; + $LEM->updatedValues[$name] = array( + 'type'=>'*', + 'value'=>$_result, + ); + return $_result; } else { - if (isset($LEM->knownVars[$name])) + if (!isset($LEM->knownVars[$name])) { - $vname = $name; + if (isset($LEM->qcode2sgqa[$name])) + { + $name = $LEM->qcode2sgqa[$name]; } - else if (isset($LEM->qcode2sgqa[$name])) + else { - $vname = $LEM->qcode2sgqa[$name]; + return ''; // shouldn't happen } + } + if (isset($_SESSION[$LEM->sessid][$name])) + { + $_result = $_SESSION[$LEM->sessid][$name]; + } + else + { + $_result = (isset($LEM->knownVars[$name]['default']) ? $LEM->knownVars[$name]['default'] : 0); + } switch($op) { case '=': - $LEM->knownVars[$name]['code'] = $value; + $_result = $value; break; case '*=': - $LEM->knownVars[$name]['code'] *= $value; + $_result *= $value; break; case '/=': - $LEM->knownVars[$name]['code'] /= $value; + $_result /= $value; break; case '+=': - $LEM->knownVars[$name]['code'] += $value; + $_result += $value; break; case '-=': - $LEM->knownVars[$name]['code'] -= $value; + $_result -= $value; break; } - return $LEM->knownVars[$name]['code']; + $_SESSION[$LEM->sessid][$name] = $_result; + $_type = $LEM->knownVars[$name]['type']; + $LEM->updatedValues[$name] = array( + 'type'=>$_type, + 'value'=>$_result, + ); + return $_result; } } @@ -7498,6 +7895,7 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL $LEM =& LimeExpressionManager::singleton(); $allErrors = array(); + $warnings = 0; $surveyOptions = array( 'assessments'=>$assessments, @@ -7529,8 +7927,6 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL $qtypes=getQuestionTypeList(); - templatereplace('{SITENAME}'); // to ensure that lime replacement fields loaded - if (is_null($moveResult) || is_null($LEM->currentQset) || count($LEM->currentQset) == 0) { return array( 'errors'=>1, @@ -7538,8 +7934,43 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL ); } - $out = "" - . "\n"; + $surveyname = templatereplace('{SURVEYNAME}'); + + $out = '

' . $LEM->gT('Logic File for Survey # ') . '[' . $LEM->sid . "]: $surveyname

\n"; + $out .= "
#".$LEM->gT('Name [ID]')."".$LEM->gT('Relevance [Validation] (Default)')."".$LEM->gT('Text [Help] (Tip)')."
"; + + if (is_null($gid) && is_null($qid)) + { + $description = templatereplace('{SURVEYDESCRIPTION}'); + $errClass = ($LEM->em->HasErrors() ? 'LEMerror' : ''); + if ($description != '') + { + $out .= ""; + } + + $welcome = templatereplace('{WELCOME}'); + $errClass = ($LEM->em->HasErrors() ? 'LEMerror' : ''); + if ($welcome != '') + { + $out .= ""; + } + + $endmsg = templatereplace('{ENDTEXT}'); + $errClass = ($LEM->em->HasErrors() ? 'LEMerror' : ''); + if ($endmsg != '') + { + $out .= ""; + } + + $_linkreplace = templatereplace('{URL}'); + $errClass = ($LEM->em->HasErrors() ? 'LEMerror' : ''); + if ($_linkreplace != '') + { + $out .= ""; + } + } + + $out .= "\n"; $_gseq=-1; foreach ($LEM->currentQset as $q) { @@ -7579,7 +8010,7 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL ////// // SHOW QUESTION-LEVEL INFO ////// - $mandatory = (($q['info']['mandatory']=='Y') ? "*" : ''); + $mandatory = (($q['info']['mandatory']=='Y') ? "*" : ''); $type = $q['info']['type']; $typedesc = $qtypes[$type]['description']; @@ -7617,7 +8048,7 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL $attrs['other'] = $LEM->questionSeq2relevance[$qseq]['other']; } if (count($attrs) > 0) { - $attrTable = "
" . $LEM->gT("Description:") . "" . $description . "
" . $LEM->gT("Welcome:") . "" . $welcome . "
" . $LEM->gT("End message:") . "" . $endmsg . "
" . $LEM->gT("End URL") . ":" . $_linkreplace . "
#".$LEM->gT('Name [ID]')."".$LEM->gT('Relevance [Validation] (Default)')."".$LEM->gT('Text [Help] (Tip)')."
\n"; + $attrTable = "
" . $LEM->gT("Question Attribute") . "" . $LEM->gT("Value"). "
\n"; $count=0; foreach ($attrs as $key=>$value) { if (is_null($value) || trim($value) == '') { @@ -7764,6 +8195,10 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL { ++$errorCount; } + else + { + ++$warnings; + } } ////// @@ -7807,9 +8242,6 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL $sgqa_len = strlen($sid . 'X'. $gid . 'X' . $qid); $varName = $rootVarName . '_' . substr($_rowdivid,$sgqa_len); } - case 'L': - // TODO - need to show array filters applied to lists - break; } if (is_null($rowdivid)) { continue; @@ -7869,10 +8301,26 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL $i=1; $_scale = $ansInfo[0]; } + + $subQeqn = ''; + $rowdivid = $sgqas[0] . $ansInfo[1]; + if ($q['info']['type'] == 'R') + { + $rowdivid = $LEM->sid . 'X' . $gid . 'X' . $qid . $ansInfo[1]; + } + if (isset($LEM->subQrelInfo[$qid][$rowdivid])) + { + $sq = $LEM->subQrelInfo[$qid][$rowdivid]; + $subQeqn = ' ' . $sq['prettyPrintEqn']; + if ($sq['hasErrors']) { + ++$errorCount; + } + } + $answerRows .= "" . "" . "" - . "" + . "" . "" . "\n"; } @@ -7899,7 +8347,7 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL else { $editlink = Yii::app()->getController()->createUrl('/admin/survey/view/surveyid/' . $LEM->sid . '/gid/' . $varNameError['gid'] . '/qid/' . $varNameError['qid']); - $questionRow .= "" . $rootVarName . ""; } @@ -7940,7 +8388,7 @@ static public function ShowSurveyLogicFile($sid, $gid=NULL, $qid=NULL,$LEMdebugL $message = $LEM->gT('This question, by itself, does not contain any syntax errors'); break; } - $out = "

$message

\n" . $out; + $out = "

$message

\n" . $out.""; } return array( @@ -8122,6 +8570,13 @@ static public function &ExcelSurveyExport($sid) } } + $surveyinfo = getSurveyInfo($sid); + $assessments = false; + if (isset($surveyinfo['assessments']) && $surveyinfo['assessments']=='Y') + { + $assessments = true; + } + foreach($langs as $lang) { if (trim($lang) == '') @@ -8129,7 +8584,7 @@ static public function &ExcelSurveyExport($sid) continue; } SetSurveyLanguage($sid,$lang); - LimeExpressionManager::StartSurvey($sid, 'survey', array('sgqaNaming'=>'N'), true); + LimeExpressionManager::StartSurvey($sid, 'survey', array('sgqaNaming'=>'N','assessments'=>$assessments), true); $moveResult = LimeExpressionManager::NavigateForwards(); $LEM =& LimeExpressionManager::singleton(); diff --git a/application/helpers/frontend_helper.php b/application/helpers/frontend_helper.php index 5f1612af6c2..ee0a982ab7c 100644 --- a/application/helpers/frontend_helper.php +++ b/application/helpers/frontend_helper.php @@ -9,9 +9,8 @@ * is derivative of works licensed under the GNU General Public License or * other free or open source software licenses. * See COPYRIGHT.php for copyright notices and details. -* -* $Id$ */ + function loadanswers() { global $surveyid; @@ -197,6 +196,9 @@ function makeLanguageChangerSurvey($sSelectedLanguage) $slangs = Survey::model()->findByPk($surveyid)->getAdditionalLanguages(); $slangs[]= GetBaseLanguageFromSurveyID($surveyid); + $aAllLanguages=getLanguageData(); + $slangs=array_keys(array_intersect_key($aAllLanguages,array_flip($slangs))); // Sort languages by their locale name + if (count($slangs)>1) // return a dropdow only of there are more than one lanagage { $previewgrp = false; @@ -217,7 +219,8 @@ function makeLanguageChangerSurvey($sSelectedLanguage) { $sHTMLCode .=" selected='selected'"; } - $sHTMLCode .=">".getLanguageNameFromCode($sLanguage,false,$sLanguage)." - ".getLanguageNameFromCode($sLanguage,false,$sSelectedLanguage)."\n"; + $sHTMLCode .= ">".$aAllLanguages[$sLanguage]['nativedescription']."\n"; + } $sHTMLCode .= "\n"; return $sHTMLCode; @@ -867,21 +870,25 @@ function remove_nulls_from_array($array) */ function submittokens($quotaexit=false) { - global $thissurvey, $timeadjust, $emailcharset ; + global $thissurvey; global $surveyid; - global $thistpl, $clienttoken; + global $clienttoken; $clang = Yii::app()->lang; $sitename = Yii::app()->getConfig("sitename"); - + $emailcharset = Yii::app()->getConfig("emailcharset"); // Shift the date due to global timeadjust setting - $today = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", $timeadjust); + $today = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust")); // check how many uses the token has left - $usesquery = "SELECT usesleft FROM {{tokens_$surveyid}} WHERE token='".$clienttoken."'"; + $usesquery = "SELECT usesleft, participant_id, tid FROM {{tokens_$surveyid}} WHERE token='".$clienttoken."'"; $usesresult = dbExecuteAssoc($usesquery); $usesrow = $usesresult->read(); - if (isset($usesrow)) { $usesleft = $usesrow['usesleft']; } + if (isset($usesrow)) { + $usesleft = $usesrow['usesleft']; + $participant_id=$usesrow['participant_id']; + $token_id=$usesrow['tid']; + } $utquery = "UPDATE {{tokens_$surveyid}}\n"; if ($quotaexit==true) @@ -893,7 +900,14 @@ function submittokens($quotaexit=false) if (isset($usesleft) && $usesleft<=1) { $utquery .= "SET usesleft=usesleft-1, completed='$today'\n"; - } + if(!empty($participant_id)) + { + //Update the survey_links table if necessary + $slquery = Survey_links::model()->find('participant_id = "'.$participant_id.'" AND survey_id = '.$surveyid.' AND token_id = '.$token_id); + $slquery->date_completed = $today; + $slquery->save(); + } + } else { $utquery .= "SET usesleft=usesleft-1\n"; @@ -904,7 +918,14 @@ function submittokens($quotaexit=false) if (isset($usesleft) && $usesleft<=1) { $utquery .= "SET usesleft=usesleft-1, completed='Y'\n"; - } + if(!empty($participant_id)) + { + //Update the survey_links table if necessary, to protect anonymity, use the date_created field date + $slquery = Survey_links::model()->find('participant_id = "'.$participant_id.'" AND survey_id = '.$surveyid.' AND token_id = '.$token_id); + $slquery->date_completed = $slquery->date_created; + $slquery->save(); + } + } else { $utquery .= "SET usesleft=usesleft-1\n"; @@ -992,7 +1013,6 @@ function submittokens($quotaexit=false) function sendSubmitNotifications($surveyid) { global $thissurvey, $debug; - global $emailcharset; global $homeurl, $maildebug, $tokensexist; $clang = Yii::app()->lang; @@ -1121,7 +1141,7 @@ function sendSubmitNotifications($surveyid) $sSubject=templatereplace($thissurvey['email_admin_notification_subj'],$aReplacementVars,$redata,'frontend_helper[1399]',($thissurvey['anonymized'] == "Y")); foreach ($aEmailNotificationTo as $sRecipient) { - if (!SendEmailMessage($sMessage, $sSubject, $sRecipient, $sFrom, $sitename, $bIsHTML, getBounceEmail($surveyid))) + if (!SendEmailMessage($sMessage, $sSubject, $sRecipient, $sFrom, $sitename, true, getBounceEmail($surveyid))) { if ($debug>0) { @@ -1137,7 +1157,7 @@ function sendSubmitNotifications($surveyid) $sSubject=templatereplace($thissurvey['email_admin_responses_subj'],$aReplacementVars,$redata,'frontend_helper[1415]',($thissurvey['anonymized'] == "Y")); foreach ($aEmailResponseTo as $sRecipient) { - if (!SendEmailMessage($sMessage, $sSubject, $sRecipient, $sFrom, $sitename, $bIsHTML, getBounceEmail($surveyid))) + if (!SendEmailMessage($sMessage, $sSubject, $sRecipient, $sFrom, $sitename, true, getBounceEmail($surveyid))) { if ($debug>0) { @@ -1154,7 +1174,7 @@ function submitfailed($errormsg='') { global $debug; global $thissurvey; - global $thistpl, $subquery, $surveyid; + global $subquery, $surveyid; $clang = Yii::app()->lang; @@ -1203,7 +1223,7 @@ function submitfailed($errormsg='') function buildsurveysession($surveyid,$previewGroup=false) { global $thissurvey, $secerror, $clienttoken; - global $tokensexist, $thistpl; + global $tokensexist; //global $surveyid; global $register_errormsg; global $totalBoilerplatequestions, $totalquestions; @@ -1216,6 +1236,10 @@ function buildsurveysession($surveyid,$previewGroup=false) $templang=$thissurvey['language']; } + $_SESSION['survey_'.$surveyid]['templatename']=validateTemplateDir($thissurvey['template']); + $_SESSION['survey_'.$surveyid]['templatepath']=getTemplatePath($_SESSION['survey_'.$surveyid]['templatename']).DIRECTORY_SEPARATOR; + $sTemplatePath=$_SESSION['survey_'.$surveyid]['templatepath']; + $totalBoilerplatequestions = 0; $loadsecurity = returnGlobal('loadsecurity'); @@ -1234,9 +1258,9 @@ function buildsurveysession($surveyid,$previewGroup=false) // No or bad answer to required security question $redata = compact(array_keys(get_defined_vars())); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata,'frontend_helper[1525]'); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata,'frontend_helper[1525]'); //echo makedropdownlist(); - echo templatereplace(file_get_contents("$thistpl/survey.pstpl"),array(),$redata,'frontend_helper[1527]'); + echo templatereplace(file_get_contents($sTemplatePath."survey.pstpl"),array(),$redata,'frontend_helper[1527]'); if (isset($loadsecurity)) { // was a bad answer @@ -1276,7 +1300,7 @@ function buildsurveysession($surveyid,$previewGroup=false)
" . $LEM->gT("Question Attribute") . "" . $LEM->gT("Value"). "
A[" . $ansInfo[0] . "]-" . $i++ . "" . $ansInfo[1]. "[VALUE: " . $valInfo[0] . "][VALUE: " . $valInfo[0] . "]".$subQeqn."" . $valInfo[1] . "
"; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata,'frontend_helper[1567]'); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata,'frontend_helper[1567]'); doFooter(); exit; } @@ -1303,12 +1327,12 @@ function buildsurveysession($surveyid,$previewGroup=false) doHeader(); $redata = compact(array_keys(get_defined_vars())); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata,'frontend_helper[1594]'); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata,'frontend_helper[1594]'); //echo makedropdownlist(); - echo templatereplace(file_get_contents("$thistpl/survey.pstpl"),array(),$redata,'frontend_helper[1596]'); + echo templatereplace(file_get_contents($sTemplatePath."survey.pstpl"),array(),$redata,'frontend_helper[1596]'); if (isset($thissurvey) && $thissurvey['allowregister'] == "Y") { - echo templatereplace(file_get_contents("$thistpl/register.pstpl"),array(),$redata,'frontend_helper[1599]'); + echo templatereplace(file_get_contents($sTemplatePath."register.pstpl"),array(),$redata,'frontend_helper[1599]'); } else { @@ -1355,7 +1379,7 @@ function buildsurveysession($surveyid,$previewGroup=false) "; } - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata,'frontend_helper[1645]'); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata,'frontend_helper[1645]'); doFooter(); exit; } @@ -1377,7 +1401,7 @@ function buildsurveysession($surveyid,$previewGroup=false) $tkresult = dbExecuteAssoc($tkquery); //Checked $tkexist = reset($tkresult->read()); - if (!$tkexist || $areTokensUsed) + if (!$tkexist || ($areTokensUsed && $thissurvey['alloweditaftercompletion'] != 'Y') ) { //TOKEN DOESN'T EXIST OR HAS ALREADY BEEN USED. EXPLAIN PROBLEM AND EXIT @@ -1386,15 +1410,15 @@ function buildsurveysession($surveyid,$previewGroup=false) doHeader(); $redata = compact(array_keys(get_defined_vars())); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata,'frontend_helper[1676]'); - echo templatereplace(file_get_contents("$thistpl/survey.pstpl"),array(),$redata,'frontend_helper[1677]'); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata,'frontend_helper[1676]'); + echo templatereplace(file_get_contents($sTemplatePath."survey.pstpl"),array(),$redata,'frontend_helper[1677]'); echo '

'.$clang->gT("This is a controlled survey. You need a valid token to participate.")."

\n" ."\t".$clang->gT("The token you have provided is either not valid, or has already been used.")."

\n" ."\t".sprintf($clang->gT("For further information please contact %s"), $thissurvey['adminname']) ." (" ."{$thissurvey['adminemail']})

\n"; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata,'frontend_helper[1684]'); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata,'frontend_helper[1684]'); doFooter(); exit; } @@ -1429,8 +1453,8 @@ function buildsurveysession($surveyid,$previewGroup=false) //TOKEN DOESN'T EXIST OR HAS ALREADY BEEN USED. EXPLAIN PROBLEM AND EXIT $redata = compact(array_keys(get_defined_vars())); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata,'frontend_helper[1719]'); - echo templatereplace(file_get_contents("$thistpl/survey.pstpl"),array(),$redata,'frontend_helper[1720]'); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata,'frontend_helper[1719]'); + echo templatereplace(file_get_contents($sTemplatePath."survey.pstpl"),array(),$redata,'frontend_helper[1720]'); echo "\t
\n" ."\t

\n" ."\t".$clang->gT("This is a controlled survey. You need a valid token to participate.")."

\n" @@ -1441,7 +1465,7 @@ function buildsurveysession($surveyid,$previewGroup=false) ."\t

\n" ."\t
\n"; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata,'frontend_helper[1731]'); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata,'frontend_helper[1731]'); doFooter(); exit; } @@ -1455,13 +1479,13 @@ function buildsurveysession($surveyid,$previewGroup=false) doHeader(); // No or bad answer to required security question $redata = compact(array_keys(get_defined_vars())); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata,'frontend_helper[1745]'); - echo templatereplace(file_get_contents("$thistpl/survey.pstpl"),array(),$redata,'frontend_helper[1746]'); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata,'frontend_helper[1745]'); + echo templatereplace(file_get_contents($sTemplatePath."survey.pstpl"),array(),$redata,'frontend_helper[1746]'); // If token wasn't provided and public registration // is enabled then show registration form if ( !isset($gettoken) && isset($thissurvey) && $thissurvey['allowregister'] == "Y") { - echo templatereplace(file_get_contents("$thistpl/register.pstpl"),array(),$redata,'frontend_helper[1751]'); + echo templatereplace(file_get_contents($sTemplatePath."register.pstpl"),array(),$redata,'frontend_helper[1751]'); } else { // only show CAPTCHA @@ -1527,7 +1551,7 @@ function buildsurveysession($surveyid,$previewGroup=false) "; } - echo ''.templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata,'frontend_helper[1817]'); + echo ''.templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata,'frontend_helper[1817]'); doFooter(); exit; } @@ -1621,8 +1645,8 @@ function buildsurveysession($surveyid,$previewGroup=false) doHeader(); $redata = compact(array_keys(get_defined_vars())); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata,'frontend_helper[1914]'); - echo templatereplace(file_get_contents("$thistpl/survey.pstpl"),array(),$redata,'frontend_helper[1915]'); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata,'frontend_helper[1914]'); + echo templatereplace(file_get_contents($sTemplatePath."survey.pstpl"),array(),$redata,'frontend_helper[1915]'); echo "\t
\n" ."\t

\n" ."\t".$clang->gT("This survey does not yet have any questions and cannot be tested or completed.")."

\n" @@ -1632,7 +1656,7 @@ function buildsurveysession($surveyid,$previewGroup=false) ."\t

\n" ."\t
\n"; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata,'frontend_helper[1925]'); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata,'frontend_helper[1925]'); doFooter(); exit; } @@ -1920,23 +1944,15 @@ function buildsurveysession($surveyid,$previewGroup=false) // } // } // Prefill questions/answers from command line params + $reservedGetValues= array('token','sid','gid','qid','lang','newtest','action'); $startingValues=array(); - if (isset($_SESSION['survey_'.$surveyid]['insertarray'])) + if (isset($_GET) && !$previewGroup) { - foreach($_SESSION['survey_'.$surveyid]['insertarray'] as $field) + foreach ($_GET as $k=>$v) { - if (isset($_GET[$field]) && $field!='token') + if (!in_array($k,$reservedGetValues)) { - $q = clone $fieldmap[$field]['q']; - $value = $q->filter($_GET[$field], 'get'); - if (!is_null($value)) - { - $_SESSION['survey_'.$surveyid][$field] = $value; - $startingValues[$field] = array ( - 'q'=>$q, - 'value'=>$value, - ); - } + $startingValues[$k] = $v; } } } @@ -2076,7 +2092,6 @@ function surveymover() */ function doAssessment($surveyid, $returndataonly=false) { - global $thistpl; $clang = Yii::app()->lang; @@ -2266,10 +2281,13 @@ function UpdateFieldArray() */ function check_quota($checkaction,$surveyid) { + global $clang, $clienttoken; if (!isset($_SESSION['survey_'.$surveyid]['s_lang'])){ return; } - global $thistpl, $clang, $clienttoken; + + $sTemplatePath=$_SESSION['survey_'.$surveyid]['templatepath']; + $global_matched = false; $quota = getQuotaInformation($surveyid, $_SESSION['survey_'.$surveyid]['s_lang']); @@ -2394,12 +2412,12 @@ function check_quota($checkaction,$surveyid) doHeader(); $redata = compact(array_keys(get_defined_vars())); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata,'frontend_helper[2617]'); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata,'frontend_helper[2617]'); echo "\t
\n"; echo "\t".$quota['Message']."

\n"; echo "\t".$quota['UrlDescrip']."
\n"; echo "\t
\n"; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata,'frontend_helper[2622]'); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata,'frontend_helper[2622]'); doFooter(); exit; } @@ -2411,7 +2429,7 @@ function check_quota($checkaction,$surveyid) doHeader(); $redata = compact(array_keys(get_defined_vars())); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata,'frontend_helper[2634]'); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata,'frontend_helper[2634]'); echo "\t
\n"; echo "\t".$quota['Message']."

\n"; echo "\t".$quota['UrlDescrip']."
\n"; @@ -2421,7 +2439,7 @@ function check_quota($checkaction,$surveyid) \n"; echo "\t
\n"; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata,'frontend_helper[2644]'); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata,'frontend_helper[2644]'); doFooter(); exit; } @@ -2507,7 +2525,7 @@ function GetReferringUrl() * Shows the welcome page, used in group by group and question by question mode */ function display_first_page() { - global $thistpl, $token, $surveyid, $thissurvey, $navigator, $totalquestions; + global $token, $surveyid, $thissurvey, $navigator, $totalquestions; $clang = Yii::app()->lang; @@ -2520,17 +2538,19 @@ function display_first_page() { LimeExpressionManager::StartProcessingGroup(-1, false, $surveyid); // start on welcome page $redata = compact(array_keys(get_defined_vars())); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata,'frontend_helper[2757]'); + $sTemplatePath=$_SESSION['survey_'.$surveyid]['templatepath']; + + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata,'frontend_helper[2757]'); echo "\n
\n"; echo "\n\n\n"; - echo templatereplace(file_get_contents("$thistpl/welcome.pstpl"),array(),$redata,'frontend_helper[2762]')."\n"; + echo templatereplace(file_get_contents($sTemplatePath."welcome.pstpl"),array(),$redata,'frontend_helper[2762]')."\n"; if ($thissurvey['anonymized'] == "Y") { - echo templatereplace(file_get_contents("$thistpl/privacy.pstpl"),array(),$redata,'frontend_helper[2765]')."\n"; + echo templatereplace(file_get_contents($sTemplatePath."/privacy.pstpl"),array(),$redata,'frontend_helper[2765]')."\n"; } - echo templatereplace(file_get_contents("$thistpl/navigator.pstpl"),array(),$redata,'frontend_helper[2767]'); + echo templatereplace(file_get_contents($sTemplatePath."navigator.pstpl"),array(),$redata,'frontend_helper[2767]'); if ($thissurvey['active'] != "Y") { echo "

".$clang->gT("This survey is currently not active. You will not be able to save your responses.")."

\n"; @@ -2549,7 +2569,7 @@ function display_first_page() { echo "\n"; echo "\n
\n"; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata,'frontend_helper[2782]'); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata,'frontend_helper[2782]'); echo LimeExpressionManager::GetRelevanceAndTailoringJavaScript(); LimeExpressionManager::FinishProcessingPage(); diff --git a/application/helpers/replacements_helper.php b/application/helpers/replacements_helper.php index 84d86f487b4..4dfcbf99f92 100644 --- a/application/helpers/replacements_helper.php +++ b/application/helpers/replacements_helper.php @@ -118,7 +118,6 @@ function templatereplace($line, $replacements = array(), &$redata = array(), $de { $templatename=Yii::app()->getConfig('defaulttemplate'); } - $templatename=validateTemplateDir($templatename); if(!isset($templatedir)) $templatedir = getTemplatePath($templatename); if(!isset($templateurl)) $templateurl = getTemplateURL($templatename)."/"; @@ -127,12 +126,11 @@ function templatereplace($line, $replacements = array(), &$redata = array(), $de if(stripos ($line,"{TEMPLATECSS}")) { $css_header_includes=Yii::app()->getConfig("css_header_includes"); - // TODO: only one jquery-ui.css, but break slider actually - if (file_exists($templatedir . '/jquery-ui-custom.css')) + if (file_exists($templatedir .DIRECTORY_SEPARATOR.'jquery-ui-custom.css')) { $template_jqueryui_css= "\n"; } - elseif(file_exists($templatedir . '/jquery-ui.css')) + elseif(file_exists($templatedir.DIRECTORY_SEPARATOR.'jquery-ui.css')) { $template_jqueryui_css= "\n"; } @@ -144,11 +142,22 @@ function templatereplace($line, $replacements = array(), &$redata = array(), $de if($css_header_includes){ foreach ($css_header_includes as $cssinclude) { - if (substr($cssinclude,0,1) == '/') - $_templatecss .= "\n"; + if (substr($cssinclude,0,4) == 'http' || substr($cssinclude,0,strlen(Yii::app()->getConfig('publicurl'))) == Yii::app()->getConfig('publicurl')) + { + $_templatecss .= "\n"; + } else + { + if(file_exists($templatedir.DIRECTORY_SEPARATOR.$cssinclude)) + { + $_templatecss .= "\n"; + } + else + { $_templatecss .= "\n"; } + } + } } $_templatecss.= $template_jqueryui_css; // Template jquery ui after default css $_templatecss.= "\n"; @@ -163,15 +172,20 @@ function templatereplace($line, $replacements = array(), &$redata = array(), $de $_jqueryuijsurl=Yii::app()->getConfig('generalscripts')."jquery/jquery-ui.js"; $_templatejs.= "\n"; $_templatejs.= "\n"; + $_templatejs.= "\n"; if($js_header_includes){ foreach ($js_header_includes as $jsinclude) { - if (substr($jsinclude,0,4) == 'http' || substr($jsinclude,0,strlen(Yii::app()->getConfig('generalscripts'))) == Yii::app()->getConfig('generalscripts')) + if (substr($jsinclude,0,4) == 'http' || substr($jsinclude,0,strlen(Yii::app()->getConfig('publicurl'))) == Yii::app()->getConfig('publicurl')) + { $_templatejs .= "\n"; + } else - $_templatejs .= "\n"; + { + $_templatejs .= "\n"; } } + } $_templatejs.= "\n"; $_templatejs.= "\n"; $_templatejs.= useFirebug(); @@ -378,9 +392,18 @@ function templatereplace($line, $replacements = array(), &$redata = array(), $de $_linkreplace=''; } - if (isset($surveyid)) { + if(isset($thissurvey['sid']) && isset($_SESSION['survey_'.$thissurvey['sid']]['srid']) && $thissurvey['active']=='Y') + { + $iscompleted=Survey_dynamic::model($surveyid)->isCompleted($_SESSION['survey_'.$thissurvey['sid']]['srid']); + } + else + { + $iscompleted=false; + } + if (isset($surveyid) && !$iscompleted) + { $_clearall = "gT("Are you sure you want to clear all your responses?", 'js') . "')) {\nwindow.open('".Yii::app()->getController()->createUrl("survey/index/sid/$surveyid?move=clearall&lang=" . $s_lang); + . "onclick=\"if (confirm('" . $clang->gT("Are you sure you want to clear all your responses?", 'js') . "')) {\nwindow.open('".Yii::app()->getController()->createUrl("survey/index/sid/$surveyid",array('move'=>'clearall','lang'=>$s_lang),'&'); if (returnGlobal('token')) { @@ -401,7 +424,6 @@ function templatereplace($line, $replacements = array(), &$redata = array(), $de { $_datestamp = '-'; } - if (isset($thissurvey['allowsave']) and $thissurvey['allowsave'] == "Y") { // Find out if the user has any saved data @@ -417,7 +439,7 @@ function templatereplace($line, $replacements = array(), &$redata = array(), $de $_saveall = "\t\t\t"; // Show Save So Far button }; } - elseif (!isset(Yii::app()->session['step']) || !Yii::app()->session['step']) + elseif (isset($surveyid) && (!isset($_SESSION['survey_'.$surveyid]['step']) || !$_SESSION['survey_'.$surveyid]['step'])) { //First page, show LOAD if ($thissurvey['tokenanswerspersistence'] != 'Y' || !isset($surveyid) || !tableExists('tokens_'.$surveyid)) { @@ -736,10 +758,18 @@ function templatereplace($line, $replacements = array(), &$redata = array(), $de } } + $_endtext = ''; + if (isset($thissurvey['surveyls_endtext']) && trim($thissurvey['surveyls_endtext'])!='') + { + $_endtext = $thissurvey['surveyls_endtext']; + } + + // Set the array of replacement variables here - don't include curly braces $coreReplacements = array(); - $coreReplacements['AID'] = isset($questiondetails->aid) ? $questiondetails->aid : ''; + $coreReplacements['ACTIVE'] = (isset($thissurvey['active']) && !($thissurvey['active'] != "Y")); + $coreReplacements['AID'] = isset($questiondetials->aid) ? $questiondetails->aid : ''; $coreReplacements['ANSWER'] = isset($answer) ? $answer : ''; // global $coreReplacements['ANSWERSCLEARED'] = $clang->gT("Answers Cleared"); $coreReplacements['ASSESSMENTS'] = $assessmenthtml; @@ -750,6 +780,7 @@ function templatereplace($line, $replacements = array(), &$redata = array(), $de $coreReplacements['CLOSEWINDOW'] = "".$clang->gT("Close this window").""; $coreReplacements['COMPLETED'] = isset($redata['completed']) ? $redata['completed'] : ''; // global $coreReplacements['DATESTAMP'] = $_datestamp; + $coreReplacements['ENDTEXT'] = $_endtext; $coreReplacements['EXPIRY'] = $_dateoutput; $coreReplacements['GID'] = isset($questiondetails->gid) ? $questiondetails->gid: ''; $coreReplacements['GOOGLE_ANALYTICS_API_KEY'] = $_googleAnalyticsAPIKey; diff --git a/application/helpers/surveytranslator_helper.php b/application/helpers/surveytranslator_helper.php index df56f6792d4..a46a503053a 100644 --- a/application/helpers/surveytranslator_helper.php +++ b/application/helpers/surveytranslator_helper.php @@ -301,12 +301,12 @@ function getLanguageData($bOrderByNative=false,$sLanguageCode='en') { $supportedLanguages['it']['dateformat'] = 5; $supportedLanguages['it']['radixpoint'] = 1; - // Italian-Formal - $supportedLanguages['it-formal']['description'] = $clang->gT('Italian (formal)'); - $supportedLanguages['it-formal']['nativedescription'] = 'Formale Italiano'; - $supportedLanguages['it-formal']['rtl'] = false; - $supportedLanguages['it-formal']['dateformat'] = 5; - $supportedLanguages['it-formal']['radixpoint'] = 1; + // Italian informal + $supportedLanguages['it-informal']['description'] = $clang->gT('Italian (informal)'); + $supportedLanguages['it-informal']['nativedescription'] = 'Italiano (informale)'; + $supportedLanguages['it-informal']['rtl'] = false; + $supportedLanguages['it-informal']['dateformat'] = 5; + $supportedLanguages['it-informal']['radixpoint'] = 1; // Japanese $supportedLanguages['ja']['description'] = $clang->gT('Japanese'); diff --git a/application/helpers/update/update_helper.php b/application/helpers/update/update_helper.php index 9c4ff1db196..2c1dd06e591 100644 --- a/application/helpers/update/update_helper.php +++ b/application/helpers/update/update_helper.php @@ -55,7 +55,7 @@ function ShowDBUpgradeNotice() { ."
  • " .$clang->gT('Table prefix') . ": " . Yii::app()->db->tablePrefix . "
  • " ."
  • " .$clang->gT('Site name') . ": " . Yii::app()->getConfig("sitename") . "
  • " ."
  • " .$clang->gT('Root URL') . ": " . Yii::app()->getController()->createUrl('') . "
  • " - .'' + .'
    ' ."

    " ."" . $clang->gT('Click here to continue') . "" ."

    " diff --git a/application/helpers/update/updatedb_helper.php b/application/helpers/update/updatedb_helper.php index 244b8a896de..f0def20c90e 100644 --- a/application/helpers/update/updatedb_helper.php +++ b/application/helpers/update/updatedb_helper.php @@ -21,36 +21,16 @@ function db_upgrade_all($oldversion) { /// This function does anything necessary to upgrade /// older versions to match current functionality global $modifyoutput, $usertemplaterootdir, $standardtemplaterootdir; + Yii::app()->loadHelper('database'); + $usertemplaterootdir = Yii::app()->getConfig('usertemplaterootdir'); $standardtemplaterootdir = Yii::app()->getConfig('standardtemplaterootdir'); $clang = Yii::app()->lang; echo str_pad($clang->gT('The LimeSurvey database is being upgraded').' ('.date('Y-m-d H:i:s').')',14096).".

    ". $clang->gT('Please be patient...')."

    \n"; - $sDBDriverName=Yii::app()->db->getDriverName(); - if ($sDBDriverName=='mysqli') $sDBDriverName='mysql'; - if ($sDBDriverName=='sqlsrv') $sDBDriverName='mssql'; - - // Special customization because Yii is too limited to handle a varchar field of a length other than 255 in a cross-DB compatible way - // see http://www.yiiframework.com/forum/index.php/topic/32289-cross-db-compatible-varchar-field-length-definitions/ - // and http://github.com/yiisoft/yii/issues/765 - if ($sDBDriverName=='pgsql') - { - Yii::app()->setConfig('char',$sChar='character'); - Yii::app()->setConfig('varchar',$sVarchar='character varying'); - Yii::app()->setConfig('autoincrement', $sAutoIncrement='serial'); - } - elseif ($sDBDriverName=='mssql') - { - Yii::app()->setConfig('char',$sChar='char'); - Yii::app()->setConfig('varchar',$sVarchar='varchar'); - Yii::app()->setConfig('autoincrement', $sAutoIncrement='integer NOT NULL IDENTITY (1,1)'); - } - else - { - Yii::app()->setConfig('char',$sChar='char'); - Yii::app()->setConfig('varchar',$sVarchar='varchar'); - Yii::app()->setConfig('autoincrement', $sAutoIncrement='int(11) NOT NULL AUTO_INCREMENT'); - } + $sDBDriverName=setsDBDriverName(); + setVarchar($sDBDriverName); + $sVarchar = Yii::app()->getConfig('varchar'); if ($oldversion < 111) { @@ -998,8 +978,24 @@ function db_upgrade_all($oldversion) { LimeExpressionManager::UpgradeConditionsToRelevance(); Yii::app()->db->createCommand()->update('{{settings_global}}',array('stg_value'=>158),"stg_name='DBVersion'"); } - if ($oldversion < 159) + { + alterColumn('{{failed_login_attempts}}', 'ip', "{$sVarchar}(40)",false); + Yii::app()->db->createCommand()->update('{{settings_global}}',array('stg_value'=>159),"stg_name='DBVersion'"); + } + + if ($oldversion < 160) + { + alterLanguageCode('it','it-informal'); + alterLanguageCode('it-formal','it'); + Yii::app()->db->createCommand()->update('{{settings_global}}',array('stg_value'=>160),"stg_name='DBVersion'"); + } + if ($oldversion < 161) + { + addColumn('{{survey_links}}','date_invited','datetime NULL default NULL'); + addColumn('{{survey_links}}','date_completed','datetime NULL default NULL'); + } + if ($oldversion < 162) { Yii::app()->db->createCommand()->createTable('{{question_types}}',array( 'tid' => 'pk', @@ -1024,15 +1020,15 @@ function db_upgrade_all($oldversion) { Yii::app()->db->createCommand()->addColumn('{{questions}}','tid',"integer NOT NULL DEFAULT '0' AFTER `gid`"); - upgradeSurveys159(); - Yii::app()->db->createCommand()->update('{{settings_global}}',array('stg_value'=>159),"stg_name='DBVersion'"); + upgradeSurveys162(); + Yii::app()->db->createCommand()->update('{{settings_global}}',array('stg_value'=>162),"stg_name='DBVersion'"); } fixLanguageConsistencyAllSurveys(); echo '

    '.sprintf($clang->gT('Database update finished (%s)'),date('Y-m-d H:i:s')).'

    '; } -function upgradeSurveys159() +function upgradeSurveys162() { $types = array(array(1, 1, 1, '5 point choice', 'FiveList', '5', 'Y'),array(2, 2, 1, 'List (dropdown)', 'Select', '!', 'Y'),array(3, 3, 1, 'List (radio)', 'List', 'L', 'Y'),array(4, 4, 1, 'List with comment', 'CommentList', 'O', 'Y'),array(5, 1, 2, 'Array', 'RadioArray', 'F', 'Y'),array(6, 2, 2, 'Array (10 point choice)', 'TenRadioArray', 'B', 'Y'),array(7, 3, 2, 'Array (5 point choice)', 'FiveRadioArray', 'A', 'Y'),array(8, 4, 2, 'Array (Increase/Same/Decrease)', 'IDRadioArray', 'E', 'Y'),array(9, 5, 2, 'Array (Numbers)', 'NumberArray', ':', 'Y'),array(10, 6, 2, 'Array (Texts)', 'TextArray', ';', 'Y'),array(11, 7, 2, 'Array (Yes/No/Uncertain)', 'YNRadioArray', 'C', 'Y'),array(12, 8, 2, 'Array by column', 'ColumnRadioArray', 'H', 'Y'),array(13, 9, 2, 'Array dual scale', 'DualRadioArray', '1', 'Y'),array(14, 1, 3, 'Date/Time', 'Date', 'D', 'Y'),array(15, 2, 3, 'Equation', 'Equation', '*', 'Y'),array(16, 3, 3, 'File upload', 'File', '|', 'Y'),array(17, 4, 3, 'Gender', 'Gender', 'G', 'Y'),array(18, 5, 3, 'Language switch', 'Language', 'I', 'Y'),array(19, 6, 3, 'Multiple numerical input', 'Multinumerical', 'K', 'Y'),array(20, 7, 3, 'Numerical input', 'Numerical', 'N', 'Y'),array(21, 8, 3, 'Ranking', 'Ranking', 'R', 'Y'),array(22, 9, 3, 'Text display', 'Display', 'X', 'Y'),array(23, 10, 3, 'Yes/No', 'YN', 'Y', 'Y'),array(24, 1, 4, 'Huge free text', 'HugeText', 'U', 'Y'),array(25, 2, 4, 'Long free text', 'LongText', 'T', 'Y'),array(26, 3, 4, 'Multiple short text', 'Multitext', 'Q', 'Y'),array(27, 4, 4, 'Short free text', 'ShortText', 'S', 'Y'),array(28, 1, 5, 'Multiple choice', 'Check', 'M', 'Y'),array(29, 2, 5, 'Multiple choice with comments', 'CommentCheck', 'P', 'Y')); $groups = array(array(1, 'Single choice questions', 1, 'Y'),array(2, 'Arrays', 2, 'Y'),array(3, 'Mask questions', 3, 'Y'),array(4, 'Text questions', 4, 'Y'),array(5, 'Multiple choice questions', 5, 'Y')); @@ -1707,7 +1703,7 @@ function dropColumn($sTableName, $sColumnName) $sDBDriverName=Yii::app()->db->getDriverName(); if ($sDBDriverName=='mysqli') $sDBDriverName='mysql'; if ($sDBDriverName=='sqlsrv') $sDBDriverName='mssql'; - if ($sDBDriverName='mssql') + if ($sDBDriverName=='mssql') { dropDefaultValueMSSQL($sColumnName,$sTableName); } @@ -1717,28 +1713,13 @@ function dropColumn($sTableName, $sColumnName) -function createTable($sTableName, $aColumns, $aOptions=null) -{ - $sDBDriverName=Yii::app()->db->getDriverName(); - if ($sDBDriverName=='mysqli') $sDBDriverName='mysql'; - if ($sDBDriverName=='sqlsrv') $sDBDriverName='mssql'; - if ($sDBDriverName='mssql') - { - foreach ($aColumns as $sName=>&$sType) - { - $sType=str_replace('text','varchar(max)',$sType); - $sType=str_replace('binary','text',$sType); - } - } - Yii::app()->db->createCommand()->createTable($sTableName,$aColumns,$aOptions); -} function addColumn($sTableName, $sColumn, $sType) { $sDBDriverName=Yii::app()->db->getDriverName(); if ($sDBDriverName=='mysqli') $sDBDriverName='mysql'; if ($sDBDriverName=='sqlsrv') $sDBDriverName='mssql'; - if ($sDBDriverName='mssql') + if ($sDBDriverName=='mssql') { $sType=str_replace('text','varchar(max)',$sType); $sType=str_replace('binary','text',$sType); @@ -1764,4 +1745,49 @@ function dropDefaultValueMSSQL($fieldname, $tablename) Yii::app()->db->createCommand("ALTER TABLE {$tablename} DROP CONSTRAINT {$defaultname['constraint_name']}")->execute(); } -} \ No newline at end of file +} + +/** +* Returns the name of the DB Driver - used for other functions that make db specific calls +* +*/ +function setsDBDriverName() { + $sDBDriverName=Yii::app()->db->getDriverName(); + if ($sDBDriverName=='mysqli') $sDBDriverName='mysql'; + if ($sDBDriverName=='sqlsrv') $sDBDriverName='mssql'; + return $sDBDriverName; +} + +/** +* Special customisation because Yii is limited in its ability to handle varchar fields of lenghts other than 255 in a cross-db +* compatible way. see http://www.yiiframework.com/forum/index.php/topic/32289-cross-db-compatible-varchar-field-length-definitions/ +* and http://github.com/yiisoft/yii/issues/765 +* +* Note that it sets values for the config files for use later, and does not return any values. +* Access the set values using Yii::app()->getConfig('varchar') or Yii::app()->getConfigu('autoincrement'); +* +* @param mixed $sDBDriverName The name of the db driver being used. If the parameter is forgotten, the +* function is capable of retrieving it itself. +*/ +function setVarchar($sDBDriverName=null) { + + if(!$sDBDriverName) { + $sDBDriverName=setsDBDriverName(); + } + + if ($sDBDriverName=='pgsql') + { + Yii::app()->setConfig('varchar',$sVarchar='character varying'); + Yii::app()->setConfig('autoincrement', $sAutoIncrement='serial'); + } + elseif ($sDBDriverName=='mssql') + { + Yii::app()->setConfig('varchar',$sVarchar='varchar'); + Yii::app()->setConfig('autoincrement', $sAutoIncrement='integer NOT NULL IDENTITY (1,1)'); + } + else + { + Yii::app()->setConfig('varchar',$sVarchar='varchar'); + Yii::app()->setConfig('autoincrement', $sAutoIncrement='int(11) NOT NULL AUTO_INCREMENT'); + } +} diff --git a/application/libraries/Load_answers.php b/application/libraries/Load_answers.php index 3aece76c5d2..b9fe0bdf36c 100644 --- a/application/libraries/Load_answers.php +++ b/application/libraries/Load_answers.php @@ -17,10 +17,10 @@ class Load_answers { function run($args) { extract($args); $redata = compact(array_keys(get_defined_vars())); - if (!isset($thistpl)) {die ("Error!");} + $sTemplatePath=$_SESSION['survey_'.$surveyid]['templatepath']; sendCacheHeaders(); doHeader(); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata); echo "\n\n\n" ."\t\n\n"; echo "
    \n"; - echo templatereplace(file_get_contents("$thistpl/load.pstpl"),array(),$redata); + echo templatereplace(file_get_contents($sTemplatePath."load.pstpl"),array(),$redata); //PRESENT OPTIONS SCREEN (Replace with Template Later) //END echo "\n"; @@ -41,7 +41,7 @@ function run($args) { } echo "
    "; - echo templatereplace(file_get_contents("$thistpl/endpage.pstpl"),array(),$redata); + echo templatereplace(file_get_contents($sTemplatePath."endpage.pstpl"),array(),$redata); doFooter(); exit; diff --git a/application/libraries/Save.php b/application/libraries/Save.php index e7083da2399..771970758bb 100644 --- a/application/libraries/Save.php +++ b/application/libraries/Save.php @@ -58,11 +58,12 @@ class Save { function showsaveform() { //Show 'SAVE FORM' only when click the 'Save so far' button the first time, or when duplicate is found on SAVE FORM. - global $thistpl, $errormsg, $thissurvey, $surveyid, $clang, $clienttoken, $thisstep; + global $errormsg, $thissurvey, $surveyid, $clang, $clienttoken, $thisstep; $redata = compact(array_keys(get_defined_vars())); + $sTemplatePath=$_SESSION['survey_'.$surveyid]['templatepath']; sendCacheHeaders(); doHeader(); - echo templatereplace(file_get_contents("$thistpl/startpage.pstpl"),array(),$redata); + echo templatereplace(file_get_contents($sTemplatePath."startpage.pstpl"),array(),$redata); echo "\n\n\n" ."\t\n"; - } - - $answer = $checkotherscript . $answer; - $answer .= $postrow; return $answer; } @@ -478,7 +446,8 @@ public function prepareConditions($row) "value"=>$row['value'], "matchfield"=>$row['cfieldname'], "matchvalue"=>$row['value'], - "matchmethod"=>$row['method'] + "matchmethod"=>$row['method'], + "subqid"=>$cfieldnamematch[1].'NAOK' ); } @@ -486,7 +455,8 @@ public function prepareConditions($row) "value"=>$row['value'], "matchfield"=>$row['cfieldname'], "matchvalue"=>"Y", - "matchmethod"=>$row['method'] + "matchmethod"=>$row['method'], + "subqid"=>$row['cfieldname'] ); } @@ -591,7 +561,7 @@ public function getSPSSData($data, $iLength, $na) public function availableAttributes($attr = false) { - $attrs=array("array_filter","array_filter_exclude","array_filter_style","assessment_value","display_columns","exclude_all_others","exclude_all_others_auto","statistics_showgraph","hide_tip","hidden","max_answers","min_answers","other_numbers_only","other_replace_text","page_break","public_statistics","random_order","parent_order","scale_export","random_group"); + $attrs=array("array_filter","array_filter_exclude","array_filter_style","assessment_value","display_columns","em_validation_q","em_validation_q_tip","exclude_all_others","exclude_all_others_auto","statistics_showgraph","hide_tip","hidden","max_answers","min_answers","other_numbers_only","other_replace_text","page_break","public_statistics","random_order","parent_order","scale_export","random_group"); return $attr?array_key_exists($attr,$attrs):$attrs; } diff --git a/application/modules/CommentCheckQuestion.php b/application/modules/CommentCheckQuestion.php index d312f8337a3..b79d1005552 100644 --- a/application/modules/CommentCheckQuestion.php +++ b/application/modules/CommentCheckQuestion.php @@ -39,12 +39,10 @@ public function getAnswerHTML() { $sSeperator = getRadixPointData($thissurvey['surveyls_numberformat']); $sSeperator = $sSeperator['seperator']; - $numbersonly = 'onkeypress="return goodchars(event,\'-0123456789'.$sSeperator.'\')"'; $oth_checkconditionFunction = "fixnum_checkconditions"; } else { - $numbersonly = ''; $oth_checkconditionFunction = "checkconditions"; } @@ -105,8 +103,7 @@ public function getAnswerHTML() $answer_main .= CHECKED; } } - $answer_main .=" onclick='cancelBubbleThis(event);$checkconditionFunction(this.value, this.name, this.type);' " - . " onchange='document.getElementById(\"answer$myfname2\").value=\"\";' />\n" + $answer_main .=" onclick='cancelBubbleThis(event);$checkconditionFunction(this.value, this.name, this.type);if (!$(this).attr(\"checked\")) { $(\"#answer$myfname2\").val(\"\"); $checkconditionFunction(document.getElementById(\"answer{$myfname2}\").value,\"$myfname2\",\"checkbox\");}' />\n" . "\t\n"; @@ -124,7 +121,7 @@ public function getAnswerHTML() ."surveyid][$myfname2])) {$answer_main .= htmlspecialchars($_SESSION['survey_'.$this->surveyid][$myfname2],ENT_QUOTES);} // --> START NEW FEATURE - SAVE - $answer_main .= "' onclick='cancelBubbleThis(event);' onchange='if (jQuery.trim($(\"#answer{$myfname2}\").val())!=\"\") { document.getElementById(\"answer{$myfname}\").checked=true;$checkconditionFunction(document.getElementById(\"answer{$myfname}\").value,\"$myfname\",\"checkbox\");}' />\n
    \n" + $answer_main .= "' onkeyup='if (jQuery.trim($(\"#answer{$myfname2}\").val())!=\"\") { document.getElementById(\"answer{$myfname}\").checked=true;$checkconditionFunction(document.getElementById(\"answer{$myfname2}\").value,\"$myfname2\",\"text\");}' />\n\n" . "\t\n"; // --> END NEW FEATURE - SAVE @@ -136,8 +133,8 @@ public function getAnswerHTML() $myfname2 = $myfname.'comment'; $anscount = $anscount + 2; $answer_main .= "\t
  • \n\n" - . "\t\n" . "\n\t\n" - . ' - surveyid]['s_lang']])!='') { $leftheader= $clang->gT($aQuestionAttributes['dualscale_headerA'][$_SESSION['survey_'.$this->surveyid]['s_lang']]); } @@ -134,12 +138,11 @@ public function getAnswerHTML() $mycolumns = "\t\n" ."\t\n"; - $myheader2 = "\n\n" - . "\t \n\n"; + $answer_head_line = "\t \n\n"; $odd_even = ''; foreach ($labelans as $ld) { - $myheader2 .= "\t".$ld."\n"; + $answer_head_line .= "\t".$ld."\n"; $odd_even = alternation($odd_even); $mycolumns .= "\n"; } @@ -149,10 +152,10 @@ public function getAnswerHTML() { $mycolumns .= "\t\n" . "\t\n"; - $myheader2 .= "\n\t \n\n"; // Separator + $answer_head_line .= "\n\t \n\n"; // Separator foreach ($labelans1 as $ld) { - $myheader2 .= "\t".$ld."\n"; + $answer_head_line .= "\t".$ld."\n"; $odd_even = alternation($odd_even); $mycolumns .= "\n"; } @@ -160,54 +163,56 @@ public function getAnswerHTML() } if ($right_exists) { - $myheader2 .= "\t \n"; + $answer_head_line .= "\t \n"; $mycolumns .= "\n\t\n\n"; } if ($this->mandatory != 'Y' && SHOW_NO_ANSWER == 1) //Question is not mandatory and we can show "no answer" { - $myheader2 .= "\t \n"; // Separator - $myheader2 .= "\t".$clang->gT('No answer')."\n"; + $answer_head_line .= "\t \n"; // Separator + $answer_head_line .= "\t".$clang->gT('No answer')."\n"; $odd_even = alternation($odd_even); $mycolumns .= "\n\t\n\n"; $mycolumns .= "\t\n"; } $mycolumns .= "\t\n"; - $myheader2 .= "\n"; + $answer_head2 = "\n\n" + . $answer_head_line + . "\n"; // build first row of header if needed if ($leftheader != '' || $rightheader !='') { - $myheader1 = "\n" + $answer_head1 = "\n" . "\t \n" . "\t$leftheader\n"; if (count($labelans1)>0) { - $myheader1 .= "\t \n" // Separator + $answer_head1 .= "\t \n" // Separator ."\t$rightheader\n"; } if ($right_exists) { - $myheader1 .= "\t \n"; + $answer_head1 .= "\t \n"; } if ($this->mandatory != 'Y' && SHOW_NO_ANSWER == 1) { - $myheader1 .= "\t \n"; // Separator - $myheader1 .= "\t \n"; + $answer_head1 .= "\t \n"; // Separator + $answer_head1 .= "\t \n"; } $myheader1 .= "\n"; } else { - $myheader1 = ''; + $answer_head1 = ''; } $answer .= "\ntext))." - a dual array type question\">\n" . $mycolumns . "\n\t\n" - . $myheader1 - . $myheader2 + . $answer_head1 + . $answer_head2 . "\n\t\n" . "\n"; @@ -220,30 +225,9 @@ public function getAnswerHTML() if ( ($anscount - $fn + 1) >= $minrepeatheadings ) { $answer .= "\n";// Close actual body and open another one - $answer .= "\n\n" - . "\t\n"; - foreach ($labelans as $ld) - { - $answer .= "\t\n"; - } - if (count($labelans1)>0) // if second label set is used - { - $answer .= "\n"; // Separator - foreach ($labelans1 as $ld) - { - $answer .= "\t\n"; - } - } - if ($right_exists) - { - $answer .= "\t\n"; - } - if ($this->mandatory != 'Y' && SHOW_NO_ANSWER == 1) //Question is not mandatory and we can show "no answer" - { - $answer .= "\t\n"; // Separator - $answer .= "\t\n"; - } - $answer .= "\n"; + $answer .= "\n\n" + . $answer_head_line + . "\n"; } } @@ -522,7 +506,7 @@ public function getAnswerHTML() { $answer .= SELECTED; } - $answer .= '>'.$lrow['title']."\n"; + $answer .= '>'.flattenText($lrow['title'])."\n"; } // If not mandatory and showanswer, show no ans if ($this->mandatory != 'Y' && SHOW_NO_ANSWER == 1) @@ -574,7 +558,7 @@ public function getAnswerHTML() { $answer .= SELECTED; } - $answer .= '>'.$lrow1['title']."\n"; + $answer .= '>'.flattenText($lrow1['title'])."\n"; } // If not mandatory and showanswer, show no ans if ($this->mandatory != 'Y' && SHOW_NO_ANSWER == 1) @@ -701,7 +685,7 @@ public function getFieldSubHeading($survey, $export, $code) public function availableAttributes($attr = false) { - $attrs=array("answer_width","array_filter","array_filter_exclude","array_filter_style","dropdown_prepostfix","dropdown_separators","dualscale_headerA","dualscale_headerB","statistics_showgraph","statistics_graphtype","hide_tip","hidden","max_answers","min_answers","page_break","public_statistics","random_order","parent_order","use_dropdown","scale_export","random_group"); + $attrs=array("answer_width","repeat_headings","array_filter","array_filter_exclude","array_filter_style","dropdown_prepostfix","dropdown_separators","dualscale_headerA","dualscale_headerB","statistics_showgraph","statistics_graphtype","hide_tip","hidden","max_answers","min_answers","page_break","public_statistics","random_order","parent_order","use_dropdown","scale_export","random_group"); return $attr?array_key_exists($attr,$attrs):$attrs; } diff --git a/application/modules/FileQuestion.php b/application/modules/FileQuestion.php index ef9bacb0a10..655ee1d7927 100644 --- a/application/modules/FileQuestion.php +++ b/application/modules/FileQuestion.php @@ -53,7 +53,7 @@ function upload_$this->fieldname[1]() { returnTxt: '" . $clang->gT('Return to survey','js') . "', headTitle: '" . $clang->gT('Title','js') . "', headComment: '" . $clang->gT('Comment','js') . "', - headFileName: '" . $clang->gT('File name','js') . "', + headFileName: '" . $clang->gT('File name','js') . "' }; \n"; diff --git a/application/modules/FiveListQuestion.php b/application/modules/FiveListQuestion.php index 44b555c3d2c..b13d72f6897 100644 --- a/application/modules/FiveListQuestion.php +++ b/application/modules/FiveListQuestion.php @@ -57,6 +57,7 @@ public function getAnswerHTML() $('#$id input').each(function(){ $(this).removeAttr('checked');}); $('#answer$this->fieldname'+value).attr('checked','checked'); } + checkconditions(value,'$this->fieldname','radio'); } }); diff --git a/application/modules/FiveRadioArrayQuestion.php b/application/modules/FiveRadioArrayQuestion.php index 9e1a708ddb1..d823549cbbd 100644 --- a/application/modules/FiveRadioArrayQuestion.php +++ b/application/modules/FiveRadioArrayQuestion.php @@ -196,7 +196,7 @@ public function getAnswerArray($em) public function availableAttributes($attr = false) { - $attrs=array("answer_width","array_filter","array_filter_exclude","array_filter_style","statistics_showgraph","statistics_graphtype","hide_tip","hidden","max_answers","min_answers","page_break","public_statistics","random_order","parent_order","random_group"); + $attrs=array("answer_width","array_filter","array_filter_exclude","array_filter_style","em_validation_q","em_validation_q_tip","exclude_all_others","statistics_showgraph","statistics_graphtype","hide_tip","hidden","max_answers","min_answers","page_break","public_statistics","random_order","parent_order","random_group"); return $attr?array_key_exists($attr,$attrs):$attrs; } diff --git a/application/modules/HugeTextQuestion.php b/application/modules/HugeTextQuestion.php index 9e4203828e6..767c55cb74d 100644 --- a/application/modules/HugeTextQuestion.php +++ b/application/modules/HugeTextQuestion.php @@ -59,7 +59,7 @@ public function getAnswerHTML() // --> START NEW FEATURE - SAVE $answer = "

    "; $answer .=' + + gT("Message:", "js")."]",$surveyid,$gid,null,$action); ?> +

  • @@ -123,7 +125,5 @@ - gT("Message:", "js")."]",$surveyid,$gid,null,$action); - } + \ No newline at end of file diff --git a/application/views/admin/browse/browsetimeheader_view.php b/application/views/admin/browse/browsetimeheader_view.php deleted file mode 100644 index d13b636c421..00000000000 --- a/application/views/admin/browse/browsetimeheader_view.php +++ /dev/null @@ -1,43 +0,0 @@ -
    eT('Time statistics'); ?>
    - - - - diff --git a/application/views/admin/browse/browsetimerow_view.php b/application/views/admin/browse/browsetimerow_view.php deleted file mode 100644 index 042aa03701d..00000000000 --- a/application/views/admin/browse/browsetimerow_view.php +++ /dev/null @@ -1,9 +0,0 @@ - - - - - diff --git a/application/views/admin/dataentry/content_view.php b/application/views/admin/dataentry/content_view.php index f4ae4547e0e..3081243a947 100644 --- a/application/views/admin/dataentry/content_view.php +++ b/application/views/admin/dataentry/content_view.php @@ -405,7 +405,7 @@ function updateJSON() { $acomma = getRadixPointData($thissurvey['surveyls_numberformat']); $acomma = $acomma['seperator']; } - $title = $clang->gT('Only numbers may be entered in this field'); + $title = $clang->gT('Only numbers may be entered in this field.'); echo $prefix; ?> onkeypress="return goodchars(event,'-0123456789')" />
    eT("Record Deleted"); ?> (ID: )


    - ', '_top');" /> + ', '_top');" />

    diff --git a/application/views/admin/dataentry/insert.php b/application/views/admin/dataentry/insert.php index c1f225c635d..bf7dace1587 100644 --- a/application/views/admin/dataentry/insert.php +++ b/application/views/admin/dataentry/insert.php @@ -82,7 +82,7 @@

    - +

    diff --git a/application/views/admin/dataentry/vvimport_upload.php b/application/views/admin/dataentry/vvimport_upload.php index 8f66c1fa51d..5471d93c9bd 100644 --- a/application/views/admin/dataentry/vvimport_upload.php +++ b/application/views/admin/dataentry/vvimport_upload.php @@ -19,6 +19,6 @@ gT("Total records imported:") . ' ' . $importcount; ?>

    - [eT("Browse responses"); ?>] + [eT("Browse responses"); ?>]
      diff --git a/application/views/admin/export/exportresults_view.php b/application/views/admin/export/exportresults_view.php index b33d8dc87fe..258385ca525 100644 --- a/application/views/admin/export/exportresults_view.php +++ b/application/views/admin/export/exportresults_view.php @@ -10,22 +10,22 @@
    • eT("From");?> eT("to");?>
    • -

    • + + +
    - eT("Questions");?> + eT("Headings");?>
      -
    • -
    • -
    • -
    • -
    • -
    • +
    • +
    • +
    • +
    • +
    • +

    • @@ -33,10 +33,10 @@
    - eT("Answers");?> + eT("Responses");?>
    • -
    • +
    • @@ -46,22 +46,22 @@
    • + eT("Full answers");?>
    eT("Format");?>
      -
    • - -
    • +
    • onclick='document.getElementById("ansabbrev").disabled=false;' /> +
    • onclick='document.getElementById("ansabbrev").disabled=false;' />
    • -
    • onclick='document.getElementById(\"ansabbrev\").disabled=false;' /> -
    • -
    • " +
    • + +
    • +
    @@ -77,7 +77,7 @@ if (returnGlobal('id')<>'') { ?> eT("Choose Columns");?>: + $clang->eT("Choose columns");?>: 255) { echo "\t".$clang->gT("Help")."$aData) { - echo "\n"; + echo ">{$i}: {$sFieldName} - ".ellipsize(FlattenText($q->text,false,true),40,0.9)."\n"; $i++; } ?> @@ -114,9 +115,7 @@ db->schema->getTable("{{tokens_$surveyid}}")) { ?>
    eT("Token control");?> eT("Choose token fields");?>: - <?php $clang->eT("Help");?>
    + <?php $clang->eT("Help");?>
    - - +
  • diff --git a/application/views/admin/export/spss_view.php b/application/views/admin/export/spss_view.php index 4166b13e938..fd4468e6cf9 100644 --- a/application/views/admin/export/spss_view.php +++ b/application/views/admin/export/spss_view.php @@ -1,9 +1,9 @@
    eT("Export result data to SPSS");?>
      -
    • + +
    • diff --git a/application/views/admin/export/statistics_browse_view.php b/application/views/admin/export/statistics_browse_view.php new file mode 100644 index 00000000000..83fe22fa332 --- /dev/null +++ b/application/views/admin/export/statistics_browse_view.php @@ -0,0 +1,52 @@ +lang; +?> +
      + + + ' class='sortorder' id='sortorder__id__T' style='cursor: pointer' /> +
      +
      + + + ' class='sortorder' id='sortorder____' style='cursor: pointer' />
      +
      + + +
      + +
      +
      + \ No newline at end of file diff --git a/application/views/admin/export/statistics_view.php b/application/views/admin/export/statistics_view.php index c54d1c3cf72..e7818d04e54 100644 --- a/application/views/admin/export/statistics_view.php +++ b/application/views/admin/export/statistics_view.php @@ -6,162 +6,190 @@ exit; } ?> - + -
      eT("General filters"); ?>
      -
      - '.$clang->gT('You do not have the GD Library installed. Showing charts requires the GD library to function properly.'); - $error .= '
      '.$clang->gT('visit http://us2.php.net/manual/en/ref.image.php for more information').'
      '; - } - else if (!function_exists("imageftbbox")) { +
      +
      <?php $clang->eT("Maximize"); ?><?php $clang->eT("Minimize"); ?>
      + eT("General filters"); ?> +
      + +
    \n"; - echo ""; - echo ""; - echo ""; - } + if (isset($datestamp) && $datestamp == "Y") { + echo "\n"; + echo ""; + echo ""; + echo ""; + } - ?> + ?> -
    - eT("Output options"); ?> -
      -
    • - - />
      - $error
      "; } ?> -
    • - -
    • - - - - - - - -
    • -
    -
    +
    + eT("Output options"); ?> +
      +
    • + + />
      +
    • +
    • + + />
      + $error
      "; } ?> +
    • + +
    • + + + + + + + +
    • +
    +
    + +

    + + ', '_top')" /> +

    - -

    - - ', '_top')" /> -

    - +
    <?php $clang->eT("Maximize"); ?><?php $clang->eT("Minimize"); ?>
    eT("Response filters"); ?>
    - + +
     ".$ld." ".$ld."  ".$clang->gT('No answer')."
    ' name='markedresponses[]' /> - '><?php $clang->eT('/> - '><?php $clang->eT('/> - ' src='/token_delete.png' alt='eT('Delete this response'); ?>' class='deleteresponse'/> - $browsedatafield
    > - - $flt): ?> - - - + $flt) { + if (!isset($previousquestiontype)) {$previousquestiontype="";} + if ($flt[1] != $currentgroup) { + if ($currentgroup!='') { ?> - - + +
    - - (gT("Question group").$flt[1]; ?>) + + + + + + (gT("Question group").$flt[1]; ?>) +
    -
    - - - - - '> +
    + + + $previousquestiontype == ";")) { ?> - - - - - \n"; //get subqestions - $result[$key1] = Questions::getQuestionsForStatistics('title as code, question as answer', "parent_qid='$flt[0]' AND language = '{$language}'", 'question_order'); + $result[$key1] = Questions::model()->getQuestionsForStatistics('title as code, question as answer', "parent_qid='$flt[0]' AND language = '{$language}'", 'question_order'); $counter2=0; //loop through all answers @@ -858,7 +900,7 @@ $counter2=0; //check all the answers - foreach($result[$key1] as $row) + foreach($result[$key1] as $key=>$row) { $row=array_values($row); $myfield2 = $myfield . "$row[0]"; @@ -895,7 +937,7 @@ * - sortorder * - language */ - $fresult = $fresults[$key1][$key]; + $fresult = $fresults[$key1]; //for debugging only: //echo $fquery; @@ -948,7 +990,7 @@ for ($i=1; $i<=$count; $i++) { //adjust layout depending on counter - if ($counter2 == 4) {echo "\t\n\t\n"; $counter=0;} + if ($counter2 == 4) {echo "\t\n\t\n"; $counter2=0;} //myfield is the SGQ identifier //myfield2 is just used as comment in HTML like "R40X34X1721-1" @@ -980,7 +1022,7 @@ //pre-select if (isset($_POST[$myfield3]) && is_array($_POST[$myfield3]) && in_array("$ans[0]", $_POST[$myfield3])) {echo " selected";} - echo ">$ans[1]\n"; + echo ">".flattenText($ans[1])."\n"; } echo "\t\n\t\n"; @@ -1122,7 +1164,6 @@ //output checkbox and question/label text echo "\t
    + + - + /> + || array_search("N{$surveyid}X{$flt[1]}X{$flt[0]}", $summary) !== FALSE)) { echo " checked='checked'"; } + ?> /> +
    - - multiple='multiple'> + \n\t
    "; echo " - +
    @@ -1247,22 +1290,39 @@

    -
    + + +
    + +
    +
    <?php $clang->eT("Maximize"); ?><?php $clang->eT("Minimize"); ?>
    + eT("Statistics"); ?> +
    + +
    +
    lang; - $sImageURL = Yii::app()->getConfig("imageurl"); + $sImageURL = Yii::app()->getConfig('adminimageurl'); if(!isset($maxchars)) { $maxchars = 100; } $htmlhinttext=str_replace("'",''',$hinttext); //the string is already HTML except for single quotes so we just replace these only - $jshinttext=javascriptEscape($hinttext,true,true); + $jshinttext=javascriptEscape($hinttext,true,true); //Build a javascript safe version of the string if(strlen($hinttext) > ($maxchars)) { @@ -1271,15 +1331,15 @@ function _showSpeaker($hinttext) $shortstring = htmlspecialchars(mb_strcut(html_entity_decode($shortstring,ENT_QUOTES,'UTF-8'), 0, $maxchars, 'UTF-8')); //output with hoover effect - $reshtml= "gT("Question","js").": $jshinttext')\">" ." \"$shortstring...\" " - ."$htmlhinttextgT("Question","js").": $jshinttext')\" />"; } else { - $reshtml= " \"$htmlhinttext\""; + $reshtml= " \"$htmlhinttext\""; } return $reshtml; } diff --git a/application/views/admin/export/vv_view.php b/application/views/admin/export/vv_view.php index dff7e12853a..cbc848b5b62 100644 --- a/application/views/admin/export/vv_view.php +++ b/application/views/admin/export/vv_view.php @@ -2,19 +2,19 @@
    eT("Export a VV survey file");?>
    • - +
    • - - + +
    • - + *
    diff --git a/application/views/admin/expressions/test/survey_logic_file.php b/application/views/admin/expressions/test/survey_logic_file.php index 8e975618791..5b5ee0b33cb 100644 --- a/application/views/admin/expressions/test/survey_logic_file.php +++ b/application/views/admin/expressions/test/survey_logic_file.php @@ -6,6 +6,13 @@ } $_REQUEST[$key] = $val; } + $_REQUEST['LEM_PRETTY_PRINT_ALL_SYNTAX'] = 'Y'; + + $surveyinfo = getSurveyInfo(sanitize_int($_REQUEST['sid'])); + if (isset($surveyinfo['assessments']) && $surveyinfo['assessments']=='Y') + { + $_REQUEST['assessments'] = 'Y'; + } } $clang = Yii::app()->lang; @@ -107,9 +114,7 @@ SetSurveyLanguage($surveyid, $language); - - echo '

    ' . sprintf($clang->gT('Logic file for survey ID %s'),$surveyid) . "

    \n"; - + LimeExpressionManager::SetDirtyFlag(); $result = LimeExpressionManager::ShowSurveyLogicFile($surveyid, $gid, $qid,$LEMdebugLevel,$assessments); print $result['html']; @@ -118,4 +123,4 @@ EOD; } -?> \ No newline at end of file +?> diff --git a/application/views/admin/globalSettings_view.php b/application/views/admin/globalSettings_view.php index 98b739f29ab..aa152e4ca28 100644 --- a/application/views/admin/globalSettings_view.php +++ b/application/views/admin/globalSettings_view.php @@ -178,11 +178,11 @@ session['dateformat']); ?>
  • - eT("Server time:").' '.convertDateTimeFormat(date('Y-m-d H:i:s'),'Y-m-d H:i:s',$dateformatdata['phpdate'].' H:i')." - ". $clang->gT("Corrected time :").' '.convertDateTimeFormat(dateShift(date("Y-m-d H:i:s"), 'Y-m-d H:i:s', getGlobalSetting('timeadjust')),'Y-m-d H:i:s',$dateformatdata['phpdate'].' H:i'); ?> + gT("Server time:").' '.convertDateTimeFormat(date('Y-m-d H:i:s'),'Y-m-d H:i:s',$dateformatdata['phpdate'].' H:i')." - ". $clang->gT("Corrected time :").' '.convertDateTimeFormat(dateShift(date("Y-m-d H:i:s"), 'Y-m-d H:i:s', getGlobalSetting('timeadjust')),'Y-m-d H:i:s',$dateformatdata['phpdate'].' H:i'); ?>
  • -
  • -
  • +
  • +
  • @@ -471,15 +471,18 @@
      - -
    • - + + +
    diff --git a/application/views/admin/labels/editlabel_view.php b/application/views/admin/labels/editlabel_view.php index d7f05e93131..df534a7bb91 100644 --- a/application/views/admin/labels/editlabel_view.php +++ b/application/views/admin/labels/editlabel_view.php @@ -36,7 +36,7 @@ getController()->createUrl("admin/participants/getAttributeInfo_json"); ?>"; var editAttributeUrl = "getController()->createUrl("admin/participants/editAttributeInfo"); ?>"; var attributeControlCols = '["eT('Actions'); ?>", "eT('Attribute name'); ?>", "eT('Attribute type'); ?>", "eT('Visible in participants panel'); ?>"]'; - var attributeTypeSelections = "DD:eT("Drop-down list"); ?>;DP:eT("Date"); ?>;TB:eT("Text box"); ?>"; - var attributeTypeSearch = "eT("Drop-down list"); ?>:eT("Drop-down list"); ?>;eT("Date"); ?>:eT("Date"); ?>;eT("Text box"); ?>:eT("Text box"); ?>" + var attributeTypeSelections = "TB:eT("Text box"); ?>;DD:eT("Drop-down list"); ?>;DP:eT("Date"); ?>"; + var attributeTypeSearch = "eT("Text box"); ?>:eT("Text box"); ?>; eT("Date"); ?>:eT("Date"); ?>; eT("Drop-down list"); ?>:eT("Drop-down list"); ?>" var attributeEditUrl = "getController()->createUrl("admin/participants/viewAttribute/aid"); ?>"; +
    +
    + + +   + + +   +


    +
    +
    eT("Attribute management"); ?>

    diff --git a/application/views/admin/participants/attributeMapCSV_view.php b/application/views/admin/participants/attributeMapCSV_view.php index e3476f57b92..bb08fee6c3f 100644 --- a/application/views/admin/participants/attributeMapCSV_view.php +++ b/application/views/admin/participants/attributeMapCSV_view.php @@ -2,8 +2,8 @@ - " /> - " /> + " /> + " /> @@ -53,16 +53,27 @@ $value) { - echo "
  • " . $value['attribute_name'] . "
     
  • "; + echo "
  • " . $value['attribute_name'] . "
     
  • "; } ?> +
    + +

    eT("Duplicates will be detected using the participant_id field in this CSV file"); + } else { + $clang->eT("Duplicates will be detected by a combination of firstname, lastname and email addresses"); + } + + ?> +
    -

    " /> - " /> +

    " /> " onClick="window.location.reload();" /> + " />

    " style="display:none"> <?php $clang->eT('Loading...'); ?> diff --git a/application/views/admin/participants/attributeMapToken_view.php b/application/views/admin/participants/attributeMapToken_view.php index 87a0be971e7..c7dea697b83 100644 --- a/application/views/admin/participants/attributeMapToken_view.php +++ b/application/views/admin/participants/attributeMapToken_view.php @@ -1,5 +1,5 @@ -" /> +" /> @@ -10,47 +10,41 @@ var surveyId = "request->getQuery('sid'); ?>"; /* LANGUAGE */ - var attributesMappedText = "et("All the attributes are automatically mapped") ?>"; + var attributesMappedText = "et("There are no unmapped attributes") ?>"; var mustPairAttributeText= "et("You have to pair it with one attribute of the token table") ?>"; - var onlyOneAttributeMappedText="et("Only one central attribute is mapped with token attribute ") ?>"; + var onlyOneAttributeMappedText="et("Only one central attribute is mapped with token attribute") ?>"; var cannotAcceptTokenAttributesText="et("This list cannot accept token attributes.") ?>"; var addElementBelowText="et("You have to add the element below the list") ?>"; - -
    -
    Token Attributes
    +
    + + eT("Map your token attributes to an existing participant attribute or create a new one"); ?> + +
    + +
    +
    eT("Unmapped token attributes") ?>
      - $value) { - echo "
    • " . $value . "
    • "; //Passing attribute description as name of the attribute - } - ?> -
    -
      - $value) - { - echo "
    • " . $value . "
    • "; + echo "
    • " . $key . "
    • "; //Passing attribute description as name of the attribute } - ?> + } + ?>
    +
    - - -
    Attributes to be created
    +
    eT("Participant attributes to create") ?>
    - - -
    Central Attribute
    +
    eT("Existing participant attributes")?>

    + +
    + +

      +
    + +
      + +
    eT("Pre-mapped attributes") ?>

    +
      + $value) + { + echo "
    • " . $alreadymappedattdescription[$value] . "
    • "; + } + ?> +
    +
    + +
    +
    - -

    +

    + + + +

    Yii::app()->baseUrl . '/images/ajax-loader.gif', diff --git a/application/views/admin/participants/attributeMap_view.php b/application/views/admin/participants/attributeMap_view.php index 98340386d2c..b9a08e606d8 100644 --- a/application/views/admin/participants/attributeMap_view.php +++ b/application/views/admin/participants/attributeMap_view.php @@ -16,6 +16,13 @@ var cannotAcceptTokenAttributesText="et("This list cannot accept token attributes.") ?>"; + + +
    + + eT("Map your participant attributes to an existing token attribute or create a new one"); ?> + +
    -
    - - - -
    -
    -

    eT("Select any attributes you'd like use in your survey by dropping the attribute in the right hand column."); ?>
    - eT("Click on 'Continue' when you are done."); ?> -

    - -
    -
    eT("Already mapped"); ?>
    -
      - $value) - { - ?> -
    • - "> +
      eT("Unmapped participant attributes"); ?>
      +
        + $value) + { ?> -
      -
        +
      • $value) - { - ?> -
      • - -
      + } + ?> +
    +
    +
    +
    eT("Token attributes to create"); ?>
    +
      +
    +
    +
    +
    + eT("Existing token attributes"); ?>
    - + $value) + { + echo "
  • " . $value . "
  • "; + } ?> -
    -
    eT("Attributes to be created"); ?>
    -
      -
    -
    + + +
    +
    + +

      +
    +  ";} + if(!empty($alreadymappedattributename)) { + ?> +
    +
    eT("Pre-mapped attributes") ?>

    +
      $value) + { + ?> +
    • + +
    +
    + +
    + -
    -
    - eT("Token table attribute"); ?> -
    -
      - $value) - { - echo "
    • " . $value . "
    • "; - } - ?> -
    +
    eT("Standard token fields") ?>

    +
      +
    • eT("Token") ?>
    • +
    +
    + +
    eT("Note: Standard token fields cannot be automatically mapped") ?>
    - -
    + +
    +

    - -

    + + +

    Yii::app()->baseUrl . '/images/ajax-loader.gif', @@ -102,6 +113,8 @@ ); ?>
    " style="display:none"> - +
    -
    + + + \ No newline at end of file diff --git a/application/views/admin/participants/displayParticipants_view.php b/application/views/admin/participants/displayParticipants_view.php index e2ef2186b04..7dcc0eea7b9 100644 --- a/application/views/admin/participants/displayParticipants_view.php +++ b/application/views/admin/participants/displayParticipants_view.php @@ -45,7 +45,7 @@ foreach ($attributes as $row) { $attnames[] = '"' . $row['attribute_name'] . '"'; - $uidNames[] = '{ "name": "' . $row['attribute_name'] . '", "index":"' . $row['attribute_name'] . '", "sorttype":"string", "sortable": true, "align":"center"}'; + $uidNames[] = '{ "name": "' . $row['attribute_name'] . '", "index":"' . $row['attribute_id'] . '", "sorttype":"string", "sortable": true, "align":"center"}'; } $columnNames = ',' . implode(",", $attnames) . ''; //Add to the end of the standard list of columnNames } @@ -74,6 +74,7 @@ var notcontainsTxt="eT("Does not contain") ?>"; var greaterthanTxt="eT("Greater than") ?>"; var lessthanTxt="eT("Less than") ?>"; + var beginswithTxt="et("Begins with") ?>"; var andTxt="eT("AND") ?>"; var orTxt="eT("OR") ?>"; /* End search form titles */ @@ -84,8 +85,9 @@ var surveyIdColTxt="eT("Survey ID") ?>"; var tokenIdColTxt="eT("Token ID") ?>"; var dateAddedColTxt="eT("Date added") ?>"; + var dateInvitedColTxt="eT("Last invited") ?>"; + var dateCompletedColTxt="eT("Submitted") ?>"; var surveylinkUrl = "getController()->createUrl("admin/participants/getSurveyInfo_json/pid/"); ?>"; - /* Colnames and heading for attributes subgrid */ var attributesHeadingTxt="eT("Participant's attribute information") ?>"; var actionsColTxt="eT("Actions") ?>"; @@ -94,6 +96,7 @@ var attributeNameColTxt="eT("Attribute name") ?>"; var attributeValueColTxt="eT("Attribute value") ?>"; var attributePosValColTxt="eT("Possible attribute values") ?>"; + var addToSurveyTxt="eT("Add participants to a survey") ?>"; var resetBtn = "eT("Reset"); ?>"; var exportToCSVTitle = "eT("Export to CSV"); ?>"; @@ -102,6 +105,7 @@ var closeTxt = "eT("Close"); ?>"; var spTitle = "eT("Sharing participants..."); ?>"; var spAddBtn = "eT("Share the selected participants"); ?>"; + var shareParticipantTxt = "eT("Share participants with other users") ?>"; var sfNoUser = "eT("No other user in the system"); ?>"; var addpartTitle = "eT("Add participant to survey"); ?>"; var addAllInViewTxt="eT("Add all %s participants in your current list to a survey."); ?>"; @@ -125,12 +129,13 @@ var deleteMsg = "
    "+deletefrompanelmsg+"

    1. "+deletefrompanel+"
    2. "+deletefrompanelandtoken+"
    3. "+deletefrompaneltokenandresponse+"
    "; var searchBtn = "eT("Search") ?>"; var shareMsg = "eT("You can see and edit settings for shared participants in share panel.") ?>"; //PLEASE REVIEW - var jsonUrl = "getController()->createUrl("admin/participants/getParticipants_json"); ?>"; + var jsonUrl = "getController()->createUrl("admin/participants/".$urlsearch); ?>"; var jsonSearchUrl = "getController()->createUrl("admin/participants/getParticipantsResults_json/search/"); ?>"; var editUrl = "getController()->createUrl("admin/participants/editParticipant"); ?>"; var getSearchIDs = "getController()->createUrl("admin/participants/getSearchIDs"); ?>"; var getaddtosurveymsg = "getController()->createUrl("admin/participants/getaddtosurveymsg"); ?>"; var minusbutton = "getConfig('adminimageurl') . "deleteanswer.png" ?>"; + var imageurl = "getConfig('adminimageurl') ?>"; var addbutton = "getConfig('adminimageurl') . "plus.png" ?>"; var minusbuttonTxt = "eT("Remove search condition") ?>"; var addbuttonTxt = "eT("Add search condition") ?>"; @@ -153,7 +158,7 @@ colModels += '{ "name":"lastname", "index":"lastname", "sorttype":"string", "sortable": true,"width":120, "align":"center", "editable":true},'; colModels += '{ "name":"email", "index":"email","align":"center","width":300, "sorttype":"string", "sortable": true, "editable":true},'; colModels += '{ "name":"blacklisted", "index":"blacklisted","align":"center","width":80,"sorttype":"string", "sortable": true, "editable":true, "edittype":"checkbox", "editoptions":{ "value":"Y:N"}},'; - colModels += '{ "name":"surveys", "index":"surveys","align":"center", "sorttype":"int", "sortable": true,"width":80,"editable":false},'; + colModels += '{ "name":"survey", "index":"survey","align":"center", "sorttype":"int", "sortable": true,"width":80,"editable":false},'; $clang->gT("Select..."), 'equal' =>$clang->gT("Equals"), 'contains' =>$clang->gT("Contains"), + 'beginswith' =>$clang->gT("Begins with"), 'notequal' => $clang->gT("Not equal"), 'notcontains' => $clang->gT("Does not contain"), 'greaterthan' => $clang->gT("Greater than"), @@ -206,9 +212,8 @@

    -

    " />" /> +

    " />

    -
    " style="display:none">

    diff --git a/application/views/admin/participants/sharePanel_view.php b/application/views/admin/participants/sharePanel_view.php index 7a945bb0101..4e21f0287ab 100644 --- a/application/views/admin/participants/sharePanel_view.php +++ b/application/views/admin/participants/sharePanel_view.php @@ -1,7 +1,19 @@

    eT("Share panel"); ?>

    diff --git a/application/views/admin/participants/uploadSummary_view.php b/application/views/admin/participants/uploadSummary_view.php index a8056042e99..56fea41ce61 100644 --- a/application/views/admin/participants/uploadSummary_view.php +++ b/application/views/admin/participants/uploadSummary_view.php @@ -3,7 +3,7 @@ - " /> + " /> @@ -11,6 +11,7 @@ " . $clang->gT("CPDB CSV summary") . "
    "; + $uploadSummary .= "
    \n"; if (empty($errorinupload)) { $uploadSummary .= "
    " . $clang->gT('Uploaded CSV file successfully') . "
    "; @@ -20,25 +21,34 @@ } else { - $uploadSummary .= "
    " . $clang->gT("Failed to create token entries") . "
    "; + $uploadSummary .= "
    " . $clang->gT("No new participants were created") . "
    "; } if (!empty($recordcount)) { - $uploadSummary .= "
    • " . sprintf($clang->gT("%s records in CSV"), $recordcount) . "
    • "; + $uploadSummary .= "
      • " . sprintf($clang->gT("%s records found in CSV file"), $recordcount) . "
      • "; } if (!empty($mandatory)) { $uploadSummary .= "
      • " . sprintf($clang->gT("%s records have empty mandatory fields"), $mandatory) . "
      • "; } $uploadSummary .= "
      • " . sprintf($clang->gT("%s records met minumum requirements"), $mincriteria) . "
      • "; - $uploadSummary .= "
      • " . sprintf($clang->gT("%s records imported"), $imported) . "
      "; + $uploadSummary .= "
    • " . sprintf($clang->gT("%s new participants were created"), $imported) . "
    • "; + if($overwritten > 0) { + $uploadSummary .= "
    • ".sprintf($clang->gT("%s records were duplicate but had attributes updated"), $overwritten)."
    • "; + } + $uploadSummary .="
    "; if (count($duplicatelist) > 0 || count($invalidemaillist) > 0 || count($invalidattribute) > 0) { $uploadSummary .= "
    " . $clang->gT('Warnings') . "
      "; if (!empty($duplicatelist) && (count($duplicatelist) > 0)) { - $uploadSummary .= "
    • " . sprintf($clang->gT("%s duplicate records removed"), count($duplicatelist)); - $uploadSummary .= "
        "; + $uploadSummary .= "
      • " . sprintf($clang->gT("%s were found to be duplicate entries and did not need a new participant to be created"), count($duplicatelist)); + if($dupreason == "participant_id") { + $uploadSummary .= "
      • ".sprintf($clang->gT("They were found to be duplicate using the participant id field"))."
      • \n"; + } else { + $uploadSummary .= "
      • ".sprintf($clang->gT("They were found to be duplicate using a combination of firstname, lastname and email fields"))."
      • \n"; + } + $uploadSummary .= "
          "; foreach ($duplicatelist as $data) { $uploadSummary .= "
        • " . $data . "
        • "; @@ -66,7 +76,7 @@ $uploadSummary .= "
        "; } } - $uploadSummary .= "
      "; + $uploadSummary .= "
    "; } else { diff --git a/application/views/admin/participants/viewAttribute_view.php b/application/views/admin/participants/viewAttribute_view.php index 13430a48ba2..cec2330dc23 100644 --- a/application/views/admin/participants/viewAttribute_view.php +++ b/application/views/admin/participants/viewAttribute_view.php @@ -1,153 +1,196 @@ + + + + - - - -
    eT("Attribute settings"); ?>

    gT('Select...'); +foreach (getLanguageData(false, Yii::app()->session['adminlang']) as $langkey2 => $langname) +{ + $options[$langkey2] = $langname['description']; +} + echo CHtml::beginForm(Yii::app()->getController()->createUrl('admin/participants/saveAttribute/aid/' . Yii::app()->request->getQuery('aid')) . '/', "post"); -$plus = array('src' => Yii::app()->baseUrl . "/images/plus.png", - 'alt' => 'Add language', - 'title' => 'Add language', - 'id' => 'add', - 'hspace' => 2, - 'vspace' => -6); + ?> -
    - eT('Add a language:') ?> - gT('Select...'); - foreach (getLanguageData(false, Yii::app()->session['adminlang']) as $langkey2 => $langname) - { - $options[$langkey2] = $langname['description']; - } - echo CHtml::dropDownList('langdata', '', $options); - echo CHtml::image($plus['src'], $plus['alt'], array_slice($plus, 2)); - ?> -
    -

    -
    -