GemsTracker/gemstracker-library

View on GitHub
classes/Gems/Tracker/Model/RespondentTrackModel.php

Summary

Maintainability
B
6 hrs
Test Coverage
A
93%
<?php

/**
 *
 * @package    Gems
 * @subpackage Tracker_Model
 * @author     Matijs de Jong <mjong@magnafacta.nl>
 * @copyright  Copyright (c) 2011 Erasmus MC
 * @license    New BSD License
 */

use MUtil\Model\Dependency\OffOnElementsDependency;

/**
 * The RespondentTrackModel is the model used to display and edit
 * respondent tracks in snippets.
 *
 * The main additions to a standard JoinModel are for filling in the
 * respondent and track info while creating new tracks and key
 * fiddling code for the different use cases.
 *
 * The respondent track model combines all possible information
 * about the respondents track from the tables:
 * - gems__reception_codes
 * - gems__respondent2org
 * - gems__respondent2track
 * - gems__respondents
 * - gems__staff (on created by)
 * - gems__tracks
 *
 * @package    Gems
 * @subpackage Tracker_Model
 * @copyright  Copyright (c) 2011 Erasmus MC
 * @license    New BSD License
 * @since      Class available since version 1.4
 */
class Gems_Tracker_Model_RespondentTrackModel extends \Gems_Model_HiddenOrganizationModel
{
    /**
     *
     * @var boolean When true the labels of wholly masked items are removed
     */
    protected $hideWhollyMasked = true;

    /**
     * @var \Gems_Loader
     */
    protected $loader;

    /**
     *
     * @var \Gems_Util
     */
    protected $util;

    /**
     * Default constructor
     *
     * @param string $name Optional different name for model
     */
    public function __construct($name = 'surveys')
    {
        parent::__construct($name, 'gems__respondent2track', 'gr2t', true);
        $this->addTable('gems__respondents',     array('gr2t_id_user' => 'grs_id_user'), 'grs', false);
        $this->addTable(
                'gems__respondent2org',
                array('gr2t_id_user' => 'gr2o_id_user', 'gr2t_id_organization' => 'gr2o_id_organization'),
                'gr2o',
                false
                );
        $this->addTable('gems__tracks',          array('gr2t_id_track' => 'gtr_id_track'), 'gtr', false);
        $this->addTable('gems__reception_codes', array('gr2t_reception_code' => 'grc_id_reception_code'), 'grc', false);
        $this->addLeftTable('gems__staff',       array('gr2t_created_by' => 'gsf_id_user'));

        // No need to send all this information to the user
        $this->setCol($this->getItemsFor('table', 'gems__staff'), 'elementClass', 'None');

        // TODO: altkeys implementatie
        // $this->setKeys($this->_getKeysFor('gems__respondent2track');
        $this->setKeys($this->_getKeysFor('gems__respondent2org') + $this->_getKeysFor('gems__tracks'));

        $this->addColumn(
            "CASE WHEN gsf_id_user IS NULL
                THEN '-'
                ELSE
                    CONCAT(
                        COALESCE(gsf_last_name, ''),
                        ', ',
                        COALESCE(gsf_first_name, ''),
                        COALESCE(CONCAT(' ', gsf_surname_prefix), '')
                    )
                END",
            'assigned_by');
        $this->addColumn(
            "CASE WHEN grc_success = 1 THEN '' ELSE 'deleted' END",
            'row_class');

        $this->addColumn(
            "CASE WHEN grc_success = 1 THEN 1 ELSE 0 END",
            'can_edit');

        $this->addColumn("CONCAT(COALESCE(CONCAT(grs_last_name, ', '), '-, '), COALESCE(CONCAT(grs_first_name, ' '), ''), COALESCE(grs_surname_prefix, ''))",
            'respondent_name');
    }

    /**
     * Add tracking off manual end date changes by the user
     *
     * @param mixed $value The value to store when the tracked field has changed
     * @return \Gems_Tracker_Model_StandardTokenModel
     */
    public function addEditTracking()
    {
        $this->addDependency(new OffOnElementsDependency('gr2t_end_date_manual',  'gr2t_end_date', 'readonly', $this));

        return $this;
    }

    /**
     * Set those settings needed for the browse display
     *
     * @return \Gems_Model_RespondentTrackModel
     */
    public function applyBrowseSettings()
    {
        $formatDate = $this->util->getTranslated()->formatDate;

        $this->resetOrder();

        $this->setKeys(array(
            \Gems_Model::RESPONDENT_TRACK => 'gr2t_id_respondent_track',
            \MUtil_Model::REQUEST_ID1     => 'gr2o_patient_nr',
            \MUtil_Model::REQUEST_ID2 => 'gr2o_id_organization',
            ));

        $this->set('gtr_track_name',    'label', $this->_('Track'));
        $this->set('gr2t_track_info',   'label', $this->_('Description'),
            'description', $this->_('Enter the particulars concerning the assignment to this respondent.'));
        $this->set('assigned_by',       'label', $this->_('Assigned by'));
        $this->set('gr2t_start_date',   'label', $this->_('Start'),
            'dateFormat', 'dd-MM-yyyy',
            'formatFunction', $formatDate,
            'default', new \Zend_Date());
        $this->set('gr2t_end_date',   'label', $this->_('Ending on'),
            'dateFormat', 'dd-MM-yyyy',
            'formatFunction', $formatDate);
        $this->set('gr2t_reception_code');
        $this->set('gr2t_comment',       'label', $this->_('Comment'));

        $this->addColumn('CONCAT(gr2t_completed, \'' . $this->_(' of ') . '\', gr2t_count)', 'progress');
        $this->set('progress', 'label', $this->_('Progress'));

        $this->loader->getModels()->addDatabaseTranslations($this);

        return $this;
    }

    /**
     * Set those settings needed for the detailed display
     *
     * @param \Gems_Tracker_Engine_TrackEngineInterface $trackEngine
     * @param boolean $edit When true the fields are added in edit mode
     * @return \Gems_Model_RespondentTrackModel
     */
    public function applyDetailSettings(\Gems_Tracker_Engine_TrackEngineInterface $trackEngine, $edit = false)
    {
        $this->resetOrder();

        $translated = $this->util->getTranslated();
        $formatDate = $this->util->getTranslated()->formatDate;

        $this->set('gr2o_patient_nr',   'label', $this->_('Respondent number'));
        $this->set('respondent_name',   'label', $this->_('Respondent name'));
        $this->set('gtr_track_name',    'label', $this->_('Track'));

        $mailCodes = $this->util->getDbLookup()->getRespondentTrackMailCodes();
        end($mailCodes);
        $defaultMailCode = key($mailCodes);
        $this->set('gr2t_mailable',
                'label', $this->_('May be mailed'),
                'default', $defaultMailCode,
                'elementClass', 'radio',
                'separator', ' ',
                'multiOptions', $mailCodes 
                );

        $this->set('assigned_by',          'label', $this->_('Assigned by'));
        $this->set('gr2t_start_date',      'label', $this->_('Start'),
            'dateFormat', 'dd-MM-yyyy',
            'formatFunction', $formatDate);

        // Integrate fields
        $trackEngine->addFieldsToModel($this, $edit);

        $this->set('gr2t_end_date_manual', 'label', $this->_('Set ending on'),
                'description', $this->_('Manually set dates are fixed and will never be (re)calculated.'),
                'elementClass', 'Radio',
                'multiOptions', $translated->getDateCalculationOptions(),
                'separator', ' '
                );
        $this->set('gr2t_end_date',        'label', $this->_('Ending on'),
            'dateFormat', 'dd-MM-yyyy',
            'formatFunction', $formatDate);
        $this->set('gr2t_track_info',      'label', $this->_('Description'));
        $this->set('gr2t_comment',         'label', $this->_('Comment'));
        $this->set('grc_description',      'label', $this->_('Reception code'),
                'elementClass', 'Exhibitor');
        $this->refreshGroupSettings();

        return $this;
    }

    /**
     * Set those values needed for editing
     *
     * @param \Gems_Tracker_Engine_TrackEngineInterface $trackEngine
     * @return \Gems_Model_RespondentTrackModel
     */
    public function applyEditSettings(\Gems_Tracker_Engine_TrackEngineInterface $trackEngine)
    {
        $this->applyDetailSettings($trackEngine, true);
        $this->addEditTracking();

        $this->set('gr2o_patient_nr',     'elementClass', 'Exhibitor');
        $this->set('respondent_name',     'elementClass', 'Exhibitor');
        $this->set('gtr_track_name',      'elementClass', 'Exhibitor');

        // Fields set in details

        $this->set('gr2t_track_info',     'elementClass', 'None');
        $this->set('assigned_by',         'elementClass', 'None');
        $this->set('gr2t_reception_code', 'elementClass', 'None');
        $this->set('gr2t_start_date',     'elementClass', 'Date',
                'default',  new \Zend_Date(),
                'required', true,
                'size',     30
                );
        $this->set('gr2t_end_date',   'elementClass', 'Date',
                'default', null,
                'size',    30
                );
        $this->set('gr2t_comment',    'elementClass', 'Textarea',
                'cols', 80,
                'rows', 5
                );

        $this->loader->getModels()->addDatabaseTranslations($this);

        return $this;
    }

    /**
     * Stores the fields that can be used for sorting or filtering in the
     * sort / filter objects attached to this model.
     *
     * @param array $parameters
     * @param boolean $includeNumericFilters When true numeric filter keys (0, 1, 2...) are added to the filter as well
     * @return array The $parameters minus the sort & textsearch keys
     */
    public function applyParameters(array $parameters, $includeNumericFilters = false)
    {
        if ($parameters) {
            // Altkey
            if (isset($parameters[\Gems_Model::RESPONDENT_TRACK])) {
                $id = $parameters[\Gems_Model::RESPONDENT_TRACK];
                unset($parameters[\Gems_Model::RESPONDENT_TRACK]);
                $parameters['gr2t_id_respondent_track'] = $id;
            }

            if (isset($parameters[\Gems_Model::TRACK_ID])) {
                $id = $parameters[\Gems_Model::TRACK_ID];
                unset($parameters[\Gems_Model::TRACK_ID]);
                $parameters['gtr_id_track'] = $id;
            }

            return parent::applyParameters($parameters, $includeNumericFilters);
        }

        return array();
    }

    /**
     * Creates new items - in memory only. Extended to load information from linked table using $filter().
     *
     * When $filter contains the keys gr2o_patient_nr and gr2o_id_organization the corresponding respondent
     * information is loaded into the new item.
     *
     * When $filter contains the key gtr_id_track the corresponding track information is loaded.
     *
     * The $filter values are also propagated to the corresponding key values in the new item.
     *
     * @param int $count When null a single new item is return, otherwise a nested array with $count new items
     * @param array $filter Allowed key values: gr2o_patient_nr, gr2o_id_organization and gtr_id_track
     * @return array Nested when $count is not null, otherwise just a simple array
     */
    public function loadNew($count = null, array $filter = null)
    {
        $values = array();

        // Get the defaults
        foreach ($this->getItemNames() as $name) {
            $value = $this->get($name, 'default');

            // Load 'Value' if set
            if (null === $value) {
                $value = $this->get($name, 'value');
            }
            $values[$name] = $value;
        }

        // Create the extra values for the result
        if ($filter) {
            $db = $this->getAdapter();

            if (isset($filter['gr2o_patient_nr'], $filter['gr2o_id_organization'])) {
                $sql = "SELECT *,
                            CONCAT(
                                COALESCE(CONCAT(grs_last_name, ', '), '-, '),
                                COALESCE(CONCAT(grs_first_name, ' '), ''),
                                COALESCE(grs_surname_prefix, '')) AS respondent_name
                        FROM gems__respondents INNER JOIN gems__respondent2org ON grs_id_user = gr2o_id_user
                        WHERE gr2o_patient_nr = ? AND gr2o_id_organization = ?";
                $values = $db->fetchRow($sql, array($filter['gr2o_patient_nr'], $filter['gr2o_id_organization'])) + $values;
                $values['gr2t_id_user']         = $values['gr2o_id_user'];
                $values['gr2t_id_organization'] = $values['gr2o_id_organization'];
            }
            if (isset($filter['gtr_id_track'])) {
                $sql = 'SELECT * FROM gems__tracks WHERE gtr_id_track = ?';
                $values = $db->fetchRow($sql, $filter['gtr_id_track']) + $values;
                $values['gr2t_id_track']        = $values['gtr_id_track'];
                $values['gr2t_count']           = $values['gtr_survey_rounds'];
            }
            if (isset($filter['gr2t_id_user'])) {
                $values['gr2t_id_user'] = $filter['gr2t_id_user'];
            }
            if (isset($filter['gr2t_id_organization'])) {
                $values['gr2t_id_organization'] = $filter['gr2t_id_organization'];
            }
        }

        // \MUtil_Echo::track($filter, $values);
        $rows = $this->processAfterLoad(array($values), true);
        $row  = reset($rows);

        // Return only a single row when no count is specified
        if (null === $count) {
            return $row;
        } else {
            return array_fill(0, $count, $row);
        }
    }

    /**
     * Save a single model item.
     *
     * @param array $newValues The values to store for a single model item.
     * @param array $filter If the filter contains old key values these are used
     * to decide on update versus insert.
     * @return array The values as they are after saving (they may change).
     */
    public function save(array $newValues, array $filter = null)
    {
        $keys = $this->getKeys();

        // This is the only key to save on, no matter
        // the keys used to initiate the model.
        $this->setKeys($this->_getKeysFor('gems__respondent2track'));

        // Change the end date until the end of the day
        if (isset($newValues['gr2t_end_date']) && $newValues['gr2t_end_date'])  {
            $displayFormat = $this->get('gr2t_end_date', 'dateFormat');
            if ( ! $displayFormat) {
                $displayFormat = \MUtil_Model_Bridge_FormBridge::getFixedOption('date', 'dateFormat');
            }

            // Of course do not do so when we got a time format
            if (! \MUtil_Date_Format::getTimeFormat($displayFormat)) {
                $newValues['gr2t_end_date'] = new \MUtil_Date($newValues['gr2t_end_date'], $displayFormat);
                $newValues['gr2t_end_date']->setTimeToDayEnd();
            }
        }

        $newValues = parent::save($newValues, $filter);

        $this->setKeys($keys);

        return $newValues;
    }
}