Skip to content

Commit

Permalink
Refactored surveymaintanceaction to use a model
Browse files Browse the repository at this point in the history
  • Loading branch information
mennodekker committed Jun 12, 2019
1 parent 224f155 commit 23e059a
Show file tree
Hide file tree
Showing 3 changed files with 467 additions and 368 deletions.
374 changes: 6 additions & 368 deletions classes/Gems/Default/SurveyMaintenanceAction.php
Expand Up @@ -152,161 +152,6 @@ public function answerImportsAction()
$this->answerImportAction(); $this->answerImportAction();
} }


/**
* A ModelAbstract->setOnLoad() function that takes care of transforming a
* dateformat read from the database to a \Zend_Date format
*
* If empty or \Zend_Db_Expression (after save) it will return just the value
* currently there are no checks for a valid date format.
*
* @see \MUtil_Model_ModelAbstract
*
* @param mixed $value The value being saved
* @param boolean $isNew True when a new item is being saved
* @param string $name The name of the current field
* @param array $context Optional, the other values being saved
* @param boolean $isPost True when passing on post data
* @return \MUtil_Date|\Zend_Db_Expr|string
*/
public function calculateDuration($value, $isNew = false, $name = null, array $context = array(), $isPost = false)
{
$surveyId = isset($context['gsu_id_survey']) ? $context['gsu_id_survey'] : false;
if (! $surveyId) {
return $this->_('incalculable');
}

$fields['cnt'] = 'COUNT(DISTINCT gto_id_token)';
$fields['avg'] = 'AVG(CASE WHEN gto_duration_in_sec > 0 THEN gto_duration_in_sec ELSE NULL END)';
$fields['std'] = 'STDDEV_POP(CASE WHEN gto_duration_in_sec > 0 THEN gto_duration_in_sec ELSE NULL END)';

$select = $this->loader->getTracker()->getTokenSelect($fields);
$select->forSurveyId($surveyId)
->onlyCompleted();

$row = $select->fetchRow();
if ($row) {
$trs = $this->util->getTranslated();
$seq = new \MUtil_Html_Sequence();
$seq->setGlue(\MUtil_Html::create('br', $this->view));

$seq->sprintf($this->_('Answered surveys: %d.'), $row['cnt']);
$seq->sprintf(
$this->_('Average answer time: %s.'),
$row['cnt'] ? $trs->formatTimeUnknown($row['avg']) : $this->_('n/a')
);
$seq->sprintf(
$this->_('Standard deviation: %s.'),
$row['cnt'] ? $trs->formatTimeUnknown($row['std']) : $this->_('n/a')
);

if ($row['cnt']) {
// Picked solution from http://stackoverflow.com/questions/1291152/simple-way-to-calculate-median-with-mysql
$sql = "SELECT t1.gto_duration_in_sec as median_val
FROM (SELECT @rownum:=@rownum+1 as `row_number`, gto_duration_in_sec
FROM gems__tokens, (SELECT @rownum:=0) r
WHERE gto_id_survey = ? AND gto_completion_time IS NOT NULL
ORDER BY gto_duration_in_sec
) AS t1,
(SELECT count(*) as total_rows
FROM gems__tokens
WHERE gto_id_survey = ? AND gto_completion_time IS NOT NULL
) as t2
WHERE t1.row_number = floor(total_rows / 2) + 1";
$med = $this->db->fetchOne($sql, array($surveyId, $surveyId));
if ($med) {
$seq->sprintf($this->_('Median value: %s.'), $trs->formatTimeUnknown($med));
}
// \MUtil_Echo::track($row, $med, $sql, $select->getSelect()->__toString());
} else {
$seq->append(sprintf($this->_('Median value: %s.'), $this->_('n/a')));
}

return $seq;
}
}

/**
* A ModelAbstract->setOnLoad() function that takes care of transforming a
* dateformat read from the database to a \Zend_Date format
*
* If empty or \Zend_Db_Expression (after save) it will return just the value
* currently there are no checks for a valid date format.
*
* @see \MUtil_Model_ModelAbstract
*
* @param mixed $value The value being saved
* @param boolean $isNew True when a new item is being saved
* @param string $name The name of the current field
* @param array $context Optional, the other values being saved
* @param boolean $isPost True when passing on post data
* @return \MUtil_Date|\Zend_Db_Expr|string
*/
public function calculateTrackCount($value, $isNew = false, $name = null, array $context = array(), $isPost = false)
{
$surveyId = isset($context['gsu_id_survey']) ? $context['gsu_id_survey'] : false;
if (! $surveyId) {
return 0;
}

$select = new \Zend_Db_Select($this->db);
$select->from('gems__rounds', array('useCnt' => 'COUNT(*)', 'trackCnt' => 'COUNT(DISTINCT gro_id_track)'));
$select->joinLeft('gems__tracks', 'gtr_id_track = gro_id_track', array())
->where('gro_id_survey = ?', $surveyId);
$counts = $select->query()->fetchObject();

if ($counts && ($counts->useCnt || $counts->trackCnt)) {
return sprintf($this->_('%d times in %d track(s).'), $counts->useCnt, $counts->trackCnt);
} else {
return $this->_('Not in any track.');
}
}

/**
* A ModelAbstract->setOnLoad() function that takes care of transforming a
* dateformat read from the database to a \Zend_Date format
*
* If empty or \Zend_Db_Expression (after save) it will return just the value
* currently there are no checks for a valid date format.
*
* @see \MUtil_Model_ModelAbstract
*
* @param mixed $value The value being saved
* @param boolean $isNew True when a new item is being saved
* @param string $name The name of the current field
* @param array $context Optional, the other values being saved
* @param boolean $isPost True when passing on post data
* @return \MUtil_Date|\Zend_Db_Expr|string
*/
public function calculateTrackUsage($value, $isNew = false, $name = null, array $context = array(), $isPost = false)
{
$surveyId = isset($context['gsu_id_survey']) ? $context['gsu_id_survey'] : false;
if (! $surveyId) {
return 0;
}

$select = new \Zend_Db_Select($this->db);
$select->from('gems__tracks', array('gtr_track_name'));
$select->joinLeft('gems__rounds', 'gro_id_track = gtr_id_track', array('useCnt' => 'COUNT(*)'))
->where('gro_id_survey = ?', $surveyId)
->group('gtr_track_name');
$usage = $this->db->fetchPairs($select);

if ($usage) {
$seq = new \MUtil_Html_Sequence();
$seq->setGlue(\MUtil_Html::create('br'));
foreach ($usage as $track => $count) {
$seq[] = sprintf($this->plural(
'%d time in %s track.',
'%d times in %s track.',
$count), $count, $track);
}
return $seq;

} else {
return $this->_('Not in any track.');
}
}

/** /**
* Check the tokens for a single survey * Check the tokens for a single survey
*/ */
Expand Down Expand Up @@ -354,229 +199,22 @@ public function checkAllAction()
*/ */
protected function createModel($detailed, $action) protected function createModel($detailed, $action)
{ {
$dbLookup = $this->util->getDbLookup(); $model = $this->loader->getModels()->getSurveyMaintenanceModel();
$survey = null;
$translated = $this->util->getTranslated();
$yesNo = $translated->getYesNo();


if ($detailed) { if ($detailed) {
$surveyId = $this->_getIdParam(); $surveyId = $this->_getIdParam();

if (('edit' == $action) || ('create' == $action)) {
if ($surveyId) { $model->applyEditSettings(('create' == $action), $surveyId);
$survey = $this->loader->getTracker()->getSurvey($surveyId); } else {
} $model->applyDetailSettings($surveyId);
}

$model = new \Gems_Model_JoinModel('surveys', 'gems__surveys', 'gus');
$model->addTable('gems__sources', array('gsu_id_source' => 'gso_id_source'));
$model->setCreate(false);

$model->addColumn(
"CASE WHEN gsu_survey_pdf IS NULL OR CHAR_LENGTH(gsu_survey_pdf) = 0 THEN 0 ELSE 1 END",
'gsu_has_pdf'
);
$model->addColumn(
sprintf(
"CASE WHEN (gsu_status IS NULL OR gsu_status = '') THEN '%s' ELSE gsu_status END",
$this->_('OK')
),
'gsu_status_show',
'gsu_status'
);
$model->addColumn(
"CASE WHEN gsu_surveyor_active THEN '' ELSE 'deleted' END",
'row_class'
);

$model->resetOrder();

$model->set('gsu_survey_name', 'label', $this->_('Name'),
'elementClass', 'Exhibitor'
);
$model->set('gsu_survey_description', 'label', $this->_('Description'),
'elementClass', 'Exhibitor',
'formatFunction', array(__CLASS__, 'formatDescription')
);
$model->set('gso_source_name', 'label', $this->_('Source'),
'elementClass', 'Exhibitor');
$model->set('gsu_surveyor_active', 'label', $this->_('Active in source'),
'elementClass', 'Exhibitor',
'multiOptions', $yesNo
);
$model->set('gsu_surveyor_id', 'label', $this->_('Source survey id'),
'elementClass', 'Exhibitor'
);
$model->set('gsu_status_show', 'label', $this->_('Status in source'),
'elementClass', 'Exhibitor');
$model->set('gsu_active', 'label', sprintf($this->_('Active in %s'), $this->project->getName()),
'elementClass', 'Checkbox',
'multiOptions', $yesNo
);
$model->set('gsu_id_primary_group', 'label', $this->_('Group'),
'description', $this->_('If empty, survey will never show up!'),
'multiOptions', $dbLookup->getGroups()
);

if ($detailed) {
$model->addDependency('CanEditDependency', 'gsu_surveyor_active', array('gsu_active'));
$model->set('gsu_active',
'validators[group]', new \MUtil_Validate_Require(
$model->get('gsu_active', 'label'),
'gsu_id_primary_group',
$model->get('gsu_id_primary_group', 'label')
));
}

$model->set('gsu_insertable', 'label', $this->_('Insertable'),
'description', $this->_('Can this survey be manually inserted into a track?'),
'elementClass', 'Checkbox',
'multiOptions', $yesNo,
'onclick', 'this.form.submit()'
);
if ($detailed) {
$model->set('gsu_valid_for_length', 'label', $this->_('Add to inserted end date'),
'description', $this->_('Add to the start date to calculate the end date when inserting.'),
'filter', 'Int'
);
$model->set('gsu_valid_for_unit', 'label', $this->_('Inserted end date unit'),
'description', $this->_('The unit used to calculate the end date when inserting the survey.'),
'multiOptions', $translated->getPeriodUnits()
);
$model->set('gsu_insert_organizations', 'label', $this->_('Insert organizations'),
'description', $this->_('The organizations where the survey may be inserted.'),
'elementClass', 'MultiCheckbox',
'multiOptions', $dbLookup->getOrganizations(),
'required', true
);
$ct = new \MUtil_Model_Type_ConcatenatedRow('|', $this->_(', '));
$ct->apply($model, 'gsu_insert_organizations');

if (($action == 'create') || ($action == 'edit')) {
$model->set('toggleOrg',
'elementClass', 'ToggleCheckboxes',
'selectorName', 'gsu_insert_organizations'
);
}

$switches = array(
0 => array(
'gsu_valid_for_length' => array('elementClass' => 'Hidden', 'label' => null),
'gsu_valid_for_unit' => array('elementClass' => 'Hidden', 'label' => null),
'gsu_insert_organizations' => array('elementClass' => 'Hidden', 'label' => null),
'toggleOrg' => array('elementClass' => 'Hidden', 'label' => null),
),
);
$model->addDependency(array('ValueSwitchDependency', $switches), 'gsu_insertable');
}

if ($detailed) {
$model->set('track_usage', 'label', $this->_('Usage'),
'elementClass', 'Exhibitor',
'noSort', true,
'no_text_search', true
);
$model->setOnLoad('track_usage', array($this, 'calculateTrackUsage'));

$model->set('calc_duration', 'label', $this->_('Duration calculated'),
'elementClass', 'Html',
'noSort', true,
'no_text_search', true
);
$model->setOnLoad('calc_duration', array($this, 'calculateDuration'));

$model->set('gsu_duration', 'label', $this->_('Duration description'),
'description', $this->_('Text to inform the respondent, e.g. "20 seconds" or "1 minute".')
);
if ($survey instanceof \Gems_Tracker_Survey) {
$surveyFields = $this->util->getTranslated()->getEmptyDropdownArray() +
$survey->getQuestionList($this->locale->getLanguage());
$model->set('gsu_result_field', 'label', $this->_('Result field'),
'multiOptions', $surveyFields
);
// $model->set('gsu_agenda_result', 'label', $this->_('Agenda field'));
} }
} else { } else {
$model->set('track_count', 'label', ' ', $model->applyBrowseSettings();
'elementClass', 'Exhibitor',
'noSort', true,
'no_text_search', true
);
$model->setOnLoad('track_count', array($this, 'calculateTrackCount'));
}
$model->set('gsu_code', 'label', $this->_('Survey code'),
'description', $this->_('Optional code name to link the survey to program code.'),
'size', 10);

$model->set('gsu_export_code', 'label', $this->_('Survey export code'),
'description', $this->_('A unique code indentifying this survey during track import'),
'size', 20);

if ($detailed) {
$events = $this->loader->getEvents();
$beforeOptions = $events->listSurveyBeforeAnsweringEvents();
if (count($beforeOptions) > 1) {
$model->set('gsu_beforeanswering_event', 'label', $this->_('Before answering'),
'multiOptions', $beforeOptions,
'elementClass', 'Select'
);
}
$completedOptions = $events->listSurveyCompletionEvents();
if (count($completedOptions) > 1) {
$model->set('gsu_completed_event', 'label', $this->_('After completion'),
'multiOptions', $completedOptions,
'elementClass', 'Select'
);
}
$displayOptions = $events->listSurveyDisplayEvents();
if (count($displayOptions) > 1) {
$model->set('gsu_display_event', 'label', $this->_('Answer display'),
'multiOptions', $displayOptions,
'elementClass', 'Select'
);
}

if (('show' !== $action) || $survey->hasPdf()) {
// Only the action changes from the current page
// and the right to see the pdf is the same as
// the right to see this page.
$pdfLink = \MUtil_Html::create(
'a',
array($this->getRequest()->getActionKey() => 'pdf'),
array(
'class' => 'pdf',
'target' => '_blank',
'type' => 'application/pdf',
'onclick' => 'event.cancelBubble = true;',
)
);

$model->set('gsu_survey_pdf', 'label', 'Pdf',
'accept', 'application/pdf',
'destination', $this->loader->getPdf()->getUploadDir('survey_pdfs'),
'elementClass', 'File',
'extension', 'pdf',
'filename', $surveyId,
'required', false,
'itemDisplay', $pdfLink,
'validators[pdf]', new \MUtil_Validate_Pdf()
);
}
} }


return $model; return $model;
} }


/**
* Strip all the tags, but keep the escaped characters
*
* @param string $value
* @return \MUtil_Html_Raw
*/
public static function formatDescription($value)
{
return \MUtil_Html::raw(strip_tags($value));
}

/** /**
* Set column usage to use for the browser. * Set column usage to use for the browser.
* *
Expand Down

0 comments on commit 23e059a

Please sign in to comment.