HEX
Server: Apache
System: Linux WWW 6.1.0-40-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20) x86_64
User: web11 (1011)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/apklausos/application/controllers/StatisticsUserController.php
<?php

/*
 * LimeSurvey
 * Copyright (C) 2007-2011 The LimeSurvey Project Team / Carsten Schmitz
 * All rights reserved.
 * License: GNU/GPL License v2 or later, see LICENSE.php
 * LimeSurvey is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 *
 */

/*
 * Created 12-2008 by Maziminke (maziminke@web.de)
 *
 * This file handles the "Show results to users" option:
 * Survey Settings -> Presentation & navigation -> "Public statistics?"
 *
 * The admin can set a question attribute "public_statistics" for each question
 * to determine whether the results of a certain question should be shown to the user
 * after he/she has submitted the survey.
 *
 */
class StatisticsUserController extends SurveyController
{
    /**
     * @var int
     */
    public $iSurveyID;

    /**
     * @var string
     */
    public $sLanguage;

    /**
     * @param mixed $method
     * @param array $params
     * @return array
     * @todo Not used?
     */
    public function remap($method, $params = array())
    {
        array_unshift($params, $method);
        return call_user_func_array(array($this, "action"), $params);
    }

    /**
     * @param int    $surveyid
     * @param string $language
     *
     * @throws CHttpException
     * @throws CException
     */
    public function actionAction($surveyid, $language = null)
    {
        $sLanguage = $language;
        $survey = Survey::model()->findByPk($surveyid);

        $this->sLanguage = $language;

        $iSurveyID = (int)$survey->sid;
        $this->iSurveyID = $survey->sid;

        //$postlang = returnglobal('lang');
        //~ Yii::import('application.libraries.admin.progressbar',true);
        Yii::app()->loadHelper("userstatistics");
        Yii::app()->loadHelper('database');
        Yii::app()->loadHelper('surveytranslator');
        $data = array();

        if (!isset($iSurveyID)) {
            $iSurveyID = returnGlobal('sid');
        } else {
            $iSurveyID = (int)$iSurveyID;
        }
        if (!$iSurveyID) {
            //This next line ensures that the $iSurveyID value is never anything but a number.
            throw new CHttpException(404, 'You have to provide a valid survey ID.');
        }


        $actresult = Survey::model()->findAll('sid = :sid AND active = :active', array(':sid' => $iSurveyID, ':active' => 'Y')); //Checked
        if (count($actresult) == 0) {
            throw new CHttpException(404, 'You have to provide a valid survey ID.');
        } else {
            $surveyinfo = getSurveyInfo($iSurveyID);
            // let's get the survey title for display
            $thisSurveyTitle = $surveyinfo["name"];
            // let's get css from individual template.css - so define path
            $thisSurveyCssPath = getTemplateURL($surveyinfo["template"]);
            if ($surveyinfo['publicstatistics'] != 'Y') {
                throw new CHttpException(404, 'The public statistics for this survey are deactivated.');
            }

            //check if graphs should be shown for this survey
            if ($survey->isPublicGraphs) {
                $publicgraphs = 1;
            } else {
                $publicgraphs = 0;
            }
        }

        //we collect all the output within this variable
        $statisticsoutput = '';

        //for creating graphs we need some more scripts which are included here
        //True -> include
        //False -> forget about charts
        if (isset($publicgraphs) && $publicgraphs == 1) {
            require_once(APPPATH . '../vendor/pchart/pChart.class.php');
            require_once(APPPATH . '../vendor/pchart/pData.class.php');
            require_once(APPPATH . '../vendor/pchart/pCache.class.php');

            $MyCache = new pCache(Yii::app()->getConfig("tempdir") . DIRECTORY_SEPARATOR);
            //$currentuser is created as prefix for pchart files
            if (isset($_SERVER['REDIRECT_REMOTE_USER'])) {
                $currentuser = $_SERVER['REDIRECT_REMOTE_USER'];
            } else {
                if (session_id()) {
                    $currentuser = substr(session_id(), 0, 15);
                } else {
                    $currentuser = "standard";
                }
            }
        }
        // Set language for questions and labels to base language of this survey
        if ($sLanguage == null || !in_array($sLanguage, $survey->allLanguages)) {
            $sLanguage = $survey->language;
        } else {
            $sLanguage = sanitize_languagecode($sLanguage);
        }
        //set survey language for translations
        SetSurveyLanguage($iSurveyID, $sLanguage);
        //Create header
        $condition = false;
        $sitename = Yii::app()->getConfig("sitename");

        $data['surveylanguage'] = $sLanguage;
        $data['sitename'] = $sitename;
        $data['condition'] = $condition;
        $data['thisSurveyCssPath'] = $thisSurveyCssPath;


        // ---------- CREATE SGQA OF ALL QUESTIONS WHICH USE "PUBLIC_STATISTICS" ----------
        // only show questions where question attribute "public_statistics" is set to "1"
        $questions = Question::model()->with(['group' => ['alias' => 'g'], 'questionattributes' => ['alias' => 'qa']])->findAll([
            'condition' => 't.sid = :surveyid AND t.parent_qid = :parent_qid AND qa.attribute = :attribute AND qa.value = :value',
            'params'    => [':surveyid' => $iSurveyID, ':parent_qid' => 0, ':attribute' => 'public_statistics', ':value' => '1'],
            'order'     => 'g.group_order, t.question_order'
        ]);

        //...while this is the array from copy/paste which we don't want to replace because this is a nasty source of error
        $allfields = [];
        // check if there are any question with public statistics
        if (isset($questions)) {
            $allfields = $this->createSGQA($questions);
        }// end if -> for removing the error message in case there are no filters
        $summary = $allfields;

        //number of records for this survey
        $totalrecords = 0;
        //count number of answers
        $query = "SELECT count(*) FROM " . $survey->responsesTableName;
        //if incompleted answers should be filtert submitdate has to be not null
        //this setting is taken from config-defaults.php
        if (Yii::app()->getConfig("filterout_incomplete_answers") == 'complete') {
            $query .= " WHERE " . $survey->responsesTableName . ".submitdate is not null";
        }
        $result = Yii::app()->db->createCommand($query)->queryAll();

        //$totalrecords = total number of answers
        foreach ($result as $row) {
            $totalrecords = reset($row);
        }

        // creates array of post variable names
        $postvars = array();
        for (reset($_POST); $key = key($_POST); next($_POST)) {
            $postvars[] = $key;
        }
        $data['thisSurveyTitle'] = $thisSurveyTitle;
        $data['totalrecords'] = $totalrecords;
        $data['summary'] = $summary;
        //show some main data at the beginnung
        // let's allow html formatted questions to show

        //push progress bar from 35 to 40
        $process_status = 40;

        //Show Summary results
        if (isset($summary) && !empty($summary)) {
            //let's run through the survey // Fixed bug 3053 with array_unique
            $runthrough = array_unique($summary);

            //loop through all selected questions
            foreach ($runthrough as $rt) {
                //update progress bar
                if ($process_status < 100) {
                    $process_status++;
                }
            }    // end foreach -> loop through all questions

            $helper = new userstatistics_helper();
            $statisticsoutput .= $helper->generate_statistics($iSurveyID, $summary, $summary, $publicgraphs, 'html', null, $sLanguage, false);
        }    //end if -> show summary results

        $data['statisticsoutput'] = $statisticsoutput;
        $data['aSurveyInfo'] = getSurveyInfo($iSurveyID);
        $data['graphUrl'] = Yii::app()->getController()->createUrl("admin/statistics/sa/graph");

        Yii::app()->getClientScript()->registerScriptFile(Yii::app()->getConfig('generalscripts') . 'statistics_user.js');
        $data['aSurveyInfo']['include_content'] = 'statistics_user';
        $data['aSurveyInfo']['trackUrlPageName'] = 'statistics_user';
        // Set template into last instance. Will be picked up later by the renderer
        $oTemplate = Template::model()->getInstance('', $iSurveyID);
        Yii::app()->twigRenderer->renderTemplateFromFile('layout_statistics_user.twig', $data, false);

        //Delete all Session Data
        Yii::app()->session['finished'] = true;
    }

    /**
     * Create SGQA of all questions which use "public_statistics"
     * Assumes this->sLanguage and this->iSurveyID is set.
     *
     * @param array $filters
     *
     * @return array
     * @throws CException
     */
    public function createSGQA(array $filters)
    {
        $allfields = array();

        /**
         * @var $flt Question
         */
        foreach ($filters as $flt) {
            //SGQ identifier
            $type = $flt['type'];
            $SGQidentifier = $this->iSurveyID . 'X' . $flt->gid . 'X' . $flt->qid;

            //let's switch through the question type for each question
            switch ($type) {
                case Question::QT_K_MULTIPLE_NUMERICAL: // Multiple Numerical
                case Question::QT_Q_MULTIPLE_SHORT_TEXT: // Multiple short text
                    $results = Question::model()->with('questionl10ns')->findAll([
                        'condition' => 'language=:language AND parent_qid=:parent_qid',
                        'params'    => [':language' => $this->sLanguage, ':parent_qid' => $flt->qid],
                        'order'     => 'question_order'
                    ]);
                    foreach ($results as $row) {
                        $allfields[] = $flt->type . $SGQidentifier . $row->title;
                    }
                    break;
                case Question::QT_A_ARRAY_5_POINT: // Array of 5 point choice questions
                case Question::QT_B_ARRAY_10_CHOICE_QUESTIONS: // Array of 10 point choice questions
                case Question::QT_C_ARRAY_YES_UNCERTAIN_NO: // Array of Yes\No\Uncertain questions
                case Question::QT_E_ARRAY_INC_SAME_DEC: // Array of Increase/Same/Decrease questions
                case Question::QT_F_ARRAY: // Array
                case Question::QT_H_ARRAY_COLUMN: // Array (By Column)
                    $results = Question::model()->with('questionl10ns')->findAll([
                        'condition' => 'language=:language AND parent_qid=:parent_qid',
                        'params'    => [':language' => $this->sLanguage, ':parent_qid' => $flt->qid],
                        'order'     => 'question_order'
                    ]);
                    foreach ($results as $row) {
                        $allfields[] = $SGQidentifier . $row->title;
                    }
                    break;
                // all "free text" types (T, U, S)  get the same prefix ("T")
                case Question::QT_S_SHORT_FREE_TEXT: // Short free text
                case Question::QT_T_LONG_FREE_TEXT: // Long free text
                case Question::QT_U_HUGE_FREE_TEXT: // Huge free text
                    $allfields[] = "T" . $SGQidentifier;
                    break;
                case Question::QT_SEMICOLON_ARRAY_TEXT:  // Array (Text)
                case Question::QT_COLON_ARRAY_NUMBERS:  // Array (Numbers)
                    $resultsScale0 = Question::model()->with('questionl10ns')->findAll([
                        'condition' => 'language=:language AND parent_qid=:parent_qid AND scale_id=:scale_id',
                        'params'    => [':language' => $this->sLanguage, ':parent_qid' => $flt->qid, ':scale_id' => 0],
                        'order'     => 'question_order'
                    ]);
                    $resultsScale1 = Question::model()->with('questionl10ns')->findAll([
                        'condition' => 'language=:language AND parent_qid=:parent_qid AND scale_id=:scale_id',
                        'params'    => [':language' => $this->sLanguage, ':parent_qid' => $flt->qid, ':scale_id' => 1],
                        'order'     => 'question_order'
                    ]);
                    foreach ($resultsScale0 as $rowScale0) {
                        foreach ($resultsScale1 as $rowScale1) {
                            $allfields[] = $SGQidentifier . $rowScale0['title'] . "_" . $rowScale1['title'];
                        }
                    }
                    break;
                case Question::QT_R_RANKING: // Ranking
                    $results = Answer::model()->with('answerl10ns')->findAll([
                        'condition' => 'language=:language AND qid=:qid',
                        'params'    => [':language' => $this->sLanguage, ':qid' => $flt->qid],
                        'order'     => 'sortorder'
                    ]);
                    $count = count($results);
                    //loop through all answers. if there are 3 items to rate there will be 3 statistics
                    for ($i = 1; $i <= $count; $i++) {
                        $allfields[] = $flt->type . $SGQidentifier . $i . "-" . strlen($i);
                    }
                    break;
                //Boilerplate questions are only used to put some text between other questions -> no analysis needed
                case Question::QT_X_TEXT_DISPLAY:  //This is a boilerplate question and it has no business in this script
                    break;
                case Question::QT_1_ARRAY_DUAL: // Dual scale
                    $results = Question::model()->with('questionl10ns')->findAll([
                        'condition' => 'language=:language AND parent_qid=:parent_qid',
                        'params'    => [':language' => $this->sLanguage, ':parent_qid' => $flt->qid],
                        'order'     => 'question_order'
                    ]);
                    //loop through answers
                    foreach ($results as $row) {
                        $allfields[] = $SGQidentifier . $row['title'] . "#0";
                        $allfields[] = $SGQidentifier . $row['title'] . "#1";
                    }    //end WHILE -> loop through all answers
                    break;

                case Question::QT_P_MULTIPLE_CHOICE_WITH_COMMENTS:  //P - Multiple choice with comments
                case Question::QT_M_MULTIPLE_CHOICE:  //M - Multiple choice
                case Question::QT_N_NUMERICAL:  //N - Numerical input
                case Question::QT_D_DATE:  //D - Date
                    $allfields[] = $flt->type . $SGQidentifier;
                    break;
                default:   //Default settings
                    $allfields[] = $SGQidentifier;
                    break;
            }    //end switch -> check question types and create filter forms
        }

        return $allfields;
    }
}