classes/Gems/Export/ModelSource/AnswerExportModelSource.php
<?php
/**
*
* @package Gems
* @subpackage Export
* @author Jasper van Gestel <jvangestel@gmail.com>
* @copyright Copyright (c) 2015 Erasmus MC
* @license New BSD License
*/
/**
*
* @package Gems
* @subpackage Export
* @copyright Copyright (c) 2015 Erasmus MC
* @license New BSD License
* @since Class available since version 1.7.1
*/
class Gems_Export_ModelSource_AnswerExportModelSource extends \Gems_Export_ModelSource_ExportModelSourceAbstract
{
/**
*
* @var \Gems_Model_RespondentModel
*/
private $_respModel;
/**
*
* @var \Gems_User_User
*/
protected $currentUser;
/**
* Current filter
*
* @var array
*/
protected $filter;
/**
*
* @var \Gems_Form
*/
protected $form;
/**
* @var \Gems_Loader
*/
protected $loader;
/**
* @var \Zend_Locale
*/
protected $locale;
/**
*
* @var \MUtil_Model_ModelAbstract
*/
protected $model;
/**
* Add the default fields and optionally joins to the model
*
* @param MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addDefaultFieldsToExportModel(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
if (!$model->checkJoinExists('gems__respondent2org.gr2o_id_user', 'gems__tokens.gto_id_respondent')) {
$model->addTable('gems__respondent2org', array(
'gems__respondent2org.gr2o_id_user' => 'gems__tokens.gto_id_respondent',
'gems__respondent2org.gr2o_id_organization' => 'gems__tokens.gto_id_organization'), 'gr2o'
);
}
if (!$model->checkJoinExists('gems__respondent2track.gr2t_id_respondent_track', 'gems__tokens.gto_id_respondent_track')) {
$model->addTable('gems__respondent2track', array('gems__respondent2track.gr2t_id_respondent_track' => 'gems__tokens.gto_id_respondent_track'), 'gr2t');
}
if (!$model->checkJoinExists('gems__tracks.gtr_id_track', 'gems__tokens.gto_id_track')) {
$model->addTable('gems__tracks', array('gems__tracks.gtr_id_track' => 'gems__tokens.gto_id_track'), 'gtr');
}
if (!$model->checkJoinExists('gems__consents.gco_description', 'gems__respondent2org.gr2o_consent')) {
$model->addTable('gems__consents', array('gems__consents.gco_description' => 'gems__respondent2org.gr2o_consent'), 'gco');
}
if (!$model->checkJoinExists('gems__respondents.grs_id_user', 'gems__tokens.gto_id_respondent')) {
$model->addTable('gems__respondents', array(
'gems__respondents.grs_id_user' => 'gems__tokens.gto_id_respondent',
), 'grs');
}
$model->set('respondentid', 'label', $this->_('Respondent ID'), 'type', \MUtil_Model::TYPE_NUMERIC);
$model->set('organizationid', 'label', $this->_('Organization'), 'type', \MUtil_Model::TYPE_NUMERIC,
'multiOptions', $this->currentUser->getAllowedOrganizations()
);
// Add relation fields
$model->set('gto_id_relation', 'label', $this->_('Relation ID'), 'type', \MUtil_Model::TYPE_NUMERIC);
$model->set('forgroup', 'label', $this->_('Filler'), 'type', \MUtil_Model::TYPE_STRING);
// Add Consent
$model->set('consentcode', 'label', $this->_('Consent'), 'type', \MUtil_Model::TYPE_STRING);
$model->set('resptrackid', 'label', $this->_('Respondent track ID'), 'type', \MUtil_Model::TYPE_NUMERIC);
$model->set('gto_round_order', 'label', $this->_('Round order'));
$model->set('gto_round_description', 'label', $this->_('Round description'));
$model->set('gtr_track_name', 'label', $this->_('Track name'));
$model->set('gr2t_track_info', 'label', $this->_('Track description'));
// These are limesurvey fields, replace them with GemsTracker fields
//$model->set('submitdate', 'label', $this->_('Submit date'));
//$model->set('startdate', 'label', $this->_('Start date'));
//$model->set('datestamp', 'label', $this->_('Datestamp'));
$model->set('gto_completion_time', 'label', $this->_('Completion date'));
$model->set('gto_start_time', 'label', $this->_('Start time'));
$model->set('gto_valid_from', 'label', $this->_('Valid from'));
$model->set('gto_valid_until', 'label', $this->_('Valid until'));
$model->set('startlanguage', 'label', $this->_('Start language'));
$model->set('lastpage', 'label', $this->_('Last page'));
$model->set('gto_id_token', 'label', $this->_('Token'));
}
/**
* Extensible function for added project specific data extensions
*
* @param \MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addExtraDataToExportModel(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
$this->_addExtraTokenReceptionCode($model, $data, $prefixes);
$this->_addExtraTrackReceptionCode($model, $data, $prefixes);
$this->_addExtraTrackFields($model, $data, $prefixes);
$this->_addExtraTrackFieldsByCode($model, $data, $prefixes);
$this->_addExtraRespondentNumber($model, $data, $prefixes);
$this->_addExtraGenderAge($model, $data, $prefixes);
}
/**
*
* @param \MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addExtraGenderAge(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
if ($this->currentUser->hasPrivilege('pr.export.gender-age')) {
if (isset($data['export_resp_gender']) && $data['export_resp_gender']) {
$model->set('grs_gender', 'label', $this->getRespondentModel()->get('grs_gender', 'label'),
'type', \MUtil_Model::TYPE_STRING
);
$prefixes['P'][] = 'grs_gender';
}
if (isset($data['export_birth_year']) && $data['export_birth_year']) {
if (! $model->has('grs_birthyear')) {
$model->addColumn('YEAR(grs_birthday)', 'grs_birthyear');
}
$model->set('grs_birthyear', 'label', $this->_('Birth year'), 'type', \MUtil_Model::TYPE_NUMERIC);
$prefixes['P'][] = 'grs_birthyear';
}
if (isset($data['export_birth_month']) && $data['export_birth_month']) {
if (! $model->has('grs_birthmonth')) {
$model->addColumn('MONTH(grs_birthday)', 'grs_birthmonth');
}
$model->set('grs_birthmonth', 'label', $this->_('Birth month'), 'type', \MUtil_Model::TYPE_NUMERIC);
$prefixes['P'][] = 'grs_birthmonth';
}
if (isset($data['export_birth_yearmonth']) && $data['export_birth_yearmonth']) {
if (! $model->has('grs_birthyearmonth')) {
$model->addColumn("CONCAT(YEAR(grs_birthday), '/', LPAD(MONTH(grs_birthday), 2, '0'))", 'grs_birthyearmonth');
}
$model->set('grs_birthyearmonth', 'label', $this->_('Birth year/month'), 'type', \MUtil_Model::TYPE_STRING);
$prefixes['P'][] = 'grs_birthyearmonth';
}
}
}
/**
*
* @param \MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addExtraRespondentNumber(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
if ($this->currentUser->hasPrivilege('pr.export.add-resp-nr')) {
if (isset($data['export_resp_nr']) && $data['export_resp_nr']) {
$model->set('gr2o_patient_nr', 'label', $this->getRespondentModel()->get('gr2o_patient_nr', 'label'),
'type', \MUtil_Model::TYPE_STRING
);
$prefixes['P'][] = 'gr2o_patient_nr';
}
}
}
/**
*
* @param \MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addExtraTokenReceptionCode(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
if (isset($data['export_token_reception_code']) && $data['export_token_reception_code']) {
$model->set('gto_reception_code', 'label', $this->_('Token reception code'));
$prefixes['D'][] = 'gto_reception_code';
}
}
/**
*
* @param \MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addExtraTrackFields(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
if (isset($data['gto_id_track']) && $data['gto_id_track'] && isset($data['add_track_fields']) && $data['add_track_fields'] == 1) {
$engine = $this->loader->getTracker()->getTrackEngine($data['gto_id_track']);
$fieldNames = $engine->getFieldNames();
if (!empty($fieldNames)) {
$engine->addFieldsToModel($model, false, 'resptrackid');
$prefixes['TF'] = array_keys($engine->getFieldNames());
}
}
}
/**
* @param MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addExtraTrackFieldsByCode(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
if (isset($data['export_trackfield_codes'])) {
$includeCodes = array_map('trim', explode(',', $data['export_trackfield_codes']));
$codes = [];
foreach ($includeCodes as $name) {
if (!empty($name)) {
$model->set($name, 'label', $name);
$prefixes['TF'][] = $name;
$codes[] = $name;
}
}
if (!empty($codes)) {
$tracker = $this->loader->getTracker();
$transformer = new \Gems\Tracker\Model\AddTrackFieldsByCodeTransformer($tracker, $codes, 'resptrackid');
$model->addTransformer($transformer);
}
}
}
/**
*
* @param \MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addExtraTrackReceptionCode(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
if (isset($data['export_track_reception_code']) && $data['export_track_reception_code']) {
$model->set('gr2t_reception_code', 'label', $this->_('Track reception code'));
$prefixes['TF'][] = 'gr2t_reception_code';
}
}
/**
* Add manual order of fields
*
* @param MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addManualFields(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
if (isset($data['manualFields'])) {
$manualFields = $data['manualFields'];
if (!is_array($data['manualFields'])) {
$manualFields = explode(',', $manualFields);
}
$labels = $model->getCol('label');
// Reset labels and order
foreach($model->getItemNames() as $itemName) {
$model->remove($itemName, 'label');
}
$model->resetOrder();
$addedAnswers = false;
foreach($manualFields as $field) {
$field = trim($field);
if ($field == '{answers}') {
foreach($prefixes['A'] as $field) {
if ($label = $labels[$field]) {
$model->set($field, 'label', $label);
}
}
$addedAnswers = true;
continue;
}
$label = $field;
if (isset($labels[$field])) {
$label = $labels[$field];
}
$model->set($field, 'label', $label);
}
if (!$addedAnswers) {
foreach ($prefixes['A'] as $field) {
if ($label = $labels[$field]) {
$model->set($field, 'label', $label);
}
}
}
}
}
/**
* Add nested model fields to the export model
*
* @param MUtil_Model_ModelAbstract $model
* @param array $data
* @param array $prefixes
*/
protected function _addNestedFieldsToExportModel(\MUtil_Model_ModelAbstract $model, array $data, array &$prefixes)
{
// Set labels in the main model for the submodel fields
if ($model->getMeta('nested', false)) {
$nestedNames = $model->getMeta('nestedNames');
foreach($nestedNames as $nestedName) {
$nestedModel = $model->get($nestedName, 'model');
$nestedLabels = $nestedModel->getcolNames('label');
foreach($nestedLabels as $colName) {
$label = $nestedModel->get($colName, 'label');
$model->set($colName, 'label', $label);
}
$model->remove($nestedName, 'label');
}
}
}
/**
* Add all survey answers to the export model
*
* @param MUtil_Model_ModelAbstract $model
* @param Gems_Tracker_Survey $survey
* @param array $data
* @param array $prefixes
*/
protected function _addSurveyAnswersToExportModel(\MUtil_Model_ModelAbstract $model, \Gems_Tracker_Survey $survey, array $data, array &$prefixes)
{
$prefixes['A'] = [];
$language = $this->locale->getLanguage();
$questions = $survey->getQuestionList($language);
$questionInformation = $survey->getQuestionInformation($language);
foreach($questions as $questionName => $label) {
if ($parent = $model->get($questionName, 'parent_question')) {
if ($model->get($parent, 'type') === \MUtil_Model::TYPE_NOVALUE) {
if (isset($data['subquestions']) && $data['subquestions'] == 'prefix_child') {
$cleanLabel = strip_tags($label);
$model->set($questionName, 'label', $cleanLabel);
}
if (isset($data['subquestions']) && $data['subquestions'] == 'show_parent') {
if (!in_array($parent, $prefixes['A'])) {
$prefixes['A'][] = $parent;
if (isset($questionInformation[$parent], $questionInformation[$parent]['question'])) {
$cleanLabel = strip_tags($questionInformation[$parent]['question']);
$model->set($parent, 'label', $cleanLabel);
}
}
} else {
$model->remove($parent, 'label');
}
}
}
if ($question = $model->get($questionName, 'survey_question') && $model->get($questionName, 'label') == null) {
$model->set($questionName, 'label', $questionName);
if (isset($questionInformation[$questionName], $questionInformation[$questionName]['question'])) {
$cleanLabel = strip_tags($questionInformation[$questionName]['question']);
$model->set($questionName, 'label', $cleanLabel);
}
}
$prefixes['A'][] = $questionName;
}
}
/**
* Add the survey source attributes to the export model that have not yet been set.
*
* @param MUtil_Model_ModelAbstract $model
* @param Gems_Tracker_Survey $survey
* @param array $data
* @param array $prefixes
* @throws Gems_Exception
*/
protected function _addSurveySourceAttributesToExportModel(\MUtil_Model_ModelAbstract $model, \Gems_Tracker_Survey $survey, array $data, array &$prefixes)
{
$source = $survey->getSource();
$attributes = $source->getAttributes();
$preExistingFields = $model->getColNames('label');
$attributes = array_diff($attributes, $preExistingFields);
foreach($attributes as $attribute) {
$model->set($attribute, 'label', $attribute);
}
}
/**
* Creates a \Zend_Form_Element_Select
*
* If $options is a string it is assumed to contain an SQL statement.
*
* @param string $name Name of the element
* @param string $label Label for element
* @param string $description Optional description
* @return \Zend_Form_Element_Checkbox
*/
protected function _createCheckboxElement($name, $label, $description = null)
{
if ($name && $label) {
$element = $this->form->createElement('checkbox', $name);
$element->setLabel($label);
$element->getDecorator('Label')->setOption('placement', \Zend_Form_Decorator_Abstract::APPEND);
if ($description) {
$element->setDescription($description);
$element->setAttrib('title', $description);
}
return $element;
}
}
/**
* Get form elements for the specific Export
*
* @param \Gems_Form $form existing form type
* @param array data existing options set in the form
* @return array of form elements
*/
public function getExtraDataFormElements(\Gems_Form $form, $data)
{
$this->form = $form;
$elements = [];
if (isset($data['gto_id_track']) && $data['gto_id_track']) {
$elements['add_track_fields'] = $this->_createCheckboxElement(
'add_track_fields',
$this->_('Track fields'),
$this->_('Add track fields to export')
);
}
if ($this->currentUser->hasPrivilege('pr.export.add-resp-nr')) {
$elements['export_resp_nr'] = $this->_createCheckboxElement(
'export_resp_nr',
$this->getRespondentModel()->get('gr2o_patient_nr', 'label'),
$this->_('Add respondent nr to export')
);
}
if ($this->currentUser->hasPrivilege('pr.export.gender-age')) {
$elements['export_resp_gender'] = $this->_createCheckboxElement(
'export_resp_gender',
$this->_('Respondent gender'),
$this->_('Add respondent gender to export')
);
$elements['export_birth_year'] = $this->_createCheckboxElement(
'export_birth_year',
$this->_('Respondent birth year'),
$this->_('Add respondent birth year to export')
);
$elements['export_birth_month'] = $this->_createCheckboxElement(
'export_birth_month',
$this->_('Respondent birth month'),
$this->_('Add respondent birth month to export')
);
$elements['export_birth_yearmonth'] = $this->_createCheckboxElement(
'export_birth_yearmonth',
$this->_('Respondent birth year/month'),
$this->_('Add respondent birth year and month to export')
);
}
$elements['export_track_reception_code'] = $this->_createCheckboxElement(
'export_track_reception_code',
$this->_('Track reception code'),
$this->_('Add reception code of track')
);
$elements['export_token_reception_code'] = $this->_createCheckboxElement(
'export_token_reception_code',
$this->_('Token reception code'),
$this->_('Add reception code of token')
);
return $elements;
}
/**
* Get the model to export
* @param array $filter Filter for the model
* @param array $data Data from the form options
* @return \MUtil_Model_ModelAbstract
*/
public function getModel($filter = array(), $data = array())
{
if ($filter !== $this->filter || !$this->model) {
$this->filter = $filter;
$surveyId = $filter['gto_id_survey'];
$language = $this->locale->getLanguage();
$survey = $this->loader->getTracker()->getSurvey($surveyId);
$model = $survey->getAnswerModel($language);
// Reset labels and order
foreach($model->getItemNames() as $itemName) {
$model->remove($itemName, 'label');
}
$model->resetOrder();
$prefixes = [];
$this->_addDefaultFieldsToExportModel($model, $data, $prefixes);
$this->_addNestedFieldsToExportModel($model, $data, $prefixes);
$this->_addSurveySourceAttributesToExportModel($model, $survey, $data, $prefixes);
$this->_addSurveyAnswersToExportModel($model, $survey, $data, $prefixes);
$prefixes['D'] = array_diff($model->getColNames('label'), $prefixes['A'], $model->getItemsFor('table', 'gems__respondent2org'));
$this->_addExtraDataToExportModel($model, $data, $prefixes);
if (isset($data['column_identifiers']) && $data['column_identifiers'] == 1) {
foreach ($prefixes as $prefix => $prefixCategory) {
foreach($prefixCategory as $columnName) {
if ($label = $model->get($columnName, 'label')) {
$model->set($columnName, 'label', '(' . $prefix . ') ' . $label);
}
}
}
}
$this->_addManualFields($model, $data, $prefixes);
$this->model = $model;
// Exclude external fields from sorting
foreach($this->model->getItemsUsed() as $item) {
if (!$this->model->get($item, 'table', 'column_expression')) {
$this->model->set($item, 'noSort', true);
}
}
}
return $this->model;
}
/**
*
* @return \Gems_Model_RespondentModel
*/
protected function getRespondentModel()
{
if (! $this->_respModel) {
$this->_respModel = $this->loader->getModels()->getRespondentModel(true);
}
return $this->_respModel;
}
}