Skip to content

Commit

Permalink
Dev: Changed filename for R-datafile and made R-export button forward…
Browse files Browse the repository at this point in the history
… to the regular repose export screen also disabled log output for response export routines.
  • Loading branch information
mennodekker committed Oct 30, 2013
1 parent 299353a commit fa32918
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 284 deletions.
275 changes: 5 additions & 270 deletions application/controllers/admin/export.php
Expand Up @@ -298,6 +298,11 @@ public function exportresults()
$sFilter='';
}

// Now disable logging to prevent errors when for example database logging is on
foreach (App()->log->routes as $route)
{
$route->enabled = $route->enabled && !($route instanceOf CWebLogRoute);
}
$resultsService->exportSurvey($iSurveyID, $explang, $type, $options, $sFilter);

exit;
Expand Down Expand Up @@ -608,276 +613,6 @@ public function exportspss()
}
}

/*
* The SPSS DATA LIST / BEGIN DATA parser is rather simple minded, the number after the type
* specifier identifies the field width (maximum number of characters to scan)
* It will stop short of that number of characters, honouring quote delimited
* space separated strings, however if the width is too small the remaining data in the current
* line becomes part of the next column. Since we want to restrict this script to ONE scan of
* the data (scan & output at same time), the information needed to construct the
* DATA LIST is held in the $fields array, while the actual data is written to a
* to a temporary location, updating length (size) values in the $fields array as
* the tmp file is generated (uses @fwrite's return value rather than strlen).
* Final output renders $fields to a DATA LIST, and then stitches in the tmp file data.
*
* Optimization opportunities remain in the VALUE LABELS section, which runs a query / column
*/
public function exportr()
{
global $length_vallabel;
$iSurveyID = sanitize_int(Yii::app()->request->getParam('sid'));
$subaction = Yii::app()->request->getParam('subaction');

$clang = $this->getController()->lang;
//for scale 1=nominal, 2=ordinal, 3=scale

//$typeMap = $this->_getTypeMap();

$length_vallabel = '120'; // Set the max text length of Value Labels
$iLength = '25500'; // Set the max text length of Text Data
$length_varlabel = '25500'; // Set the max text length of Variable Labels
$headerComment = '';
// $tempFile = '';

if ( ! isset($iSurveyID) ) { $iSurveyID = returnGlobal('sid'); }
$filterstate = incompleteAnsFilterState();

$headerComment = '#$Rev: 10193 $' . " $filterstate.\n";

if ( isset($_POST['dldata']) ) $subaction = "dldata";
if ( isset($_POST['dlstructure']) ) $subaction = "dlstructure";

if ( ! isset($subaction) )
{
$selecthide = "";
$selectshow = "";
$selectinc = "";

switch ( $filterstate )
{
case "incomplete":
$selectinc = "selected='selected'";
break;
case "complete":
$selecthide = "selected='selected'";
break;
default:
$selectshow = "selected='selected'";
}

$data['selectinc'] = $selectinc;
$data['selecthide'] = $selecthide;
$data['selectshow'] = $selectshow;
$data['filename'] = "survey_" . $iSurveyID . "_R_syntax_file.R";
$data['surveyid'] = $iSurveyID;
$data['display']['menu_bars']['browse'] = $clang->gT("Export results");

$this->_renderWrappedTemplate('export', 'r_view', $data);
}
else
{
Yii::app()->loadHelper("admin/exportresults");
}


if ( $subaction == 'dldata' )
{
header("Content-Disposition: attachment; filename=survey_" . $iSurveyID . "_R_data_file.csv");
header("Content-type: text/comma-separated-values; charset=UTF-8");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Pragma: public");

$na = ""; //change to empty string instead of two double quotes to fix warnings on NA
SPSSExportData($iSurveyID, $iLength, $na='', $q='"', $header=TRUE);

exit;
}

if ( $subaction == 'dlstructure' )
{
header("Content-Disposition: attachment; filename=survey_" . $iSurveyID . "_R_syntax_file.R");
header("Content-type: application/download; charset=UTF-8");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Pragma: public");

echo $headerComment;

echo ('data <- read.csv("survey_' . $iSurveyID .'_R_data_file.csv", quote = "\'\"", na.strings=c("", "\"\""), stringsAsFactors=FALSE)');
echo ("\n\n");

// Build array that has to be returned
$fields = SPSSFieldMap($iSurveyID,"V");

//Now get the query string with all fields to export
$query = SPSSGetQuery($iSurveyID, 500, 0); // Sample first 500 responses for adjusting fieldmap
$result = $query->query();

$num_fields = 0;
//Now we check if we need to adjust the size of the field or the type of the field
foreach ( $result as $row )
{
if($num_fields==0) {
$num_fields = count($row);
}
$row = array_values($row);
$fieldno = 0;

while ( $fieldno < $num_fields )
{
//Performance improvement, don't recheck fields that have valuelabels
if ( ! isset($fields[$fieldno]['answers']) )
{
$strTmp = mb_substr(stripTagsFull($row[$fieldno]), 0, $iLength);
$len = mb_strlen($strTmp);

if ( $len > $fields[$fieldno]['size'] ) $fields[$fieldno]['size'] = $len;

if ( trim($strTmp) != '' )
{
if ( $fields[$fieldno]['SPSStype'] == 'F' && (isNumericExtended($strTmp) === FALSE || $fields[$fieldno]['size'] > 16) )
{
$fields[$fieldno]['SPSStype'] = 'A';
}
}
}

$fieldno++;
}
}
$result->close();

$errors = "";
$i = 1;
foreach ( $fields as $field )
{
if ( $field['SPSStype'] == 'DATETIME23.2' ) $field['size']='';

if ( $field['LStype'] == 'N' || $field['LStype'] == 'K' )
{
$field['size'] .= '.' . ($field['size'] - 1);
}

switch ( $field['SPSStype'] )
{
case 'F':
$type = "numeric";
break;
case 'A':
$type = "character";
break;
case 'DATETIME23.2':
case 'SDATE':
$type = "character";
//@TODO set $type to format for date
break;
}

if ( ! $field['hide'] )
{
echo("# LimeSurvey Field type: $field[SPSStype]\n");
echo "data[, " . $i . "] <- "
. "as.$type(data[, " . $i . "])\n";

echo 'attributes(data)$variable.labels[' . $i . '] <- "'
. addslashes(
htmlspecialchars_decode(
mb_substr(
stripTagsFull(
$field['VariableLabel']
), 0, $length_varlabel
)
)
)
. '"' . "\n";

// Create the value Labels!
if ( isset($field['answers']) )
{
$answers = $field['answers'];

//print out the value labels!
echo 'data[, ' . $i .'] <- factor(data[, ' . $i . '], levels=c(';

$str = "";
foreach ( $answers as $answer )
{
if ( $field['SPSStype'] == "F" && isNumericExtended($answer['code']) )
{
$str .= ",{$answer['code']}";
}
else
{
$str .= ",\"{$answer['code']}\"";
}
}

$str = mb_substr($str, 1);
echo $str . '),labels=c(';

$str = "";
foreach ( $answers as $answer )
{
$str .= ", \"{$answer['value']}\"";
}

$str = mb_substr($str, 2); // Remove leading comma and space

if ( $field['scale'] !== '' && $field['scale'] == 2 )
{
$scale = ", ordered=TRUE";
}
else
{
$scale = "";
}

echo("{$str}){$scale})\n");
}

//Rename the Variables (in case somethings goes wrong, we still have the OLD values
if ( isset($field['sql_name']) )
{
$ftitle = $field['title'];
if (!preg_match ("/^([a-z]|[A-Z])+.*$/", $ftitle))
{
$ftitle = "q_" . $ftitle;
}

$ftitle = str_replace(array("-",":",";","!"), array("_hyph_","_dd_","_dc_","_excl_"), $ftitle);

if ( ! $field['hide'] )
{
if ( $ftitle != $field['title'] )
{
$errors .= "# Variable name was incorrect and was changed from {$field['title']} to $ftitle .\n";
}

echo "names(data)[" . $i . "] <- "
. "\"". $ftitle . "\"\n"; // <AdV> added \n
}

$i++;
}
else
{
echo "#sql_name not set\n";
}
}
else
{
echo "#Field hidden\n";
}

echo "\n";

} // end foreach
echo $errors;
exit;
}


}

public function vvexport()
{
$iSurveyId = sanitize_int(Yii::app()->request->getParam('surveyid'));
Expand Down
8 changes: 7 additions & 1 deletion application/core/plugins/ExportR/RDataWriter.php
@@ -1,8 +1,14 @@
<?php
Yii::import('application.helpers.admin.export.*');
class RDataWriter extends CsvWriter {
public function init(\SurveyObj $survey, $sLanguageCode, \FormattingOptions $oOptions) {
public function init(\SurveyObj $survey, $sLanguageCode, \FormattingOptions $oOptions) {
parent::init($survey, $sLanguageCode, $oOptions);

// Change filename
$this->csvFilename = 'survey_' . $survey->id .'_R_data_file.csv';
// Skip the first line with headers
$this->doHeaders = false;

$oOptions->answerFormat = "short"; // force answer codes
$oOptions->convertN = true;
$oOptions->nValue = 1;
Expand Down
47 changes: 35 additions & 12 deletions application/helpers/admin/export/CsvWriter.php
Expand Up @@ -8,6 +8,21 @@ class CsvWriter extends Writer
* The open filehandle
*/
private $file = null;

/**
* The filename to use for the resulting file when output = display
*
* @var string
*/
protected $csvFilename = '';

/**
* Should headers be output? For example spss and r export use more or less
* the same output but do not need headers at all.
*
* @var boolean
*/
protected $doHeaders = true;

function __construct()
{
Expand All @@ -19,10 +34,10 @@ function __construct()
public function init(SurveyObj $survey, $sLanguageCode, FormattingOptions $oOptions)
{
parent::init($survey, $sLanguageCode, $oOptions);
if ($oOptions->output=='display') {
header("Content-Disposition: attachment; filename=results-survey".$survey->id.".csv");
header("Content-type: text/comma-separated-values; charset=UTF-8");
} elseif ($oOptions->output == 'file') {

$this->csvFilename = "results-survey".$survey->id.".csv";

if ($oOptions->output == 'file') {
$this->file = fopen($this->filename, 'w');
}

Expand All @@ -33,14 +48,22 @@ protected function outputRecord($headers, $values, FormattingOptions $oOptions)
$sRecord='';
if(!$this->hasOutputHeader)
{
$index = 0;
foreach ($headers as $header)
{
$headers[$index] = $this->csvEscape($header);
$index++;
if ($oOptions->output=='display') {
header("Content-Disposition: attachment; filename=" . $this->csvFilename);
header("Content-type: text/comma-separated-values; charset=UTF-8");
}

// If we don't want headers in our csv, for example in exports like r/spss etc. we suppress the header by setting this switch in the init
if ($this->doHeaders == true) {
$index = 0;
foreach ($headers as $header)
{
$headers[$index] = $this->csvEscape($header);
$index++;
}
//Output the header...once and only once.
$sRecord.=implode($this->separator, $headers) . PHP_EOL;
}
//Output the header...once and only once.
$sRecord.=implode($this->separator, $headers);
$this->hasOutputHeader = true;
}
//Output the values.
Expand All @@ -50,7 +73,7 @@ protected function outputRecord($headers, $values, FormattingOptions $oOptions)
$values[$index] = $this->csvEscape($value);
$index++;
}
$sRecord.=PHP_EOL.implode($this->separator, $values);
$sRecord.= implode($this->separator, $values) . PHP_EOL;
if ($oOptions->output=='display')
{
echo $sRecord;
Expand Down
2 changes: 1 addition & 1 deletion application/views/admin/responses/browsemenubar_view.php
Expand Up @@ -70,7 +70,7 @@
<a href='<?php echo $this->createUrl("admin/export/sa/exportspss/sid/$surveyid"); ?>'>
<img src='<?php echo $sImageURL; ?>exportspss.png' alt="<?php $clang->eT("Export results to a SPSS/PASW command file"); ?>" /></a>

<a href='<?php echo $this->createUrl("admin/export/sa/exportr/sid/$surveyid"); ?>'>
<a href='<?php echo $this->createUrl("admin/export/sa/exportresults/surveyid/$surveyid"); ?>'>
<img src='<?php echo $sImageURL; ?>exportr.png' alt='<?php $clang->eT("Export results to a R data file"); ?>' /></a>
<?php
}
Expand Down

0 comments on commit fa32918

Please sign in to comment.