GemsTracker/gemstracker-library

View on GitHub
classes/Gems/Default/FieldReportAction.php

Summary

Maintainability
C
1 day
Test Coverage
F
0%
<?php

/**
 *
 * @package    Gems
 * @subpackage Default
 * @author     Matijs de Jong <mjong@magnafacta.nl>
 * @copyright  Copyright (c) 2014 Erasmus MC
 * @license    New BSD License
 * @version    $Id: FieldReportAction.php 2534 2015-05-05 18:07:37Z matijsdejong $
 */

use Gems\Tracker\Model\FieldDataModel;

/**
 *
 *
 * @package    Gems
 * @subpackage Default
 * @copyright  Copyright (c) 2014 Erasmus MC
 * @license    New BSD License
 * @since      Class available since version 1.6.5 30-nov-2014 17:50:22
 */
class Gems_Default_FieldReportAction extends \Gems_Controller_ModelSnippetActionAbstract
{
    /**
     * The parameters used for the autofilter action.
     *
     * When the value is a function name of that object, then that functions is executed
     * with the array key as single parameter and the return value is set as the used value
     * - unless the key is an integer in which case the code is executed but the return value
     * is not stored.
     *
     * @var array Mixed key => value array for snippet initialization
     */
    protected $autofilterParameters = array(
        'browse' => false,
        'columns' => 'getBrowseColumns',
        );

    /**
     *
     * @var \Gems_User_User
     */
    public $currentUser;
    
    /**
     * Where statement filtering on track start / end dates
     *
     * @var string
     */
    protected $dateWhere;

    /**
     *
     * @var \Zend_Db_Adapter_Abstract
     */
    public $db;

    /**
     *
     * @var \Gems_Tracker_Engine_TrackEngineInterface
     */
    protected $engine;

    /**
     * The snippets used for the index action, before those in autofilter
     *
     * @var mixed String or array of snippets name
     */
    protected $indexStartSnippets = array('Generic\\ContentTitleSnippet', 'Tracker_Fields_FieldReportSearchSnippet');

    /**
     * Where statement filtering out organizations
     *
     * @var string
     */
    protected $orgWhere;

    /**
     * The number of instances of the currently selected track id
     *
     * @var int
     */
    protected $trackCount;

    /**
     * The number of instances of the current field that have been filled
     *
     * @var int
     */
    protected $trackFilled;

    /**
     * The currently selected track id
     *
     * @var int
     */
    protected $trackId;

    /**
     * Creates a model for getModel(). Called only for each new $action.
     *
     * The parameters allow you to easily adapt the model to the current action. The $detailed
     * parameter was added, because the most common use of action is a split between detailed
     * and summarized actions.
     *
     * @param boolean $detailed True when the current action is not in $summarizedActions.
     * @param string $action The current action.
     * @return \MUtil_Model_ModelAbstract
     */
    public function createModel($detailed, $action)
    {
        $filter = $this->getSearchFilter($action !== 'export');

        // Return empty model when no track sel;ected
        if (! (isset($filter['gtf_id_track']) && $filter['gtf_id_track'])) {
            $model = new \Gems_Model_JoinModel('trackfields' , 'gems__track_fields');
            $model->set('gtf_field_name', 'label', $this->_('Name'));
            $model->setFilter(array('1=0'));
            $this->autofilterParameters['onEmpty'] = $this->_('No track selected...');

            return $model;
        }

        $this->trackId = $filter['gtf_id_track'];

        $tracker      = $this->loader->getTracker();
        $this->engine = $tracker->getTrackEngine($this->trackId);

        $orgs         = $this->currentUser->getRespondentOrgFilter();
        if (isset($filter['gr2t_id_organization'])) {
            $orgs = array_intersect($orgs, (array) $filter['gr2t_id_organization']);
        }
        $this->orgWhere = " AND gr2t_id_organization IN (" . implode(", ", $orgs) . ")";

        $sql     = "SELECT COUNT(*)
            FROM gems__respondent2track INNER JOIN gems__reception_codes ON gr2t_reception_code = grc_id_reception_code
            WHERE gr2t_id_track = ? AND grc_success = 1" . $this->orgWhere;
        
        // Add the period filter - if any
        if ($where = \Gems_Snippets_AutosearchFormSnippet::getPeriodFilter($filter, $this->db)) {
            $sql .= ' AND ' . $where;
        }
        $this->dateWhere = $where; 

        $this->trackCount = $this->db->fetchOne($sql, $this->trackId);

        $model = $this->engine->getFieldsMaintenanceModel();
        //$model->setFilter($filter);

        // $model->addColumn(new \Zend_Db_Expr($trackCount), 'trackcount');
        // $model->addColumn(new \Zend_Db_Expr("(SELECT COUNT())"), 'fillcount');

        $model->set('trackcount', 'label', $this->_('Tracks'));
        $model->setOnLoad('trackcount', $this->trackCount);

        $model->set('fillcount', 'label', $this->_('Filled'));
        $model->setOnLoad('fillcount', array($this, 'fillCount'));

        $model->set('emptycount', 'label', $this->_('Empty'));
        $model->setOnLoad('emptycount', array($this, 'emptyCount'));

        $model->set('valuecount', 'label', $this->_('Unique values'));
        $model->setOnLoad('valuecount', array($this, 'valueCount'));

        return $model;
    }

    /**
     * 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 emptyCount($value, $isNew = false, $name = null, array $context = array(), $isPost = false)
    {
        $value = $this->trackCount - $this->trackFilled;
        return sprintf(
                $this->_('%d (%d%%)'),
                $value,
                $this->trackCount ? round($value / $this->trackCount * 100, 0) : 0
            );
    }

    /**
     * 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 fillCount($value, $isNew = false, $name = null, array $context = array(), $isPost = false)
    {
        $model = $this->engine->getFieldsDataStorageModel();

        if (! $model instanceof FieldDataModel) {
            return null;
        }

        $subName  = $model->getModelNameForRow($context);
        $sql = sprintf("SELECT COUNT(*)
            FROM %s INNER JOIN gems__respondent2track ON %s = gr2t_id_respondent_track
                INNER JOIN gems__reception_codes ON gr2t_reception_code = grc_id_reception_code
            WHERE %s = %s AND %s IS NOT NULL AND gr2t_id_track = %d AND grc_success = 1" . $this->orgWhere,
                $model->getTableName($subName),
                $model->getFieldName('gr2t2f_id_respondent_track', $subName),
                $model->getFieldName('gr2t2f_id_field', $subName),
                $context['gtf_id_field'],
                $model->getFieldName('gr2t2f_value', $subName),
                $this->trackId
                );
        
        // Add the period filter - if any
        if ($this->dateWhere) {
            $sql .= ' AND ' . $this->dateWhere;
        }

        // \MUtil_Echo::track($sql);
        $this->trackFilled = $this->db->fetchOne($sql);

        $value = $this->trackFilled;
        return sprintf(
                $this->_('%d (%d%%)'),
                $value,
                $this->trackCount ? round($value / $this->trackCount * 100, 0) : 0
            );
    }

    /**
     * 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 valueCount($value, $isNew = false, $name = null, array $context = array(), $isPost = false)
    {
        $model = $this->engine->getFieldsDataStorageModel();

        if (! $model instanceof FieldDataModel) {
            return null;
        }

        $subName  = $model->getModelNameForRow($context);
        $sql = sprintf("SELECT COUNT(DISTINCT %s)
            FROM %s INNER JOIN gems__respondent2track ON %s = gr2t_id_respondent_track
                INNER JOIN gems__reception_codes ON gr2t_reception_code = grc_id_reception_code
            WHERE %s = %s AND %s IS NOT NULL AND gr2t_id_track = %d AND grc_success = 1" . $this->orgWhere,
                $model->getFieldName('gr2t2f_value', $subName),
                $model->getTableName($subName),
                $model->getFieldName('gr2t2f_id_respondent_track', $subName),
                $model->getFieldName('gr2t2f_id_field', $subName),
                $context['gtf_id_field'],
                $model->getFieldName('gr2t2f_value', $subName),
                $this->trackId
                );
        
        // Add the period filter - if any
        if ($this->dateWhere) {
            $sql .= ' AND ' . $this->dateWhere;
        }

        // \MUtil_Echo::track($sql);
        $value = $this->db->fetchOne($sql);
        return sprintf(
                $this->_('%d (uses per value: %01.2f)'),
                $value,
                $value ? $this->trackFilled / $value : 0
            );
    }

    /**
     * Get the browse columns
     * @return array
     */
    public function getBrowseColumns()
    {
        $filter = $this->getSearchFilter(true);
        if (! (isset($filter['gtf_id_track']) && $filter['gtf_id_track'])) {
            return array(
                array('gtf_field_name'),
                );
        }
        return array(
            array('gtf_field_name'),
            array('gtf_id_order'),
            array('gtf_field_type'),
            array('trackcount'),
            array('emptycount'),
            array('fillcount'),
            array('valuecount'),
        );
    }

    /**
     * Helper function to get the title for the index action.
     *
     * @return $string
     */
    public function getIndexTitle()
    {
        return $this->_('Track fields');
    }

    /**
     * Function to allow the creation of search defaults in code
     *
     * @see getSearchFilter()
     *
     * @return array
     */
    public function getSearchDefaults()
    {
        if (! isset($this->defaultSearchData['gr2t_id_organization'])) {
            $orgs = $this->currentUser->getRespondentOrganizations();
            $this->defaultSearchData['gr2t_id_organization'] = array_keys($orgs);
        }
        
        if (!isset($this->defaultSearchData['gtf_id_track'])) {
            $orgs = $this->currentUser->getRespondentOrganizations();
            $tracks = $this->util->getTrackData()->getTracksForOrgs($orgs);
            if (count($tracks) == 1) {
                $this->defaultSearchData['gtf_id_track'] = key($tracks);
            }
        }

        return parent::getSearchDefaults();
    }

    /**
     * Helper function to allow generalized statements about the items in the model.
     *
     * @param int $count
     * @return $string
     */
    public function getTopic($count = 1)
    {
        return $this->plural('track', 'tracks', $count);
    }
}