Skip to content

Commit

Permalink
DEV: implement SurveyActivator (#923)
Browse files Browse the repository at this point in the history
* dont use activateSurvey()

* Split activation to pieces 1

* Split activation to pieces 2

* Split activation to pieces 2

* fix brackets

* create directory

* remove activateSurvey from helper

* add phpdoc & return types

* Scrutinizer Auto-Fixes

This commit consists of patches automatically generated for this project on https://scrutinizer-ci.com

* less ifs

* replace raw SQl with createCommand()

* DEV: SurveyActivator make private methods protected

* Scrutinizer Auto-Fixes

This commit consists of patches automatically generated for this project on https://scrutinizer-ci.com

* Add tests

* DEV: surveyActivator : tests - assert tables created

* DEV: surveyActivator : tests - assert tokens table created

* Scrutinizer Auto-Fixes

This commit consists of patches automatically generated for this project on https://scrutinizer-ci.com

* DEV: activator - add directory separators
  • Loading branch information
TonisOrmisson committed Feb 4, 2018
1 parent 0c2c0d4 commit 5b936cb
Show file tree
Hide file tree
Showing 8 changed files with 881 additions and 256 deletions.
5 changes: 3 additions & 2 deletions application/controllers/admin/surveyadmin.php
Expand Up @@ -694,6 +694,7 @@ public function activate($iSurveyID)

$iSurveyID = (int) $iSurveyID;
$survey = Survey::model()->findByPk($iSurveyID);
$surveyActivator = new SurveyActivator($survey);

Yii::app()->user->setState('sql_'.$iSurveyID, ''); // If user has set some filters for responses from statistics on a previous activation, it must be wiped out
$aData = array();
Expand Down Expand Up @@ -724,7 +725,6 @@ public function activate($iSurveyID)

$this->_renderWrappedTemplate('survey', 'activateSurvey_view', $aData);
} else {
$survey = Survey::model()->findByAttributes(array('sid' => $iSurveyID));
if (!is_null($survey)) {
$survey->anonymized = Yii::app()->request->getPost('anonymized');
$survey->datestamp = Yii::app()->request->getPost('datestamp');
Expand All @@ -735,7 +735,8 @@ public function activate($iSurveyID)
Survey::model()->resetCache(); // Make sure the saved values will be picked up
}

$aResult = activateSurvey($iSurveyID);
$aResult = $surveyActivator->activate();

$aViewUrls = array();
if ((isset($aResult['error']) && $aResult['error'] == 'plugin')
|| (isset($aResult['blockFeedback']) && $aResult['blockFeedback'])) {
Expand Down
251 changes: 1 addition & 250 deletions application/helpers/admin/activate_helper.php
Expand Up @@ -244,258 +244,9 @@ function checkQuestions($postsid, $iSurveyID, $qtypes)
} else {
return false;
}
}

/**
* Function to activate a survey
* @param int $iSurveyID The Survey ID
* @param bool $simulate
* @return array
*/
function activateSurvey($iSurveyID, $simulate = false)
{
// Event beforeSurveyActivate
$oSurvey = Survey::model()->findByPk($iSurveyID);
$event = new PluginEvent('beforeSurveyActivate');
$event->set('surveyId', $iSurveyID);
$event->set('simulate', $simulate);
App()->getPluginManager()->dispatchEvent($event);
$success = $event->get('success');
$message = $event->get('message');
if ($success === false) {
Yii::app()->user->setFlash('error', $message);
return array('error' => 'plugin');
} else if (!empty($message)) {
Yii::app()->user->setFlash('info', $message);
}

$aTableDefinition = array();
$bCreateSurveyDir = false;
// Specify case sensitive collations for the token
$sCollation = '';
if (Yii::app()->db->driverName == 'mysqli' || Yii::app()->db->driverName == 'mysql') {
$sCollation = " COLLATE 'utf8mb4_bin'";
}
if (Yii::app()->db->driverName == 'sqlsrv' || Yii::app()->db->driverName == 'dblib' || Yii::app()->db->driverName == 'mssql') {
$sCollation = " COLLATE SQL_Latin1_General_CP1_CS_AS";
}
//Check for any additional fields for this survey and create necessary fields (token and datestamp)
$oSurvey->fixInvalidQuestions();
//Get list of questions for the base language
$sFieldMap = createFieldMap($oSurvey, 'full', true, false, $oSurvey->language);
//For each question, create the appropriate field(s)
foreach ($sFieldMap as $j=>$aRow) {
switch ($aRow['type']) {
case 'seed':
$aTableDefinition[$aRow['fieldname']] = "string(31)";
break;
case 'startlanguage':
$aTableDefinition[$aRow['fieldname']] = "string(20) NOT NULL";
break;
case 'id':
$aTableDefinition[$aRow['fieldname']] = "pk";
break;
case "startdate":
case "datestamp":
$aTableDefinition[$aRow['fieldname']] = "datetime NOT NULL";
break;
case "submitdate":
$aTableDefinition[$aRow['fieldname']] = "datetime";
break;
case "lastpage":
$aTableDefinition[$aRow['fieldname']] = "integer";
break;
case Question::QT_N_NUMERICAL: //Numerical
case Question::QT_K_MULTIPLE_NUMERICAL_QUESTION: //Multiple Numerical
$aTableDefinition[$aRow['fieldname']] = "decimal (30,10)";
break;
case Question::QT_S_SHORT_FREE_TEXT: //SHORT TEXT
$aTableDefinition[$aRow['fieldname']] = "text";
break;
case Question::QT_L_LIST_DROPDOWN: //LIST (RADIO)
case Question::QT_EXCLAMATION_LIST_DROPDOWN: //LIST (DROPDOWN)
case Question::QT_M_MULTIPLE_CHOICE: //Multiple choice
case Question::QT_P_MULTIPLE_CHOICE_WITH_COMMENTS: //Multiple choice with comment
case Question::QT_O_LIST_WITH_COMMENT: //DROPDOWN LIST WITH COMMENT
if ($aRow['aid'] != 'other' && strpos($aRow['aid'], 'comment') === false && strpos($aRow['aid'], 'othercomment') === false) {
$aTableDefinition[$aRow['fieldname']] = "string(5)";
} else {
$aTableDefinition[$aRow['fieldname']] = "text";
}
break;
case Question::QT_U_HUGE_FREE_TEXT: //Huge text
case Question::QT_Q_MULTIPLE_SHORT_TEXT: //Multiple short text
case Question::QT_T_LONG_FREE_TEXT: //LONG TEXT
case Question::QT_SEMICOLON_ARRAY_MULTI_FLEX_TEXT: //Multi Flexi
case Question::QT_COLON_ARRAY_MULTI_FLEX_NUMBERS: //Multi Flexi
$aTableDefinition[$aRow['fieldname']] = "text";
break;
case Question::QT_D_DATE: //DATE
$aTableDefinition[$aRow['fieldname']] = "datetime";
break;
case Question::QT_5_POINT_CHOICE: //5 Point Choice
case Question::QT_G_GENDER_DROPDOWN: //Gender
case Question::QT_Y_YES_NO_RADIO: //YesNo
case Question::QT_X_BOILERPLATE_QUESTION: //Boilerplate
$aTableDefinition[$aRow['fieldname']] = "string(1)";
break;
case Question::QT_I_LANGUAGE: //Language switch
$aTableDefinition[$aRow['fieldname']] = "string(20)";
break;
case Question::QT_VERTICAL_FILE_UPLOAD:
$bCreateSurveyDir = true;
if (strpos($aRow['fieldname'], "_")) {
$aTableDefinition[$aRow['fieldname']] = "integer";
} else {
$aTableDefinition[$aRow['fieldname']] = "text";
}
break;
case "ipaddress":
if ($oSurvey->ipaddr == "Y") {
$aTableDefinition[$aRow['fieldname']] = "text";
}
break;
case "url":
if ($oSurvey->refurl == "Y") {
$aTableDefinition[$aRow['fieldname']] = "text";
}
break;
case "token":
$aTableDefinition[$aRow['fieldname']] = 'string(35)'.$sCollation;
break;
case Question::QT_ASTERISK_EQUATION: // Equation
$aTableDefinition[$aRow['fieldname']] = "text";
break;
case Question::QT_R_RANKING_STYLE:
/**
* See bug #09828: Ranking question : update allowed can broke Survey DB
* If max_subquestions is not set or is invalid : set it to actual answers numbers
*/

$nrOfAnswers = Answer::model()->countByAttributes(
array('qid' => $aRow['qid'])
);
$oQuestionAttribute = QuestionAttribute::model()->find(
"qid = :qid AND attribute = 'max_subquestions'",
array(':qid' => $aRow['qid'])
);
if (empty($oQuestionAttribute)) {
$oQuestionAttribute = new QuestionAttribute();
$oQuestionAttribute->qid = $aRow['qid'];
$oQuestionAttribute->attribute = 'max_subquestions';
$oQuestionAttribute->value = $nrOfAnswers;
$oQuestionAttribute->save();
} elseif (intval($oQuestionAttribute->value) < 1) {
// Fix it if invalid : disallow 0, but need a sub question minimum for EM
$oQuestionAttribute->value = $nrOfAnswers;
$oQuestionAttribute->save();
}
$aTableDefinition[$aRow['fieldname']] = "string(5)";
break;
default:
$aTableDefinition[$aRow['fieldname']] = "string(5)";
}
if ($oSurvey->anonymized == 'N' && !array_key_exists('token', $aTableDefinition)) {
$aTableDefinition['token'] = 'string(35)'.$sCollation;
}
if ($simulate) {
$tempTrim = trim($aTableDefinition);
$brackets = strpos($tempTrim, "(");
if ($brackets === false) {
$type = substr($tempTrim, 0, 2);
} else {
$type = substr($tempTrim, 0, 2);
}
$arrSim[] = array($type);
}
}

if ($simulate) {
return array('dbengine'=>Yii::app()->db->getDriverName(), 'dbtype'=>Yii::app()->db->driverName, 'fields'=>$arrSim);
}

// If last question is of type MCABCEFHP^QKJR let's get rid of the ending coma in createsurvey

$sTableName = "{{survey_{$iSurveyID}}}";
Yii::app()->loadHelper("database");
try {
Yii::app()->db->createCommand()->createTable($sTableName, $aTableDefinition);
Yii::app()->db->schema->getTable($sTableName, true); // Refresh schema cache just in case the table existed in the past
} catch (CDbException $e) {
if (App()->getConfig('debug')) {
return array('error'=>$e->getMessage());
} else {
return array('error'=>'surveytablecreation');
}
}
try {
if (isset($aTableDefinition['token'])) {
Yii::app()->db->createCommand()->createIndex("idx_survey_token_{$iSurveyID}_".rand(1, 50000), $sTableName, 'token');
}
} catch (CDbException $e) {
}

$sQuery = "SELECT autonumber_start FROM {{surveys}} WHERE sid={$iSurveyID}";
$iAutoNumberStart = Yii::app()->db->createCommand($sQuery)->queryScalar();
//if there is an autonumber_start field, start auto numbering here
if ($iAutoNumberStart !== false && $iAutoNumberStart > 0) {
if (Yii::app()->db->driverName == 'mssql' || Yii::app()->db->driverName == 'sqlsrv' || Yii::app()->db->driverName == 'dblib') {
mssql_drop_primary_index('survey_'.$iSurveyID);
mssql_drop_constraint('id', 'survey_'.$iSurveyID);
$sQuery = "ALTER TABLE {{survey_{$iSurveyID}}} drop column id ";
Yii::app()->db->createCommand($sQuery)->execute();
$sQuery = "ALTER TABLE {{survey_{$iSurveyID}}} ADD [id] int identity({$iAutoNumberStart},1)";
Yii::app()->db->createCommand($sQuery)->execute();
// Add back the primaryKey

Yii::app()->db->createCommand()->addPrimaryKey('PRIMARY_'.rand(1, 50000), $oSurvey->responsesTableName, 'id');
} elseif (Yii::app()->db->driverName == 'pgsql') {
$sQuery = "SELECT setval(pg_get_serial_sequence('{{survey_{$iSurveyID}}}', 'id'),{$iAutoNumberStart},false);";
@Yii::app()->db->createCommand($sQuery)->execute();
} else {
$sQuery = "ALTER TABLE {{survey_{$iSurveyID}}} AUTO_INCREMENT = {$iAutoNumberStart}";
@Yii::app()->db->createCommand($sQuery)->execute();
}
}

if ($oSurvey->savetimings == "Y") {
$timingsfieldmap = createTimingsFieldMap($iSurveyID, "full", false, false, $oSurvey->language);

$aTimingTableDefinition = array();
$aTimingTableDefinition['id'] = 'integer';
foreach ($timingsfieldmap as $field=>$fielddata) {
$aTimingTableDefinition[$field] = 'FLOAT';
}

$sTableName = "{{survey_{$iSurveyID}_timings}}";
try {
Yii::app()->db->createCommand()->createTable($sTableName, $aTimingTableDefinition);
Yii::app()->db->createCommand()->addPrimaryKey('PK_Timing_'.rand(1, 50000), $sTableName, 'id');
Yii::app()->db->schema->getTable($sTableName, true); // Refresh schema cache just in case the table existed in the past
} catch (CDbException $e) {
return array('error'=>'timingstablecreation');
}

}
$aResult = array(
'status' => 'OK',
'pluginFeedback' => $event->get('pluginFeedback')
);
// create the survey directory where the uploaded files can be saved
if ($bCreateSurveyDir) {
if (!file_exists(Yii::app()->getConfig('uploaddir')."/surveys/".$iSurveyID."/files")) {
if (!(mkdir(Yii::app()->getConfig('uploaddir')."/surveys/".$iSurveyID."/files", 0777, true))) {
$aResult['warning'] = 'nouploadsurveydir';
} else {
file_put_contents(Yii::app()->getConfig('uploaddir')."/surveys/".$iSurveyID."/files/index.html", '<html><head></head><body></body></html>');
}
}
}
$sQuery = "UPDATE {{surveys}} SET active='Y' WHERE sid=".$iSurveyID;
Yii::app()->db->createCommand($sQuery)->query();
return $aResult;
}


/**
* @param string $fieldname
* @param string $tablename
Expand Down
10 changes: 8 additions & 2 deletions application/helpers/admin/import_helper.php
Expand Up @@ -1079,7 +1079,9 @@ function importSurveyFile($sFullFilePath, $bTranslateLinksFields, $sNewSurveyNam
}
// Activate the survey
Yii::app()->loadHelper("admin/activate");
activateSurvey($aImportResults['newsid']);
$survey = Survey::model()->findByPk($aImportResults['newsid']);
$surveyActivator = new SurveyActivator($survey);
$surveyActivator->activate();
unlink(Yii::app()->getConfig('tempdir').DIRECTORY_SEPARATOR.$aFile['filename']);
break;
}
Expand Down Expand Up @@ -1371,7 +1373,11 @@ function XMLImportSurvey($sFullFilePath, $sXMLdata = null, $sNewSurveyName = nul
}
// now translate any links
$insertdata['group_name'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['group_name']);
$insertdata['description'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['description']);

if (isset($insertdata['description'])) {
$insertdata['description'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['description']);
}

if (isset($aGIDReplacements[$insertdata['gid']])) {
$insertdata['gid'] = $aGIDReplacements[$insertdata['gid']];
} else {
Expand Down
3 changes: 2 additions & 1 deletion application/helpers/remotecontrol/remotecontrol_handle.php
Expand Up @@ -461,7 +461,8 @@ public function activate_survey($sSessionKey, $iSurveyID)
}
if (Permission::model()->hasSurveyPermission($iSurveyID, 'surveyactivation', 'update')) {
Yii::app()->loadHelper('admin/activate');
$aActivateResults = activateSurvey($iSurveyID);
$surveyActivator = new SurveyActivator($oSurvey);
$aActivateResults = $surveyActivator->activate();
if (isset($aActivateResults['error'])) {
return array('status' => 'Error: '.$aActivateResults['error']);
} else {
Expand Down

0 comments on commit 5b936cb

Please sign in to comment.