SurveyUtil::getSurveyList()   C
last analyzed

Complexity

Conditions 11
Paths 20

Size

Total Lines 109
Code Lines 75

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 75
c 0
b 0
f 0
nc 20
nop 1
dl 0
loc 109
rs 6.3987

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\AbstractResource;
6
use Chamilo\CoreBundle\Entity\Course;
7
use Chamilo\CoreBundle\Entity\Session as SessionEntity;
8
use Chamilo\CoreBundle\Entity\User;
9
use Chamilo\CoreBundle\Enums\ActionIcon;
10
use Chamilo\CoreBundle\Enums\ObjectIcon;
11
use Chamilo\CoreBundle\Enums\StateIcon;
12
use Chamilo\CoreBundle\Enums\ToolIcon;
13
use Chamilo\CoreBundle\Framework\Container;
14
use Chamilo\CourseBundle\Entity\CGroup;
15
use Chamilo\CourseBundle\Entity\CSurvey;
16
use Chamilo\CourseBundle\Entity\CSurveyAnswer;
17
use Chamilo\CourseBundle\Entity\CSurveyInvitation;
18
use Chamilo\CourseBundle\Entity\CSurveyQuestion;
19
use Chamilo\CourseBundle\Entity\CSurveyQuestionOption;
20
use ChamiloSession as Session;
21
22
/**
23
 * This class offers a series of general utility functions for survey querying and display.
24
 */
25
class SurveyUtil
26
{
27
    /**
28
     * Checks whether the given survey has a pagebreak question as the first
29
     * or the last question.
30
     * If so, break the current process, displaying an error message.
31
     *
32
     * @param int  $survey_id Survey ID (database ID)
33
     * @param bool $continue  Optional. Whether to continue the current
34
     *                        process or exit when breaking condition found. Defaults to true (do not break).
35
     */
36
    public static function check_first_last_question($survey_id, $continue = true)
37
    {
38
        // Table definitions
39
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
40
        $course_id = api_get_course_int_id();
41
        $survey_id = (int) $survey_id;
42
43
        // Getting the information of the question
44
        $sql = "SELECT * FROM $tbl_survey_question
45
                WHERE survey_id='".$survey_id."'
46
                ORDER BY sort ASC";
47
        $result = Database::query($sql);
48
        $total = Database::num_rows($result);
49
        $counter = 1;
50
        $error = false;
51
        while ($row = Database::fetch_assoc($result)) {
52
            if (1 == $counter && 'pagebreak' === $row['type']) {
53
                echo Display::return_message(get_lang('The page break cannot be the first'), 'error', false);
54
                $error = true;
55
            }
56
            if ($counter == $total && 'pagebreak' === $row['type']) {
57
                echo Display::return_message(get_lang('The page break cannot be the last one'), 'error', false);
58
                $error = true;
59
            }
60
            $counter++;
61
        }
62
63
        if (!$continue && $error) {
64
            Display::display_footer();
65
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
66
        }
67
    }
68
69
    /**
70
     * This function removes an (or multiple) answer(s) of a user on a question of a survey.
71
     *
72
     * @param mixed   The user id or email of the person who fills the survey
73
     * @param int The survey id
74
     * @param int The question id
75
     * @param int The option id
76
     *
77
     * @author Patrick Cool <[email protected]>, Ghent University
78
     *
79
     * @version January 2007
80
     */
81
    public static function remove_answer($user, $survey_id, $question_id, $lpItemId = 0): void
82
    {
83
        $sessionId = api_get_session_id();
84
        // table definition
85
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
86
87
        $lpItemCondition = '';
88
        if (!empty($lpItemId)) {
89
            $lpItemCondition = " AND c_lp_item_id = $lpItemId";
90
        }
91
        $sessionCondition = '';
92
        if (true === api_get_configuration_value('show_surveys_base_in_sessions')) {
93
            $sessionCondition = api_get_session_condition($sessionId);
94
        }
95
96
        $sql = "DELETE FROM $table
97
				WHERE
98
                    user = '".Database::escape_string($user)."' AND
99
                    survey_id = '".intval($survey_id)."' AND
100
                    question_id = '".intval($question_id)."'
101
                    $sessionCondition
102
                    $lpItemCondition";
103
        Database::query($sql);
104
    }
105
106
    public static function saveAnswer(
107
        $user,
108
        CSurvey $survey,
109
        CSurveyQuestion $question,
110
        $optionId,
111
        $optionValue,
112
        $otherOption = '',
113
        $lpItemId = 0
114
    ): bool {
115
116
        // Make the survey anonymous
117
        if (1 == $survey->getAnonymous()) {
118
            $surveyUser = Session::read('surveyuser');
119
            if (empty($surveyUser)) {
120
                $user = md5($user.time());
121
                Session::write('surveyuser', $user);
122
            } else {
123
                $user = Session::read('surveyuser');
124
            }
125
        }
126
127
        if (!empty($otherOption)) {
128
            $optionId = $optionId.'@:@'.$otherOption;
129
        }
130
131
        $sessionId = api_get_session_id();
132
        $answer = new CSurveyAnswer();
133
        $answer
134
            ->setUser($user)
135
            ->setSurvey($survey)
136
            ->setQuestion($question)
137
            ->setOptionId($optionId)
138
            ->setValue((int) $optionValue)
139
            ->setLpItemId((int) $lpItemId)
140
            ->setSessionId($sessionId ?: null)
141
        ;
142
143
        $em = Database::getManager();
144
        $em->persist($answer);
145
        $em->flush();
146
147
        $insertId = $answer->getIid();
148
        if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
149
            return true;
150
        }
151
152
        return false;
153
    }
154
155
    /**
156
     * This function checks the parameters that are used in this page.
157
     *
158
     * @return string $people_filled The header, an error and the footer if any parameter fails, else it returns true
159
     *
160
     * @author Patrick Cool <[email protected]>, Ghent University
161
     *
162
     * @version February 2007
163
     */
164
    public static function check_parameters($people_filled)
165
    {
166
        $error = false;
167
168
        // Getting the survey data
169
        $survey_data = SurveyManager::get_survey($_GET['survey_id']);
170
171
        // $_GET['survey_id'] has to be numeric
172
        if (!is_numeric($_GET['survey_id'])) {
173
            $error = get_lang('Unknown survey id');
174
        }
175
176
        // $_GET['action']
177
        $allowed_actions = [
178
            'overview',
179
            'questionreport',
180
            'userreport',
181
            'comparativereport',
182
            'completereport',
183
            'deleteuserreport',
184
        ];
185
        if (isset($_GET['action']) && !in_array($_GET['action'], $allowed_actions)) {
186
            $error = get_lang('Action not allowed');
187
        }
188
189
        // User report
190
        if (isset($_GET['action']) && 'userreport' == $_GET['action']) {
191
            if (0 == $survey_data['anonymous']) {
192
                //TODO fix that this may trigger 'PHP Warning:  Undefined array key "anonymous"'
193
                foreach ($people_filled as $key => &$value) {
194
                    $people_filled_userids[] = $value['invited_user'];
195
                }
196
            } else {
197
                $people_filled_userids = $people_filled;
198
            }
199
200
            if (isset($_GET['user']) && !in_array($_GET['user'], $people_filled_userids)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $people_filled_userids does not seem to be defined for all execution paths leading up to this point.
Loading history...
201
                $error = get_lang('Unknow user');
202
            }
203
        }
204
205
        // Question report
206
        if (isset($_GET['action']) && 'questionreport' == $_GET['action']) {
207
            if (isset($_GET['question']) && !is_numeric($_GET['question'])) {
208
                $error = get_lang('Unknown question');
209
            }
210
        }
211
212
        if ($error) {
213
            $tool_name = get_lang('Reporting');
214
            Display::addFlash(
215
                Display::return_message(
216
                    get_lang('Error').': '.$error,
217
                    'error',
218
                    false
219
                )
220
            );
221
            Display::display_header($tool_name);
222
            Display::display_footer();
223
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
224
        }
225
226
        return true;
227
    }
228
229
    public static function handleReportingActions(CSurvey $survey, array $people_filled = [])
230
    {
231
        $action = $_GET['action'] ?? '';
232
233
        switch ($action) {
234
            case 'questionreport':
235
                self::display_question_report($survey);
236
                break;
237
            case 'userreport':
238
                self::displayUserReport($survey, $people_filled);
239
                break;
240
            case 'comparativereport':
241
                self::display_comparative_report();
242
                break;
243
            case 'completereport':
244
                $surveysAnswered = SurveyManager::getInvitationsAnswered(
245
                    $survey->getCode(),
246
                    api_get_course_int_id(),
247
                    api_get_session_id()
248
                );
249
250
                if (!empty($surveysAnswered)) {
251
                    foreach ($surveysAnswered as $invitation) {
252
                        $surveyEntity = $invitation->getSurvey();
253
                        if (!$surveyEntity) {
254
                            continue;
255
                        }
256
257
                        $showNames = ($surveyEntity->getAnonymous() === '0');
258
259
                        echo SurveyUtil::displayCompleteReport(
260
                            $surveyEntity,
261
                            0,
262
                            true,
263
                            true,
264
                            $showNames,
265
                            (int) $invitation->getLpItemId()
266
                        );
267
                    }
268
                }
269
                break;
270
            case 'deleteuserreport':
271
                self::delete_user_report($survey->getIid(), $_GET['user']);
272
                break;
273
        }
274
    }
275
276
    /**
277
     * This function deletes the report of an user who wants to retake the survey.
278
     *
279
     * @param int $survey_id
280
     * @param int $user_id
281
     *
282
     * @author Christian Fasanando Flores <[email protected]>
283
     *
284
     * @version November 2008
285
     */
286
    public static function delete_user_report($survey_id, $user_id)
287
    {
288
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
289
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
290
        $table_survey = Database::get_course_table(TABLE_SURVEY);
291
292
        $course_id = api_get_course_int_id();
293
        $survey_id = (int) $survey_id;
294
        $user_id = Database::escape_string($user_id);
295
296
        if (!empty($survey_id) && !empty($user_id)) {
297
298
            $sessionCondition = '';
299
            if (true === api_get_configuration_value('show_surveys_base_in_sessions')) {
300
                $sessionId = api_get_session_id();
301
                $sessionCondition = api_get_session_condition($sessionId);
302
            }
303
304
            // delete data from survey_answer by user_id and survey_id
305
            $sql = "DELETE FROM $table_survey_answer
306
			        WHERE c_id = $course_id AND survey_id = '".$survey_id."' AND user = '".$user_id."' $sessionCondition";
307
            Database::query($sql);
308
            // update field answered from survey_invitation by user_id and survey_id
309
            $sql = "UPDATE $table_survey_invitation SET answered = '0'
310
			        WHERE
311
			            c_id = $course_id AND
312
			            survey_id = (
313
                            SELECT iid FROM $table_survey
314
                            WHERE
315
                                iid = '".$survey_id."'
316
                        ) AND
317
			            user_id = '".$user_id."'  $sessionCondition";
318
            $result = Database::query($sql);
319
        }
320
321
        if (false !== $result) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.
Loading history...
322
            $message = get_lang('The user\'s answers to the survey have been successfully removed.').'<br />
323
					<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=userreport&survey_id=' .$survey_id.'&'.api_get_cidreq().'">'.get_lang('Go back').'</a>';
324
            echo Display::return_message($message, 'confirmation', false);
325
        }
326
    }
327
328
    /**
329
     * @return string
330
     */
331
    public static function displayUserReportForm(CSurvey $survey, array $people_filled = [])
332
    {
333
        $surveyId = $survey->getIid();
334
        // Step 1: selection of the user
335
        echo "<script>
336
        function jumpMenu(targ,selObj,restore) {
337
            eval(targ+\".location='\"+selObj.options[selObj.selectedIndex].value+\"'\");
338
            if (restore) selObj.selectedIndex=0;
339
        }
340
		</script>";
341
        echo get_lang('Select user who filled the survey').'<br />';
342
        echo '<select name="user" onchange="jumpMenu(\'parent\',this,0)">';
343
        echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
344
            .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">'
345
            .get_lang('User').'</option>';
346
347
        foreach ($people_filled as $key => &$person) {
348
            if (0 == $survey->getAnonymous()) {
349
                $name = $person['user_info']['complete_name_with_username'];
350
                $id = $person['user_id'];
351
                if ('' == $id) {
352
                    $id = $person['invited_user'];
353
                    $name = $person['invited_user'];
354
                }
355
            } else {
356
                $name = get_lang('Anonymous').' '.($key + 1);
357
                $id = $person;
358
            }
359
            echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
360
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&user='
361
                .Security::remove_XSS($id).'&'.api_get_cidreq().'" ';
362
            if (isset($_GET['user']) && $_GET['user'] == $id) {
363
                echo 'selected="selected"';
364
            }
365
            echo '>'.$name.'</option>';
366
        }
367
        echo '</select>';
368
    }
369
370
    /**
371
     * @param int   $userId
372
     * @param array $survey_data
373
     * @param bool  $addMessage
374
     */
375
    public static function displayUserReportAnswers($userId, CSurvey $survey, $addMessage = true)
376
    {
377
        // Database table definitions
378
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
379
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
380
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
381
        $course_id = api_get_course_int_id();
382
        $surveyId = $survey->getIid();
383
        $userId = Database::escape_string($userId);
384
385
        $content = '';
386
        // Step 2: displaying the survey and the answer of the selected users
387
        if (!empty($userId)) {
388
            if ($addMessage) {
389
                $content .= Display::return_message(
390
                    get_lang('This screen displays an exact copy of the form as it was filled by the user'),
391
                    'normal',
392
                    false
393
                );
394
            }
395
396
            // Getting all the questions and options
397
            $sql = "SELECT
398
			            survey_question.iid question_id,
399
			            survey_question.survey_id,
400
			            survey_question.survey_question,
401
			            survey_question.display,
402
			            survey_question.max_value,
403
			            survey_question.sort,
404
			            survey_question.type,
405
                        survey_question_option.iid question_option_id,
406
                        survey_question_option.option_text,
407
                        survey_question_option.sort as option_sort
408
					FROM $table_survey_question survey_question
409
					LEFT JOIN $table_survey_question_option survey_question_option
410
					ON
411
					    survey_question.iid = survey_question_option.question_id
412
					WHERE
413
					    survey_question NOT LIKE '%{{%' AND
414
					    survey_question.survey_id = '".$surveyId."'
415
					ORDER BY survey_question.sort, survey_question_option.sort ASC";
416
            $result = Database::query($sql);
417
            while ($row = Database::fetch_assoc($result)) {
418
                if ('pagebreak' !== $row['type']) {
419
                    $questions[$row['sort']]['question_id'] = $row['question_id'];
420
                    $questions[$row['sort']]['survey_id'] = $row['survey_id'];
421
                    $questions[$row['sort']]['survey_question'] = $row['survey_question'];
422
                    $questions[$row['sort']]['display'] = $row['display'];
423
                    $questions[$row['sort']]['type'] = $row['type'];
424
                    $questions[$row['sort']]['maximum_score'] = $row['max_value'];
425
                    $questions[$row['sort']]['options'][$row['question_option_id']] = $row['option_text'];
426
                }
427
            }
428
429
            $sessionCondition = '';
430
            if (true === api_get_configuration_value('show_surveys_base_in_sessions')) {
431
                $sessionId = api_get_session_id();
432
                $sessionCondition = api_get_session_condition($sessionId);
433
            }
434
435
            // Getting all the answers of the user
436
            $sql = "SELECT * FROM $table_survey_answer
437
			        WHERE
438
                        survey_id = '".$surveyId."' AND
439
                        user = '".$userId."' $sessionCondition";
440
            $result = Database::query($sql);
441
            while ($row = Database::fetch_assoc($result)) {
442
                $answers[$row['question_id']][] = $row['option_id'];
443
                $all_answers[$row['question_id']][] = $row;
444
            }
445
446
            // Displaying all the questions
447
            foreach ($questions as &$question) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $questions does not seem to be defined for all execution paths leading up to this point.
Loading history...
448
                // If the question type is a scoring then we have to format the answers differently
449
                switch ($question['type']) {
450
                    case 'score':
451
                        $finalAnswer = [];
452
                        if (is_array($question) && is_array($all_answers)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $all_answers does not seem to be defined for all execution paths leading up to this point.
Loading history...
453
                            foreach ($all_answers[$question['question_id']] as $key => &$answer_array) {
454
                                $finalAnswer[$answer_array['option_id']] = $answer_array['value'];
455
                            }
456
                        }
457
                        break;
458
                    case 'multipleresponse':
459
                        $finalAnswer = isset($answers[$question['question_id']]) ? $answers[$question['question_id']] : '';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $answers does not seem to be defined for all execution paths leading up to this point.
Loading history...
460
                        break;
461
                    default:
462
                        $finalAnswer = '';
463
                        if (isset($all_answers[$question['question_id']])) {
464
                            $finalAnswer = $all_answers[$question['question_id']][0]['option_id'];
465
                        }
466
                        break;
467
                }
468
469
                $display = survey_question::createQuestion($question['type']);
470
                $url = api_get_self();
471
                $form = new FormValidator('question', 'post', $url);
472
                $form->addHtml('<div class="survey_question_wrapper"><div class="survey_question">');
473
                $form->addHtml($question['survey_question']);
474
                $display->render($form, $question, $finalAnswer);
475
                $form->addHtml('</div></div>');
476
                $content .= $form->returnForm();
477
            }
478
        }
479
480
        return $content;
481
    }
482
483
    /**
484
     * This function displays the user report which is basically nothing more
485
     * than a one-page display of all the questions
486
     * of the survey that is filled with the answers of the person who filled the survey.
487
     *
488
     * @return string html code of the one-page survey with the answers of the selected user
489
     *
490
     * @author Patrick Cool <[email protected]>, Ghent University
491
     *
492
     * @version February 2007 - Updated March 2008
493
     */
494
    public static function displayUserReport(CSurvey $survey, $people_filled, $addActionBar = true)
495
    {
496
        $surveyId = $survey->getIid();
497
        $reportingUrl = api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq();
498
499
        // Actions bar
500
        if ($addActionBar) {
501
            $actions = '<a href="'.$reportingUrl.'">'.
502
                Display::getMdiIcon(ActionIcon::BACK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Back to').' '.get_lang('Reporting overview'))
503
                .'</a>';
504
            if (isset($_GET['user'])) {
505
                if (api_is_allowed_to_edit()) {
506
                    // The delete link
507
                    $actions .= '<a
508
                        href="'.$reportingUrl.'&action=deleteuserreport&user='.Security::remove_XSS($_GET['user']).'" >'.
509
                        Display::getMdiIcon(ActionIcon::DELETE, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Delete')).'</a>';
510
                }
511
512
                // Export the user report
513
                $actions .= '<a href="javascript: void(0);" onclick="document.form1a.submit();">'
514
                    .Display::getMdiIcon(ActionIcon::EXPORT_CSV, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('CSV export')).'</a> ';
515
                $actions .= '<a href="javascript: void(0);" onclick="document.form1b.submit();">'
516
                    .Display::getMdiIcon(ActionIcon::EXPORT_SPREADSHEET, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Excel export')).'</a> ';
517
                $actions .= '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='
518
                    .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
519
                    .Security::remove_XSS($_GET['user']).'">';
520
                $actions .= '<input type="hidden" name="export_report" value="export_report">';
521
                $actions .= '<input type="hidden" name="export_format" value="csv">';
522
                $actions .= '</form>';
523
                $actions .= '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='
524
                    .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
525
                    .Security::remove_XSS($_GET['user']).'">';
526
                $actions .= '<input type="hidden" name="export_report" value="export_report">';
527
                $actions .= '<input type="hidden" name="export_format" value="xls">';
528
                $actions .= '</form>';
529
                $actions .= '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='
530
                    .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
531
            }
532
            echo Display::toolbarAction('survey', [$actions]);
533
        }
534
535
        echo self::displayUserReportForm($survey, $people_filled);
536
        if (isset($_GET['user'])) {
537
            echo self::displayUserReportAnswers($_GET['user'], $survey);
538
        }
539
    }
540
541
    /**
542
     * This function displays the report by question.
543
     *
544
     * It displays a table with all the options of the question and the number of users who have answered positively on
545
     * the option. The number of users who answered positive on a given option is expressed in an absolute number, in a
546
     * percentage of the total and graphically using bars By clicking on the absolute number you get a list with the
547
     * persons who have answered this. You can then click on the name of the person and you will then go to the report
548
     * by user where you see all the answers of that user.
549
     *
550
     * @return string html code that displays the report by question
551
     *
552
     * @todo allow switching between horizontal and vertical.
553
     * @todo multiple response: percentage are probably not OK
554
     * @todo the question and option text have to be shortened and should expand when the user clicks on it.
555
     * @todo the pagebreak and comment question types should not be shown => removed from $survey_data before
556
     *
557
     * @author Patrick Cool <[email protected]>, Ghent University
558
     *
559
     * @version February 2007 - Updated March 2008
560
     */
561
    public static function display_question_report(CSurvey $survey)
562
    {
563
        $singlePage = isset($_GET['single_page']) ? (int) $_GET['single_page'] : 0;
564
        // Determining the offset of the sql statement (the n-th question of the survey)
565
        $offset = !isset($_GET['question']) ? 0 : (int) $_GET['question'];
566
        $currentQuestion = isset($_GET['question']) ? (int) $_GET['question'] : 0;
567
        $surveyId = $survey->getIid();
568
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
569
        $course_id = api_get_course_int_id();
570
571
        $sessionCondition = '';
572
        if (true === api_get_configuration_value('show_surveys_base_in_sessions')) {
573
            $sessionId = api_get_session_id();
574
            $sessionCondition = api_get_session_condition($sessionId);
575
        }
576
577
        // Database table definitions
578
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
579
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
580
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
581
582
        $actions = '<a
583
            href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'.
584
            Display::getMdiIcon(ActionIcon::BACK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Back to').' '.get_lang('Reporting overview')).
585
            '</a>';
586
        $actions .= Display::url(
587
            Display::getMdiIcon(ActionIcon::EXPORT_PDF, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Export to PDF')),
588
            'javascript: void(0);',
589
            ['onclick' => 'exportToPdf();']
590
        );
591
592
        echo Display::toolbarAction('survey', [$actions]);
593
594
        $fromUntil = sprintf(
595
            get_lang('From %s until %s'),
596
            api_get_local_time($survey->getAvailFrom()),
597
            api_get_local_time($survey->getAvailTill())
598
        );
599
        $max = 80;
600
        $data = [
601
            get_lang('Survey title') => cut(strip_tags($survey->getTitle()), $max),
602
            get_lang('Survey subtitle') => cut(strip_tags($survey->getSubtitle()), $max),
603
            get_lang('Dates') => $fromUntil,
604
            get_lang('Survey introduction') => cut(strip_tags($survey->getIntro()), $max),
605
        ];
606
607
        $table = new HTML_Table(['id' => 'pdf_table', 'class' => 'table']);
608
        $row = 0;
609
        foreach ($data as $label => $item) {
610
            $table->setCellContents($row, 0, $label);
611
            $table->setCellContents($row, 1, $item);
612
            $row++;
613
        }
614
615
        $questions = $survey->getQuestions();
616
        $numberOfQuestions = 0;
617
        foreach ($questions as $question) {
618
            if ('pagebreak' !== $question->getType()) {
619
                $numberOfQuestions++;
620
            }
621
        }
622
623
        $newQuestionList = [];
624
        if ($numberOfQuestions > 0) {
625
            $limitStatement = null;
626
            if (!$singlePage) {
627
                echo '<div id="question_report_questionnumbers" class="pagination">';
628
                if (0 != $currentQuestion) {
629
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
630
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset - 1).'">'
631
                        .get_lang('Previous question').'</a></li>';
632
                }
633
634
                for ($i = 1; $i <= $numberOfQuestions; $i++) {
635
                    if ($offset != $i - 1) {
636
                        echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
637
                            .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($i - 1).'">'.$i.'</a></li>';
638
                    } else {
639
                        echo '<li class="disabled"s><a href="#">'.$i.'</a></li>';
640
                    }
641
                }
642
                if ($currentQuestion < ($numberOfQuestions - 1)) {
643
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
644
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset + 1).'">'
645
                        .get_lang('Next question').'</li></a>';
646
                }
647
                echo '</ul>';
648
                echo '</div>';
649
                $limitStatement = " LIMIT $offset, 1";
650
            }
651
652
            // Getting the question information
653
            /*$sql = "SELECT * FROM $table_survey_question
654
                    WHERE
655
                        survey_id = $surveyId AND
656
                        survey_question NOT LIKE '%{{%' AND
657
                        type <>'pagebreak'
658
                    ORDER BY sort ASC
659
                    $limitStatement";
660
            $result = Database::query($sql);
661
            while ($row = Database::fetch_array($result)) {*/
662
            foreach ($questions as $question) {
663
                if (strpos($question->getSurveyQuestion(), '%{{%') && 'pagebreak' !== $question->getType()) {
664
                    continue;
665
                }
666
                $newQuestionList[$question->getIid()] = $question;
667
            }
668
        }
669
        echo '<div id="question_results">';
670
        /** @var CSurveyQuestion $question */
671
        foreach ($newQuestionList as $question) {
672
            $chartData = [];
673
            $options = [];
674
            $questionId = $question->getIid();
675
676
            echo '<div class="question-item">';
677
            echo '<div class="title-question">';
678
            echo strip_tags($question->getSurveyQuestion());
679
            echo '</div>';
680
            $type = $question->getType();
681
682
            if ('score' === $type) {
683
                /** @todo This function should return the options as this is needed further in the code */
684
                $options = self::display_question_report_score($survey, $question, $offset);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $options is correct as self::display_question_r...ey, $question, $offset) targeting SurveyUtil::display_question_report_score() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
685
            } elseif ('open' === $type || 'comment' === $type) {
686
                echo '<div class="open-question">';
687
                /** @todo Also get the user who has answered this */
688
                $sql = "SELECT * FROM $table_survey_answer
689
                        WHERE
690
                            survey_id= $surveyId AND
691
                            question_id = $questionId ";
692
                $result = Database::query($sql);
693
                while ($row = Database::fetch_assoc($result)) {
694
                    echo $row['option_id'].'<hr noshade="noshade" size="1" />';
695
                }
696
                echo '</div>';
697
            } else {
698
                // Getting the options ORDER BY sort ASC
699
                $sql = "SELECT * FROM $table_survey_question_option
700
                        WHERE
701
                            survey_id = $surveyId AND
702
                            question_id = $questionId
703
                        ORDER BY sort ASC";
704
                $result = Database::query($sql);
705
                while ($row = Database::fetch_assoc($result)) {
706
                    $options[$row['iid']] = $row;
707
                }
708
                // Getting the answers
709
                $sql = "SELECT *, count(iid) as total
710
                        FROM $table_survey_answer
711
                        WHERE
712
                            survey_id = $surveyId AND
713
                            question_id = $questionId
714
                        GROUP BY option_id, value";
715
                $result = Database::query($sql);
716
                $number_of_answers = [];
717
                $data = [];
718
                while ($row = Database::fetch_assoc($result)) {
719
                    if (!isset($number_of_answers[$row['question_id']])) {
720
                        $number_of_answers[$row['question_id']] = 0;
721
                    }
722
                    $number_of_answers[$row['question_id']] += $row['total'];
723
                    if ('multiplechoiceother' === $type) {
724
                        $parts = ch_multiplechoiceother::decodeOptionValue($row['option_id']);
725
                        $row['option_id'] = $parts[0];
726
                    }
727
                    $data[$row['option_id']] = $row;
728
                }
729
730
                foreach ($options as $option) {
731
                    $optionText = strip_tags($option['option_text']);
732
                    $optionText = html_entity_decode($optionText);
733
                    $votes = 0;
734
                    if (isset($data[$option['iid']]['total'])) {
735
                        $votes = $data[$option['iid']]['total'];
736
                    }
737
                    array_push($chartData, ['option' => $optionText, 'votes' => $votes]);
738
                }
739
                $chartContainerId = 'chartContainer'.$questionId;
740
                echo '<div id="'.$chartContainerId.'" style="text-align:center;">';
741
                echo self::drawChart($chartData, false, $chartContainerId, false);
742
                echo '</div>';
743
744
                // displaying the table: headers
745
                echo '<table class="display-survey table" id="table_'.$chartContainerId.'">';
746
                echo '';
747
                echo '	<tr>';
748
                echo '		<th style="width: 50%">&nbsp;</th>';
749
                echo '		<th style="width: 10%">'.get_lang('Absolute total').'</th>';
750
                echo '		<th style="width: 10%">'.get_lang('Percentage').'</th>';
751
                echo '		<th style="width: 30%">'.get_lang('Graphic').'</th>';
752
                echo '	</tr>';
753
754
                // Displaying the table: the content
755
                if (is_array($options)) {
756
                    foreach ($options as $key => &$value) {
757
                        if ('multiplechoiceother' === $type && 'other' === $value['option_text']) {
758
                            $value['option_text'] = get_lang('Please specify:');
759
                        }
760
761
                        $absolute_number = null;
762
                        if (isset($data[$value['iid']])) {
763
                            $absolute_number = $data[$value['iid']]['total'];
764
                        }
765
                        if ('percentage' === $type && empty($absolute_number)) {
766
                            continue;
767
                        }
768
                        $number_of_answers[$option['question_id']] = isset($number_of_answers[$option['question_id']])
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $option does not seem to be defined for all execution paths leading up to this point.
Loading history...
769
                            ? $number_of_answers[$option['question_id']]
770
                            : 0;
771
                        if (0 == $number_of_answers[$option['question_id']]) {
772
                            $answers_number = 0;
773
                        } else {
774
                            $answers_number = $absolute_number / $number_of_answers[$option['question_id']] * 100;
775
                        }
776
                        echo '	<tr>';
777
                        echo '<td>'.$value['option_text'].'</td>';
778
                        echo '<td>';
779
                        if (0 != $absolute_number) {
780
                            echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?'.api_get_cidreq().'&action='.$action
781
                                .'&survey_id='.$surveyId.'&question='.$offset.'&viewoption='
782
                                .$value['iid'].'">'.$absolute_number.'</a>';
783
                        } else {
784
                            echo '0';
785
                        }
786
787
                        echo '      </td>';
788
                        echo '<td>'.round($answers_number, 2).' %</td>';
789
                        echo '<td>';
790
                        $size = $answers_number * 2;
791
                        if ($size > 0) {
792
                            echo '<div
793
                                    style="border:1px solid #264269; background-color:#aecaf4; height:10px;
794
                                    width:'.$size.'px">
795
                                    &nbsp;
796
                                    </div>';
797
                        } else {
798
                            echo '<div style="text-align: left;">'.get_lang("No data available").'</div>';
799
                        }
800
                        echo ' </td>';
801
                        echo ' </tr>';
802
                    }
803
                }
804
805
                $optionResult = '';
806
                if (isset($option['question_id']) && isset($number_of_answers[$option['question_id']])) {
807
                    if (0 == $number_of_answers[$option['question_id']]) {
808
                        $optionResult = '0';
809
                    } else {
810
                        $optionResult = $number_of_answers[$option['question_id']];
811
                    }
812
                }
813
814
                // displaying the table: footer (totals)
815
                echo '	<tr>
816
                            <td><b>'.get_lang('Total').'</b></td>
817
                            <td><b>'.$optionResult.'</b></td>
818
                            <td>&nbsp;</td>
819
                            <td>&nbsp;</td>
820
                        </tr>
821
                        </table>';
822
            }
823
            echo '</div>';
824
        }
825
        echo '</div>';
826
827
        // Survey information, needed for the PDF export.
828
        echo Display::page_subheader(get_lang('Survey')).'<br />';
829
        $table->display();
830
831
        if (isset($_GET['viewoption'])) {
832
            echo '<div class="answered-people">';
833
            echo '<h4>'.get_lang('People who have chosen this answer').': '
834
                .strip_tags($options[Security::remove_XSS($_GET['viewoption'])]['option_text']).'</h4>';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $options seems to be defined by a foreach iteration on line 671. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
835
836
            if (is_numeric($_GET['value'])) {
837
                $sql_restriction = "AND value='".Database::escape_string($_GET['value'])."'";
838
            }
839
840
            $sql = "SELECT user FROM $table_survey_answer
841
                    WHERE
842
                        c_id = $course_id AND
843
                        option_id = '".Database::escape_string($_GET['viewoption'])."'
844
                        $sql_restriction $sessionCondition";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sql_restriction does not seem to be defined for all execution paths leading up to this point.
Loading history...
845
            $result = Database::query($sql);
846
            echo '<ul>';
847
            while ($row = Database::fetch_assoc($result)) {
848
                $user_info = api_get_user_info($row['user']);
849
                echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?'.api_get_cidreq().'&action=userreport&survey_id='
850
                    .$surveyId.'&user='.$row['user'].'">'
851
                    .$user_info['complete_name_with_username']
852
                    .'</a></li>';
853
            }
854
            echo '</ul>';
855
            echo '</div>';
856
        }
857
    }
858
859
    /**
860
     * Display score data about a survey question.
861
     *
862
     * @param    int    The offset of results shown
863
     */
864
    public static function display_question_report_score(CSurvey $survey, CSurveyQuestion $question, $offset)
865
    {
866
        // Database table definitions
867
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
868
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
869
        $surveyId = $survey->getIid();
870
        $questionId = $question->getIid();
871
        $options = $survey->getOptions();
872
873
        $sessionCondition = '';
874
        if (true === api_get_configuration_value('show_surveys_base_in_sessions')) {
875
            $sessionId = api_get_session_id();
876
            $sessionCondition = api_get_session_condition($sessionId);
877
        }
878
879
        foreach ($options as $option) {
880
            $options[$option->getIid()] = $option;
881
        }
882
883
        // Getting the answers
884
        $sql = "SELECT *, count(iid) as total
885
                FROM $table_survey_answer
886
                WHERE
887
                   survey_id= $surveyId AND
888
                   question_id = '".$questionId."'
889
                   $sessionCondition
890
                GROUP BY option_id, value";
891
        $result = Database::query($sql);
892
        $number_of_answers = 0;
893
        while ($row = Database::fetch_array($result)) {
894
            $number_of_answers += $row['total'];
895
            $data[$row['option_id']][$row['value']] = $row;
896
        }
897
898
        $chartData = [];
899
        /** @var CSurveyQuestionOption $option */
900
        foreach ($options as $option) {
901
            $optionId = $option->getIid();
902
            $optionText = strip_tags($option->getOptionText());
903
            $optionText = html_entity_decode($optionText);
904
            for ($i = 1; $i <= $question->getMaxValue(); $i++) {
905
                $votes = null;
906
                if (isset($data[$optionId][$i])) {
907
                    $votes = $data[$optionId][$i]['total'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.
Loading history...
908
                }
909
910
                if (empty($votes)) {
911
                    $votes = '0';
912
                }
913
                array_push(
914
                    $chartData,
915
                    [
916
                        'serie' => $optionText,
917
                        'option' => $i,
918
                        'votes' => $votes,
919
                    ]
920
                );
921
            }
922
        }
923
        echo '<div id="chartContainer" class="col-md-12">';
924
        echo self::drawChart($chartData, true);
925
        echo '</div>';
926
927
        // Displaying the table: headers
928
        echo '<table class="table">';
929
        echo '	<tr>';
930
        echo '		<th>&nbsp;</th>';
931
        echo '		<th>'.get_lang('Score').'</th>';
932
        echo '		<th>'.get_lang('Absolute total').'</th>';
933
        echo '		<th>'.get_lang('Percentage').'</th>';
934
        echo '		<th>'.get_lang('Graphic').'</th>';
935
        echo '	</tr>';
936
        // Displaying the table: the content
937
        foreach ($options as $key => $value) {
938
            $optionId = $value->getIid();
939
            for ($i = 1; $i <= $question->getMaxValue(); $i++) {
940
                $absolute_number = null;
941
                if (isset($data[$optionId][$i])) {
942
                    $absolute_number = $data[$optionId][$i]['total'];
943
                }
944
945
                echo '<tr>';
946
                echo '<td>'.$value->getOptionText().'</td>';
947
                echo '<td>'.$i.'</td>';
948
949
                echo '<td><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?'.api_get_cidreq().'&action='.$action
950
                    .'&survey_id='.$surveyId.'&question='.Security::remove_XSS($offset)
951
                    .'&viewoption='.$optionId.'&value='.$i.'">'.$absolute_number.'</a></td>';
952
953
                $percentage = 0;
954
                $size = 0;
955
                if (!empty($number_of_answers)) {
956
                    $percentage = round($absolute_number / $number_of_answers * 100, 2);
957
                    $size = ($absolute_number / $number_of_answers * 100 * 2);
958
                }
959
                echo '<td>'.$percentage.' %</td>';
960
                echo '<td>';
961
                if ($size > 0) {
962
                    echo '<div
963
                            style="border:1px solid #264269;
964
                            background-color:#aecaf4;
965
                            height:10px; width:'.$size.'px">
966
                            &nbsp;
967
                        </div>';
968
                }
969
                echo '		</td>';
970
                echo '	</tr>';
971
            }
972
        }
973
        // Displaying the table: footer (totals)
974
        echo '	<tr>';
975
        echo '		<td style="border-top:1px solid black"><b>'.get_lang('Total').'</b></td>';
976
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
977
        echo '		<td style="border-top:1px solid black"><b>'.$number_of_answers.'</b></td>';
978
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
979
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
980
        echo '	</tr>';
981
        echo '</table>';
982
    }
983
984
    /**
985
     * This functions displays the complete reporting.
986
     *
987
     * @param int  $userId
988
     * @param bool $addActionBar
989
     * @param bool $addFilters
990
     * @param bool $addExtraFields
991
     *
992
     * @return string
993
     */
994
    public static function displayCompleteReport(
995
        CSurvey $survey,
996
        $userId = 0,
997
        $addActionBar = true,
998
        $addFilters = true,
999
        $addExtraFields = true,
1000
        $lpItemId = 0
1001
    ) {
1002
        // Database table definitions
1003
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1004
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1005
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1006
1007
        $surveyId = $survey->getIid();
1008
        $course_id = api_get_course_int_id();
1009
1010
        if (empty($surveyId) || empty($course_id)) {
1011
            return '';
1012
        }
1013
1014
        $sessionCondition = '';
1015
        if (true === api_get_configuration_value('show_surveys_base_in_sessions')) {
1016
            $sessionId = api_get_session_id();
1017
            $sessionCondition = api_get_session_condition($sessionId);
1018
        }
1019
        $lpItemCondition = '';
1020
        if (!empty($lpItemId)) {
1021
            $lpItemCondition = " AND c_lp_item_id = $lpItemId";
1022
        }
1023
1024
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
1025
        $content = '';
1026
        if (!empty($lpItemId)) {
1027
            $tableLp = Database::get_course_table(TABLE_LP_MAIN);
1028
            $tableLpItem = Database::get_course_table(TABLE_LP_ITEM);
1029
            $sql = "SELECT l.name,
1030
                    li.title
1031
                    FROM $tableLpItem li
1032
                    INNER JOIN $tableLp l
1033
                    ON l.iid = li.lp_id AND
1034
                       l.c_id = li.c_id
1035
                    WHERE li.c_id = $course_id AND
1036
                          li.iid = $lpItemId";
1037
            $rs = Database::query($sql);
1038
            if (Database::num_rows($rs) > 0) {
1039
                $row = Database::fetch_assoc($rs);
1040
                $lpName = $row['name'];
1041
                $lpItemTitle = $row['title'];
1042
                $content .= '<h3>'.$lpName.' : '.$lpItemTitle.'</h3>';
1043
            }
1044
        }
1045
1046
        if ($addActionBar) {
1047
            $actions = '<a
1048
                href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'
1049
                .Display::getMdiIcon(ActionIcon::BACK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Back to').' '.get_lang('Reporting overview'),
1050
                    [],
1051
                    ICON_SIZE_MEDIUM
1052
                )
1053
                .'</a>';
1054
            $actions .= '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1a.submit();">'
1055
                .Display::getMdiIcon(ActionIcon::EXPORT_CSV, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('CSV export')).'</a>';
1056
            $actions .= '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1b.submit();">'
1057
                .Display::getMdiIcon(ActionIcon::EXPORT_SPREADSHEET, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Excel export')).'</a>';
1058
            $actions .= '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1c.submit();">'
1059
                .Display::getMdiIcon(ActionIcon::EXPORT_ARCHIVE, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Export as compact CSV')).'</a>';
1060
1061
            $content .= Display::toolbarAction('survey', [$actions]);
1062
1063
            // The form
1064
            $content .= '<form
1065
                id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
1066
                .$surveyId.'&'.api_get_cidreq().'">';
1067
            $content .= '<input type="hidden" name="export_report" value="export_report">';
1068
            $content .= '<input type="hidden" name="export_format" value="csv">';
1069
            $content .= '</form>';
1070
            $content .= '<form id="form1b" name="form1b" method="post" action="'.api_get_self(
1071
                ).'?action='.$action.'&survey_id='
1072
                .$surveyId.'&'.api_get_cidreq().'">';
1073
            $content .= '<input type="hidden" name="export_report" value="export_report">';
1074
            $content .= '<input type="hidden" name="export_format" value="xls">';
1075
            $content .= '</form>';
1076
            $content .= '<form id="form1c" name="form1c" method="post" action="'.api_get_self(
1077
                ).'?action='.$action.'&survey_id='
1078
                .$surveyId.'&'.api_get_cidreq().'">';
1079
            $content .= '<input type="hidden" name="export_report" value="export_report">';
1080
            $content .= '<input type="hidden" name="export_format" value="csv-compact">';
1081
            $content .= '</form>';
1082
        }
1083
1084
        $content .= '<form
1085
            id="form2"
1086
            name="form2"
1087
            method="post"
1088
            action="'.api_get_self().'?action='.$action.'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
1089
        $content .= '<br /><table class="table table-hover table-striped data_table" border="1">';
1090
        // Getting the number of options per question
1091
        $content .= '<tr>';
1092
        $content .= '<th>';
1093
1094
        if ($addFilters) {
1095
            if ((isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
1096
                (isset($_POST['export_report']) && $_POST['export_report'])
1097
            ) {
1098
                $content .= '<button class="cancel"
1099
                                type="submit"
1100
                                name="reset_question_filter" value="'.get_lang('Reset filter').'">'.
1101
                                get_lang('Reset filter').'</button>';
1102
            }
1103
            $content .= '<button
1104
                            class = "save"
1105
                            type="submit" name="submit_question_filter" value="'.get_lang('Filter').'">'.
1106
                            get_lang('Filter').'</button>';
1107
            $content .= '</th>';
1108
        }
1109
1110
        $display_extra_user_fields = false;
1111
        if ($addExtraFields) {
1112
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
1113
                    isset($_POST['export_report']) && $_POST['export_report']) ||
1114
                !empty($_POST['fields_filter'])
1115
            ) {
1116
                // Show user fields section with a big th colspan that spans over all fields
1117
                $extra_user_fields = UserManager::get_extra_fields(
1118
                    0,
1119
                    0,
1120
                    5,
1121
                    'ASC',
1122
                    false,
1123
                    true
1124
                );
1125
                $num = count($extra_user_fields);
1126
                if ($num > 0) {
1127
                    $content .= '<th '.($num > 0 ? ' colspan="'.$num.'"' : '').'>';
1128
                    $content .= '<label>';
1129
                    if ($addFilters) {
1130
                        $content .= '<input type="checkbox" name="fields_filter" value="1" checked="checked"/> ';
1131
                    }
1132
                    $content .= get_lang('Profile attributes');
1133
                    $content .= '</label>';
1134
                    $content .= '</th>';
1135
                    $display_extra_user_fields = true;
1136
                }
1137
            }
1138
        }
1139
1140
        $sql = "SELECT
1141
                  q.iid question_id,
1142
                  q.type,
1143
                  q.survey_question,
1144
                  count(o.iid) as number_of_options
1145
				FROM $table_survey_question q
1146
				LEFT JOIN $table_survey_question_option o
1147
				ON q.iid = o.question_id
1148
				WHERE
1149
				    survey_question NOT LIKE '%{{%' AND
1150
				    q.survey_id = '".$surveyId."'
1151
				GROUP BY q.iid
1152
				ORDER BY q.sort ASC";
1153
        $result = Database::query($sql);
1154
        $questions = [];
1155
        while ($row = Database::fetch_array($result)) {
1156
            // We show the questions if
1157
            // 1. there is no question filter and the export button has not been clicked
1158
            // 2. there is a quesiton filter but the question is selected for display
1159
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
1160
                (is_array($_POST['questions_filter']) &&
1161
                in_array($row['question_id'], $_POST['questions_filter']))
1162
            ) {
1163
                // We do not show comment and pagebreak question types
1164
                if ('pagebreak' !== $row['type']) {
1165
                    $content .= ' <th';
1166
                    if ($row['number_of_options'] > 0 && 'percentage' !== $row['type']) {
1167
                        $content .= ' colspan="'.$row['number_of_options'].'"';
1168
                    }
1169
                    $content .= '>';
1170
                    $content .= '<label>';
1171
                    if ($addFilters) {
1172
                        $content .= '<input
1173
                                type="checkbox"
1174
                                name="questions_filter[]" value="'.$row['question_id'].'" checked="checked"/>';
1175
                    }
1176
                    $content .= $row['survey_question'];
1177
                    $content .= '</label>';
1178
                    $content .= '</th>';
1179
                }
1180
                // No column at all if it's not a question
1181
            }
1182
            $questions[$row['question_id']] = $row;
1183
        }
1184
        $content .= '	</tr>';
1185
1186
        // Getting all the questions and options
1187
        $content .= '	<tr>';
1188
        $content .= '		<th>&nbsp;</th>'; // the user column
1189
1190
        if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
1191
            isset($_POST['export_report']) && $_POST['export_report']) || !empty($_POST['fields_filter'])
1192
        ) {
1193
            if ($addExtraFields) {
1194
                // show the fields names for user fields
1195
                foreach ($extra_user_fields as &$field) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $extra_user_fields does not seem to be defined for all execution paths leading up to this point.
Loading history...
1196
                    $content .= '<th>'.$field[3].'</th>';
1197
                }
1198
            }
1199
        }
1200
1201
        // cells with option (none for open question)
1202
        $sql = "SELECT
1203
                    sq.iid question_id,
1204
                    sq.survey_id,
1205
                    sq.survey_question,
1206
                    sq.display,
1207
                    sq.sort,
1208
                    sq.type,
1209
                    sqo.iid question_option_id,
1210
                    sqo.option_text,
1211
                    sqo.sort as option_sort
1212
				FROM $table_survey_question sq
1213
				LEFT JOIN $table_survey_question_option sqo
1214
				ON sq.iid = sqo.question_id
1215
				WHERE
1216
				    survey_question NOT LIKE '%{{%' AND
1217
				    sq.survey_id = $surveyId
1218
				ORDER BY sq.sort ASC, sqo.sort ASC";
1219
        $result = Database::query($sql);
1220
1221
        $display_percentage_header = 1;
1222
        $possible_answers = [];
1223
        // in order to display only once the cell option (and not 100 times)
1224
        while ($row = Database::fetch_array($result)) {
1225
            // We show the options if
1226
            // 1. there is no question filter and the export button has not been clicked
1227
            // 2. there is a question filter but the question is selected for display
1228
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
1229
                (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))
1230
            ) {
1231
                // we do not show comment and pagebreak question types
1232
                if ('open' == $row['type'] || 'comment' == $row['type']) {
1233
                    $content .= '<th>&nbsp;-&nbsp;</th>';
1234
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1235
                    $display_percentage_header = 1;
1236
                } elseif ('percentage' == $row['type'] && $display_percentage_header) {
1237
                    $content .= '<th>&nbsp;%&nbsp;</th>';
1238
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1239
                    $display_percentage_header = 0;
1240
                } elseif ('percentage' == $row['type']) {
1241
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1242
                } elseif ('pagebreak' != $row['type'] && 'percentage' != $row['type']) {
1243
                    $content .= '<th>';
1244
                    $content .= $row['option_text'];
1245
                    $content .= '</th>';
1246
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1247
                    $display_percentage_header = 1;
1248
                }
1249
            }
1250
        }
1251
1252
        $content .= '	</tr>';
1253
1254
        $userCondition = '';
1255
        if (!empty($userId)) {
1256
            $userId = (int) $userId;
1257
            $userCondition = " AND user = $userId ";
1258
        }
1259
1260
        // Getting all the answers of the users
1261
        $old_user = '';
1262
        $answers_of_user = [];
1263
        $sql = "SELECT * FROM $table_survey_answer
1264
                WHERE
1265
                    survey_id = $surveyId
1266
                    $userCondition
1267
                    $sessionCondition
1268
                    $lpItemCondition
1269
                ORDER BY iid, user ASC";
1270
        $result = Database::query($sql);
1271
        $i = 1;
1272
        while ($row = Database::fetch_array($result)) {
1273
            if ($old_user != $row['user'] && '' != $old_user) {
1274
                $userParam = $old_user;
1275
                if (0 != $survey->getAnonymous()) {
1276
                    $userParam = $i;
1277
                    $i++;
1278
                }
1279
                $content .= self::display_complete_report_row(
1280
                    $survey,
1281
                    $possible_answers,
1282
                    $answers_of_user,
1283
                    $userParam,
1284
                    $questions,
1285
                    $display_extra_user_fields
1286
                );
1287
                $answers_of_user = [];
1288
            }
1289
            if (isset($questions[$row['question_id']]) &&
1290
                'open' != $questions[$row['question_id']]['type'] &&
1291
                'comment' != $questions[$row['question_id']]['type']
1292
            ) {
1293
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1294
            } else {
1295
                $answers_of_user[$row['question_id']][0] = $row;
1296
            }
1297
            $old_user = $row['user'];
1298
        }
1299
1300
        $userParam = $old_user;
1301
        if (0 != $survey->getAnonymous()) {
1302
            $userParam = $i;
1303
            $i++;
1304
        }
1305
1306
        $content .= self::display_complete_report_row(
1307
            $survey,
1308
            $possible_answers,
1309
            $answers_of_user,
1310
            $userParam,
1311
            $questions,
1312
            $display_extra_user_fields
1313
        );
1314
1315
        // This is to display the last user
1316
        $content .= '</table>';
1317
        $content .= '</form>';
1318
1319
        return $content;
1320
    }
1321
1322
    /**
1323
     * Return user answers in a row.
1324
     *
1325
     * @return string
1326
     */
1327
    public static function display_complete_report_row(
1328
        CSurvey $survey,
1329
        $possible_options,
1330
        $answers_of_user,
1331
        $user,
1332
        $questions,
1333
        $display_extra_user_fields = false
1334
    ) {
1335
        $user = Security::remove_XSS($user);
1336
        $surveyId = $survey->getIid();
1337
1338
        if (empty($surveyId)) {
1339
            return '';
1340
        }
1341
1342
        $content = '<tr>';
1343
        $url = api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq();
1344
        if (0 == $survey->getAnonymous()) {
1345
            if (0 !== (int) $user) {
1346
                $userInfo = api_get_user_info($user);
1347
                $user_displayed = '-';
1348
                if (!empty($userInfo)) {
1349
                    $user_displayed = $userInfo['complete_name_with_username'];
1350
                }
1351
1352
                $content .= '<th>
1353
                    <a href="'.$url.'&action=userreport&user='.$user.'">'
1354
                        .$user_displayed.'
1355
                    </a>
1356
                    </th>'; // the user column
1357
            } else {
1358
                $content .= '<th>'.$user.'</th>'; // the user column
1359
            }
1360
        } else {
1361
            $content .= '<th>'.get_lang('Anonymous').' '.$user.'</th>';
1362
        }
1363
1364
        if ($display_extra_user_fields) {
1365
            // Show user fields data, if any, for this user
1366
            $user_fields_values = UserManager::get_extra_user_data(
1367
                $user,
1368
                false,
1369
                false,
1370
                false,
1371
                true
1372
            );
1373
            foreach ($user_fields_values as &$value) {
1374
                $content .= '<td align="center">'.$value.'</td>';
1375
            }
1376
        }
1377
1378
        if (is_array($possible_options)) {
1379
            foreach ($possible_options as $question_id => &$possible_option) {
1380
                if ('open' === $questions[$question_id]['type'] || 'comment' === $questions[$question_id]['type']) {
1381
                    $content .= '<td align="center">';
1382
                    if (isset($answers_of_user[$question_id]) && isset($answers_of_user[$question_id]['0'])) {
1383
                        $content .= $answers_of_user[$question_id]['0']['option_id'];
1384
                    }
1385
                    $content .= '</td>';
1386
                } else {
1387
                    foreach ($possible_option as $option_id => $value) {
1388
                        if ('multiplechoiceother' === $questions[$question_id]['type']) {
1389
                            foreach ($answers_of_user[$question_id] as $key => $newValue) {
1390
                                $parts = ch_multiplechoiceother::decodeOptionValue($key);
1391
                                if (isset($parts[0])) {
1392
                                    $data = $answers_of_user[$question_id][$key];
1393
                                    unset($answers_of_user[$question_id][$key]);
1394
                                    $newKey = $parts[0];
1395
                                    $answers_of_user[$question_id][$newKey] = $data;
1396
                                }
1397
                            }
1398
                        }
1399
                        if ('percentage' === $questions[$question_id]['type']) {
1400
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1401
                                $content .= "<td align='center'>";
1402
                                $content .= $answers_of_user[$question_id][$option_id]['value'];
1403
                                $content .= "</td>";
1404
                            }
1405
                        } else {
1406
                            $content .= '<td align="center">';
1407
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1408
                                if (0 != $answers_of_user[$question_id][$option_id]['value']) {
1409
                                    $content .= $answers_of_user[$question_id][$option_id]['value'];
1410
                                } else {
1411
                                    $content .= 'v';
1412
                                }
1413
                            }
1414
                        }
1415
                    }
1416
                }
1417
            }
1418
        }
1419
1420
        $content .= '</tr>';
1421
1422
        return $content;
1423
    }
1424
1425
    /**
1426
     * Quite similar to display_complete_report(), returns an HTML string
1427
     * that can be used in a csv file.
1428
     *
1429
     * @param array $survey_data The basic survey data as initially obtained by SurveyManager::get_survey()
1430
     * @param int   $user_id     The ID of the user asking for the report
1431
     * @param bool  $compact     Whether to present the long (v marks with multiple columns per question) or compact
1432
     *                           (one column per question) answers format
1433
     *
1434
     * @todo consider merging this function with display_complete_report
1435
     *
1436
     * @throws Exception
1437
     *
1438
     * @return string The contents of a csv file
1439
     *
1440
     * @author Patrick Cool <[email protected]>, Ghent University
1441
     *
1442
     * @version February 2007
1443
     */
1444
    public static function export_complete_report($survey_data, $user_id = 0, $compact = false)
1445
    {
1446
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1447
1448
        if (empty($surveyId)) {
1449
            return false;
1450
        }
1451
1452
        $course = api_get_course_info();
1453
        $course_id = $course['real_id'];
1454
1455
        $sessionCondition = '';
1456
        if (true === api_get_configuration_value('show_surveys_base_in_sessions')) {
1457
            $sessionId = api_get_session_id();
1458
            $sessionCondition = api_get_session_condition($sessionId);
1459
        }
1460
1461
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1462
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1463
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1464
1465
        $translate = false;
1466
        if ('true' === api_get_setting('editor.translate_html')) {
1467
            $translate = true;
1468
        }
1469
1470
        // The first column
1471
        $return = ';';
1472
1473
        // Show extra fields blank space (enough for extra fields on next line)
1474
        $extra_user_fields = UserManager::get_extra_fields(
1475
            0,
1476
            0,
1477
            5,
1478
            'ASC',
1479
            false,
1480
            true
1481
        );
1482
1483
        $num = count($extra_user_fields);
1484
        $return .= str_repeat(';', $num);
1485
1486
        $sql = "SELECT
1487
                    questions.iid,
1488
                    questions.type,
1489
                    questions.survey_question,
1490
                    count(options.iid) as number_of_options
1491
				FROM $table_survey_question questions
1492
                LEFT JOIN $table_survey_question_option options
1493
				ON
1494
				  questions.iid = options.question_id
1495
				WHERE
1496
				    survey_question NOT LIKE '%{{%' AND
1497
				    questions.type <> 'pagebreak' AND
1498
				    questions.survey_id = $surveyId
1499
				GROUP BY questions.iid
1500
				ORDER BY questions.sort ASC";
1501
1502
        $result = Database::query($sql);
1503
        while ($row = Database::fetch_array($result)) {
1504
            if ($translate) {
1505
                $row['survey_question'] = api_get_filtered_multilingual_HTML_string($row['survey_question'], $course['language']);
1506
            }
1507
            // We show the questions if
1508
            // 1. there is no question filter and the export button has not been clicked
1509
            // 2. there is a quesiton filter but the question is selected for display
1510
            if (!(isset($_POST['submit_question_filter'])) ||
1511
                (isset($_POST['submit_question_filter']) &&
1512
                    is_array($_POST['questions_filter']) &&
1513
                    in_array($row['iid'], $_POST['questions_filter']))
1514
            ) {
1515
                if (0 == $row['number_of_options'] || $compact) {
1516
                    $return .= str_replace(
1517
                        "\r\n",
1518
                        '  ',
1519
                        api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1520
                    )
1521
                    .';';
1522
                } else {
1523
                    for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1524
                        $return .= str_replace(
1525
                            "\r\n",
1526
                            '  ',
1527
                            api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1528
                        )
1529
                        .';';
1530
                    }
1531
                }
1532
            }
1533
        }
1534
1535
        $return .= "\n";
1536
        // Getting all the questions and options
1537
        $return .= ';';
1538
        // Show the fields names for user fields
1539
        if (!empty($extra_user_fields)) {
1540
            foreach ($extra_user_fields as &$field) {
1541
                if ($translate) {
1542
                    $field[3] = api_get_filtered_multilingual_HTML_string($field[3], $course['language']);
1543
                }
1544
                $return .= '"'
1545
                    .str_replace(
1546
                        "\r\n",
1547
                        '  ',
1548
                        api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1549
                    )
1550
                    .'";';
1551
            }
1552
        }
1553
1554
        $sql = "SELECT DISTINCT
1555
		            survey_question.iid question_id,
1556
		            survey_question.survey_id,
1557
		            survey_question.survey_question,
1558
		            survey_question.display,
1559
		            survey_question.sort,
1560
		            survey_question.type,
1561
                    survey_question_option.iid question_option_id,
1562
                    survey_question_option.option_text,
1563
                    survey_question_option.sort as option_sort
1564
				FROM $table_survey_question survey_question
1565
				LEFT JOIN $table_survey_question_option survey_question_option
1566
				ON
1567
				    survey_question.iid = survey_question_option.question_id
1568
				WHERE
1569
				    survey_question NOT LIKE '%{{%' AND
1570
				    survey_question.type <> 'pagebreak' AND
1571
				    survey_question.survey_id = $surveyId
1572
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1573
        $result = Database::query($sql);
1574
        $possible_answers = [];
1575
        $possible_answers_type = [];
1576
        while ($row = Database::fetch_array($result)) {
1577
            // We show the options if
1578
            // 1. there is no question filter and the export button has not been clicked
1579
            // 2. there is a question filter but the question is selected for display
1580
            if ($translate) {
1581
                $row['option_text'] = api_get_filtered_multilingual_HTML_string($row['option_text'], $course['language']);
1582
            }
1583
            if (!(isset($_POST['submit_question_filter'])) || (
1584
                is_array($_POST['questions_filter']) &&
1585
                in_array($row['question_id'], $_POST['questions_filter'])
1586
            )
1587
            ) {
1588
                $row['option_text'] = str_replace(["\r", "\n"], ['', ''], $row['option_text']);
1589
                if (!$compact) {
1590
                    $return .= api_html_entity_decode(strip_tags($row['option_text']), ENT_QUOTES).';';
1591
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1592
                } else {
1593
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['option_text'];
1594
                }
1595
                $possible_answers_type[$row['question_id']] = $row['type'];
1596
            }
1597
        }
1598
1599
        $return .= "\n";
1600
1601
        // Getting all the answers of the users
1602
        $old_user = '';
1603
        $answers_of_user = [];
1604
        $sql = "SELECT * FROM $table_survey_answer
1605
		        WHERE
1606
		          survey_id = $surveyId
1607
		          $sessionCondition
1608
		          ";
1609
        if (0 != $user_id) {
1610
            $user_id = (int) $user_id;
1611
            $sql .= " AND user = $user_id ";
1612
        }
1613
        $sql .= ' ORDER BY user ASC ';
1614
1615
        $questionIdList = array_keys($possible_answers_type);
1616
        $open_question_iterator = 1;
1617
        $result = Database::query($sql);
1618
        while ($row = Database::fetch_assoc($result)) {
1619
            if (!in_array($row['question_id'], $questionIdList)) {
1620
                continue;
1621
            }
1622
            if ($old_user != $row['user'] && '' != $old_user) {
1623
                $return .= self::export_complete_report_row(
1624
                    $survey_data,
1625
                    $possible_answers,
1626
                    $answers_of_user,
1627
                    $old_user,
1628
                    true,
1629
                    $compact
1630
                );
1631
                $answers_of_user = [];
1632
            }
1633
1634
            if ('open' === $possible_answers_type[$row['question_id']] ||
1635
                'comment' === $possible_answers_type[$row['question_id']]
1636
            ) {
1637
                $temp_id = 'open'.$open_question_iterator;
1638
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1639
                $open_question_iterator++;
1640
            } else {
1641
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1642
            }
1643
            $old_user = $row['user'];
1644
        }
1645
1646
        // This is to display the last user
1647
        $return .= self::export_complete_report_row(
1648
            $survey_data,
1649
            $possible_answers,
1650
            $answers_of_user,
1651
            $old_user,
1652
            true,
1653
            $compact
1654
        );
1655
1656
        return $return;
1657
    }
1658
1659
    /**
1660
     * Add a line to the csv file.
1661
     *
1662
     * @param array $survey_data               Basic survey data (we're mostly interested in the 'anonymous' index)
1663
     * @param array $possible_options          Possible answers
1664
     * @param array $answers_of_user           User's answers
1665
     * @param mixed $user                      User ID or user details as string - Used as a string in the result
1666
     *                                         string
1667
     * @param bool  $display_extra_user_fields Whether to display user fields or not
1668
     * @param bool  $compact                   Whether to show answers as different column values (true) or one column
1669
     *                                         per option (false, default)
1670
     *
1671
     * @return string One line of the csv file
1672
     *
1673
     * @author Patrick Cool <[email protected]>, Ghent University
1674
     *
1675
     * @version February 2007
1676
     */
1677
    public static function export_complete_report_row(
1678
        CSurvey $survey,
1679
        $possible_options,
1680
        $answers_of_user,
1681
        $user,
1682
        $display_extra_user_fields = false,
1683
        $compact = false
1684
    ) {
1685
        $return = '';
1686
        if (0 == $survey->getAnonymous()) {
1687
            if (0 !== intval($user)) {
1688
                $userInfo = api_get_user_info($user);
1689
                if (!empty($userInfo)) {
1690
                    $user_displayed = $userInfo['complete_name_with_username'];
1691
                } else {
1692
                    $user_displayed = '-';
1693
                }
1694
                $return .= $user_displayed.';';
1695
            } else {
1696
                $return .= $user.';';
1697
            }
1698
        } else {
1699
            $return .= '-;'; // The user column
1700
        }
1701
1702
        if ($display_extra_user_fields) {
1703
            // Show user fields data, if any, for this user
1704
            $user_fields_values = UserManager::get_extra_user_data(
1705
                $user,
1706
                false,
1707
                false,
1708
                false,
1709
                true
1710
            );
1711
            foreach ($user_fields_values as &$value) {
1712
                $return .= '"'.str_replace('"', '""', api_html_entity_decode(strip_tags($value), ENT_QUOTES)).'";';
1713
            }
1714
        }
1715
1716
        if (is_array($possible_options)) {
1717
            foreach ($possible_options as $question_id => $possible_option) {
1718
                if (is_array($possible_option) && count($possible_option) > 0) {
1719
                    foreach ($possible_option as $option_id => &$value) {
1720
                        // For each option of this question, look if it matches the user's answer
1721
                        $my_answer_of_user = !isset($answers_of_user[$question_id]) || isset($answers_of_user[$question_id]) && null == $answers_of_user[$question_id] ? [] : $answers_of_user[$question_id];
1722
                        $key = array_keys($my_answer_of_user);
1723
                        if (isset($key[0]) && 'open' === substr($key[0], 0, 4)) {
1724
                            // If this is an open type question (type starts by 'open'), take whatever answer is given
1725
                            $return .= '"'.
1726
                                str_replace(
1727
                                    '"',
1728
                                    '""',
1729
                                    api_html_entity_decode(
1730
                                        strip_tags(
1731
                                            $answers_of_user[$question_id][$key[0]]['option_id']
1732
                                        ),
1733
                                        ENT_QUOTES
1734
                                    )
1735
                                ).
1736
                                '";';
1737
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
1738
                            //$return .= 'v';
1739
                            if ($compact) {
1740
                                // If we asked for a compact view, show only one column for the question
1741
                                // and fill it with the text of the selected option (i.e. "Yes") instead of an ID
1742
                                if (0 != $answers_of_user[$question_id][$option_id]['value']) {
1743
                                    $return .= $answers_of_user[$question_id][$option_id]['value'].";";
1744
                                } else {
1745
                                    $return .= '"'.
1746
                                        str_replace(
1747
                                            '"',
1748
                                            '""',
1749
                                            api_html_entity_decode(
1750
                                                strip_tags(
1751
                                                    $possible_option[$option_id]
1752
                                                ),
1753
                                                ENT_QUOTES
1754
                                            )
1755
                                        ).
1756
                                        '";';
1757
                                }
1758
                            } else {
1759
                                // If we don't want a compact view, show one column per possible option and mark a 'v'
1760
                                // or the defined value in the corresponding column if the user selected it
1761
                                if (0 != $answers_of_user[$question_id][$option_id]['value']) {
1762
                                    $return .= $answers_of_user[$question_id][$option_id]['value'].";";
1763
                                } else {
1764
                                    $return .= 'v;';
1765
                                }
1766
                            }
1767
                        } else {
1768
                            if (!$compact) {
1769
                                $return .= ';';
1770
                            }
1771
                        }
1772
                    }
1773
                }
1774
            }
1775
        }
1776
        $return .= "\n";
1777
1778
        return $return;
1779
    }
1780
1781
    public static function export_complete_report_xls(CSurvey $survey, $filename, $user_id = 0, $returnFile = false)
1782
    {
1783
        $course_id = api_get_course_int_id();
1784
        $user_id = (int) $user_id;
1785
        $surveyId = $survey->getIid();
1786
1787
        if (empty($course_id) || empty($surveyId)) {
1788
            return false;
1789
        }
1790
1791
        // Show extra fields blank space (enough for extra fields on next line)
1792
        // Show user fields section with a big th colspan that spans over all fields
1793
        $extra_user_fields = UserManager::get_extra_fields(
1794
            0,
1795
            0,
1796
            5,
1797
            'ASC',
1798
            false,
1799
            true
1800
        );
1801
        $list = [];
1802
        $num = count($extra_user_fields);
1803
        for ($i = 0; $i < $num; $i++) {
1804
            $list[0][] = '';
1805
        }
1806
1807
        $display_extra_user_fields = true;
1808
1809
        // Database table definitions
1810
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1811
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1812
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1813
1814
        // First line (questions)
1815
        $sql = "SELECT
1816
                    questions.question_id,
1817
                    questions.type,
1818
                    questions.survey_question,
1819
                    count(options.iid) as number_of_options
1820
				FROM $table_survey_question questions
1821
				LEFT JOIN $table_survey_question_option options
1822
                ON
1823
                  questions.iid = options.question_id
1824
				WHERE
1825
				    survey_question NOT LIKE '%{{%' AND
1826
				    questions.type <> 'pagebreak' AND
1827
				    questions.survey_id = $surveyId
1828
				GROUP BY questions.question_id
1829
				ORDER BY questions.sort ASC";
1830
        $result = Database::query($sql);
1831
        $line = 1;
1832
        $column = 1;
1833
        while ($row = Database::fetch_array($result)) {
1834
            // We show the questions if
1835
            // 1. there is no question filter and the export button has not been clicked
1836
            // 2. there is a quesiton filter but the question is selected for display
1837
            if (!(isset($_POST['submit_question_filter'])) ||
1838
                (isset($_POST['submit_question_filter']) && is_array($_POST['questions_filter']) &&
1839
                in_array($row['question_id'], $_POST['questions_filter']))
1840
            ) {
1841
                // We do not show comment and pagebreak question types
1842
                if ('pagebreak' !== $row['type']) {
1843
                    if (0 == $row['number_of_options'] && ('open' === $row['type'] || 'comment' === $row['type'])) {
1844
                        $list[$line][$column] = api_html_entity_decode(
1845
                            strip_tags($row['survey_question']),
1846
                            ENT_QUOTES
1847
                        );
1848
                        $column++;
1849
                    } else {
1850
                        for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1851
                            $list[$line][$column] = api_html_entity_decode(
1852
                                strip_tags($row['survey_question']),
1853
                                ENT_QUOTES
1854
                            );
1855
                            $column++;
1856
                        }
1857
                    }
1858
                }
1859
            }
1860
        }
1861
1862
        $line++;
1863
        $column = 1;
1864
        // Show extra field values
1865
        if ($display_extra_user_fields) {
1866
            // Show the fields names for user fields
1867
            foreach ($extra_user_fields as &$field) {
1868
                $list[$line][$column] = api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES);
1869
                $column++;
1870
            }
1871
        }
1872
1873
        // Getting all the questions and options (second line)
1874
        $sql = "SELECT
1875
                    survey_question.iid question_id,
1876
                    survey_question.survey_id,
1877
                    survey_question.survey_question,
1878
                    survey_question.display,
1879
                    survey_question.sort,
1880
                    survey_question.type,
1881
                    survey_question_option.iid question_option_id,
1882
                    survey_question_option.option_text,
1883
                    survey_question_option.sort as option_sort
1884
				FROM $table_survey_question survey_question
1885
				LEFT JOIN $table_survey_question_option survey_question_option
1886
				ON
1887
				    survey_question.iid = survey_question_option.question_id
1888
				WHERE
1889
				    survey_question NOT LIKE '%{{%' AND
1890
				    survey_question.type <> 'pagebreak' AND
1891
				    survey_question.survey_id = $surveyId
1892
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1893
        $result = Database::query($sql);
1894
        $possible_answers = [];
1895
        $possible_answers_type = [];
1896
        while ($row = Database::fetch_array($result)) {
1897
            // We show the options if
1898
            // 1. there is no question filter and the export button has not been clicked
1899
            // 2. there is a quesiton filter but the question is selected for display
1900
            if (!isset($_POST['submit_question_filter']) ||
1901
                (isset($_POST['questions_filter']) && is_array($_POST['questions_filter']) &&
1902
                in_array($row['question_id'], $_POST['questions_filter']))
1903
            ) {
1904
                // We do not show comment and pagebreak question types
1905
                if ('pagebreak' !== $row['type']) {
1906
                    $list[$line][$column] = api_html_entity_decode(
1907
                        strip_tags($row['option_text']),
1908
                        ENT_QUOTES
1909
                    );
1910
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1911
                    $possible_answers_type[$row['question_id']] = $row['type'];
1912
                    $column++;
1913
                }
1914
            }
1915
        }
1916
1917
        // Getting all the answers of the users
1918
        $line++;
1919
        $column = 0;
1920
        $old_user = '';
1921
        $answers_of_user = [];
1922
        $sql = "SELECT * FROM $table_survey_answer
1923
                WHERE c_id = $course_id AND survey_id = $surveyId";
1924
        if (0 != $user_id) {
1925
            $sql .= " AND user='".$user_id."' ";
1926
        }
1927
        $sql .= ' ORDER BY user ASC';
1928
1929
        $open_question_iterator = 1;
1930
        $result = Database::query($sql);
1931
        while ($row = Database::fetch_array($result)) {
1932
            if ($old_user != $row['user'] && '' != $old_user) {
1933
                $return = self::export_complete_report_row_xls(
1934
                    $survey,
1935
                    $possible_answers,
1936
                    $answers_of_user,
1937
                    $old_user,
1938
                    true
1939
                );
1940
                foreach ($return as $elem) {
1941
                    $list[$line][$column] = $elem;
1942
                    $column++;
1943
                }
1944
                $answers_of_user = [];
1945
                $line++;
1946
                $column = 0;
1947
            }
1948
            if ('open' === $possible_answers_type[$row['question_id']] || 'comment' === $possible_answers_type[$row['question_id']]) {
1949
                $temp_id = 'open'.$open_question_iterator;
1950
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1951
                $open_question_iterator++;
1952
            } else {
1953
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1954
            }
1955
            $old_user = $row['user'];
1956
        }
1957
1958
        $return = self::export_complete_report_row_xls(
1959
            $survey,
1960
            $possible_answers,
1961
            $answers_of_user,
1962
            $old_user,
1963
            true
1964
        );
1965
1966
        // this is to display the last user
1967
        if (!empty($return)) {
1968
            foreach ($return as $elem) {
1969
                $list[$line][$column] = $elem;
1970
                $column++;
1971
            }
1972
        }
1973
1974
        Export::arrayToXls($list, $filename);
1975
1976
        return null;
1977
    }
1978
1979
    /**
1980
     * Add a line to the csv file.
1981
     *
1982
     * @param array Possible answers
1983
     * @param array User's answers
0 ignored issues
show
Documentation Bug introduced by
The doc comment User's at position 0 could not be parsed: Unknown type name 'User's' at position 0 in User's.
Loading history...
1984
     * @param mixed User ID or user details as string - Used as a string in the result string
1985
     * @param bool Whether to display user fields or not
1986
     *
1987
     * @return array
1988
     */
1989
    public static function export_complete_report_row_xls(
1990
        CSurvey $survey,
1991
        $possible_options,
1992
        $answers_of_user,
1993
        $user,
1994
        $display_extra_user_fields = false
1995
    ) {
1996
        $return = [];
1997
        if (0 == $survey->getAnonymous()) {
1998
            if (0 !== (int) $user) {
1999
                $userInfo = api_get_user_info($user);
2000
                if ($userInfo) {
2001
                    $user_displayed = $userInfo['complete_name_with_username'];
2002
                } else {
2003
                    $user_displayed = '-';
2004
                }
2005
                $return[] = $user_displayed;
2006
            } else {
2007
                $return[] = $user;
2008
            }
2009
        } else {
2010
            $return[] = '-'; // The user column
2011
        }
2012
2013
        if ($display_extra_user_fields) {
2014
            //show user fields data, if any, for this user
2015
            $user_fields_values = UserManager::get_extra_user_data(
2016
                $user,
2017
                false,
2018
                false,
2019
                false,
2020
                true
2021
            );
2022
            foreach ($user_fields_values as $value) {
2023
                $return[] = api_html_entity_decode(strip_tags($value), ENT_QUOTES);
2024
            }
2025
        }
2026
2027
        if (is_array($possible_options)) {
2028
            foreach ($possible_options as $question_id => &$possible_option) {
2029
                if (is_array($possible_option) && count($possible_option) > 0) {
2030
                    foreach ($possible_option as $option_id => &$value) {
2031
                        $my_answers_of_user = $answers_of_user[$question_id] ?? [];
2032
                        $key = array_keys($my_answers_of_user);
2033
                        if (isset($key[0]) && 'open' === substr($key[0], 0, 4)) {
2034
                            $return[] = api_html_entity_decode(
2035
                                strip_tags($answers_of_user[$question_id][$key[0]]['option_id']),
2036
                                ENT_QUOTES
2037
                            );
2038
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
2039
                            if (0 != $answers_of_user[$question_id][$option_id]['value']) {
2040
                                $return[] = $answers_of_user[$question_id][$option_id]['value'];
2041
                            } else {
2042
                                $return[] = 'v';
2043
                            }
2044
                        } else {
2045
                            $return[] = '';
2046
                        }
2047
                    }
2048
                }
2049
            }
2050
        }
2051
2052
        return $return;
2053
    }
2054
2055
    /**
2056
     * This function displays the comparative report which
2057
     * allows you to compare two questions
2058
     * A comparative report creates a table where one question
2059
     * is on the x axis and a second question is on the y axis.
2060
     * In the intersection is the number of people who have
2061
     * answered positive on both options.
2062
     *
2063
     * @return string HTML code
2064
     *
2065
     * @author Patrick Cool <[email protected]>, Ghent University
2066
     *
2067
     * @version February 2007
2068
     */
2069
    public static function display_comparative_report()
2070
    {
2071
        // Allowed question types for comparative report
2072
        $allowed_question_types = [
2073
            'yesno',
2074
            'multiplechoice',
2075
            'multipleresponse',
2076
            'dropdown',
2077
            'percentage',
2078
            'score',
2079
        ];
2080
2081
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
2082
2083
        // Getting all the questions
2084
        $questions = SurveyManager::get_questions($surveyId);
2085
2086
        // Actions bar
2087
        $actions = '<a href="'.api_get_path(
2088
                WEB_CODE_PATH
2089
            ).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq()
2090
            .'">'
2091
            .Display::getMdiIcon(ActionIcon::BACK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Back to').' '.get_lang('Reporting overview'))
2092
            .'</a>';
2093
        echo Display::toolbarAction('survey', [$actions]);
2094
2095
        // Displaying an information message that only the questions with predefined answers can be used in a comparative report
2096
        echo Display::return_message(get_lang('Only questions with predefined answers can be used'), 'normal', false);
2097
2098
        $xAxis = isset($_GET['xaxis']) ? Security::remove_XSS($_GET['xaxis']) : '';
2099
        $yAxis = isset($_GET['yaxis']) ? Security::remove_XSS($_GET['yaxis']) : '';
2100
2101
        $url = api_get_path(WEB_CODE_PATH).'survey/reporting.php?'.api_get_cidreq().'&action='.Security::remove_XSS($_GET['action'])
2102
            .'&survey_id='.$surveyId.'&xaxis='.$xAxis.'&y='.$yAxis;
2103
2104
        $form = new FormValidator('compare', 'get', $url);
2105
        $form->addHidden('action', Security::remove_XSS($_GET['action']));
2106
        $form->addHidden('survey_id', $surveyId);
2107
        $form->addHidden('cid', api_get_course_int_id());
2108
        $form->addHidden('sid', api_get_session_id());
2109
        $optionsX = ['----'];
2110
        $optionsY = ['----'];
2111
        $defaults = [];
2112
        foreach ($questions as $key => &$question) {
2113
            // Ignored tagged questions
2114
            if ($question) {
2115
                if (false !== strpos($question['question'], '{{')) {
2116
                    $question = null;
2117
                    continue;
2118
                }
2119
            }
2120
            if (is_array($allowed_question_types)) {
2121
                if (in_array($question['type'], $allowed_question_types)) {
2122
                    if (isset($_GET['xaxis']) && $_GET['xaxis'] == $question['question_id']) {
2123
                        $defaults['xaxis'] = $question['question_id'];
2124
                    }
2125
2126
                    if (isset($_GET['yaxis']) && $_GET['yaxis'] == $question['question_id']) {
2127
                        $defaults['yaxis'] = $question['question_id'];
2128
                    }
2129
2130
                    $optionsX[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
2131
                    $optionsY[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
2132
                }
2133
            }
2134
        }
2135
2136
        $form->addSelect('xaxis', get_lang('Select the question on the X axis'), $optionsX);
2137
        $form->addSelect('yaxis', get_lang('Select the question on the Y axis'), $optionsY);
2138
2139
        $form->addButtonSearch(get_lang('Compare questions'));
2140
        $form->setDefaults($defaults);
2141
        $form->display();
2142
2143
        // Getting all the information of the x axis
2144
        if (is_numeric($xAxis)) {
2145
            $question_x = SurveyManager::get_question($xAxis);
2146
        }
2147
2148
        // Getting all the information of the y axis
2149
        if (is_numeric($yAxis)) {
2150
            $question_y = SurveyManager::get_question($yAxis);
2151
        }
2152
2153
        if (is_numeric($xAxis) && is_numeric($yAxis) && $question_x && $question_y) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_x does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $question_y does not seem to be defined for all execution paths leading up to this point.
Loading history...
2154
            // Getting the answers of the two questions
2155
            $answers_x = self::get_answers_of_question_by_user($surveyId, $xAxis);
2156
            $answers_y = self::get_answers_of_question_by_user($surveyId, $yAxis);
2157
2158
            // Displaying the table
2159
            $tableHtml = '<table border="1" class="table table-hover table-striped data_table">';
2160
            $xOptions = [];
2161
            // The header
2162
            $tableHtml .= '<tr>';
2163
            for ($ii = 0; $ii <= count($question_x['answers']); $ii++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2164
                if (0 == $ii) {
2165
                    $tableHtml .= '<th>&nbsp;</th>';
2166
                } else {
2167
                    if ('score' == $question_x['type']) {
2168
                        for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2169
                            $tableHtml .= '<th>'.$question_x['answers'][($ii - 1)].'<br />'.$x.'</th>';
2170
                        }
2171
                        $x = '';
2172
                    } else {
2173
                        $tableHtml .= '<th>'.$question_x['answers'][($ii - 1)].'</th>';
2174
                    }
2175
                    $optionText = strip_tags($question_x['answers'][$ii - 1]);
2176
                    $optionText = html_entity_decode($optionText);
2177
                    array_push($xOptions, trim($optionText));
2178
                }
2179
            }
2180
            $tableHtml .= '</tr>';
2181
            $chartData = [];
2182
            // The main part
2183
            for ($ij = 0; $ij < count($question_y['answers']); $ij++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2184
                $currentYQuestion = strip_tags($question_y['answers'][$ij]);
2185
                $currentYQuestion = html_entity_decode($currentYQuestion);
2186
                // The Y axis is a scoring question type so we have more rows than the options (actually options * maximum score)
2187
                if ('score' == $question_y['type']) {
2188
                    for ($y = 1; $y <= $question_y['maximum_score']; $y++) {
2189
                        $tableHtml .= '<tr>';
2190
                        for ($ii = 0; $ii <= count($question_x['answers']); $ii++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2191
                            if ('score' == $question_x['type']) {
2192
                                for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2193
                                    if (0 == $ii) {
2194
                                        $tableHtml .= '<th>'.$question_y['answers'][($ij)].' '.$y.'</th>';
2195
                                        break;
2196
                                    } else {
2197
                                        $tableHtml .= '<td align="center">';
2198
                                        $votes = self::comparative_check(
2199
                                            $answers_x,
2200
                                            $answers_y,
2201
                                            $question_x['answersid'][($ii - 1)],
2202
                                            $question_y['answersid'][($ij)],
2203
                                            $x,
2204
                                            $y
2205
                                        );
2206
                                        $tableHtml .= $votes;
2207
                                        array_push(
2208
                                            $chartData,
2209
                                            [
2210
                                                'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2211
                                                'option' => $x,
2212
                                                'votes' => $votes,
2213
                                            ]
2214
                                        );
2215
                                        $tableHtml .= '</td>';
2216
                                    }
2217
                                }
2218
                            } else {
2219
                                if (0 == $ii) {
2220
                                    $tableHtml .= '<th>'.$question_y['answers'][$ij].' '.$y.'</th>';
2221
                                } else {
2222
                                    $tableHtml .= '<td align="center">';
2223
                                    $votes = self::comparative_check(
2224
                                        $answers_x,
2225
                                        $answers_y,
2226
                                        $question_x['answersid'][($ii - 1)],
2227
                                        $question_y['answersid'][($ij)],
2228
                                        0,
2229
                                        $y
2230
                                    );
2231
                                    $tableHtml .= $votes;
2232
                                    array_push(
2233
                                        $chartData,
2234
                                        [
2235
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2236
                                            'option' => $y,
2237
                                            'votes' => $votes,
2238
                                        ]
2239
                                    );
2240
                                    $tableHtml .= '</td>';
2241
                                }
2242
                            }
2243
                        }
2244
                        $tableHtml .= '</tr>';
2245
                    }
2246
                } else {
2247
                    // The Y axis is NOT a score question type so the number of rows = the number of options
2248
                    $tableHtml .= '<tr>';
2249
                    for ($ii = 0; $ii <= count($question_x['answers']); $ii++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2250
                        if ('score' == $question_x['type']) {
2251
                            for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2252
                                if (0 == $ii) {
2253
                                    $tableHtml .= '<th>'.$question_y['answers'][$ij].'</th>';
2254
                                    break;
2255
                                } else {
2256
                                    $tableHtml .= '<td align="center">';
2257
                                    $votes = self::comparative_check(
2258
                                        $answers_x,
2259
                                        $answers_y,
2260
                                        $question_x['answersid'][($ii - 1)],
2261
                                        $question_y['answersid'][($ij)],
2262
                                        $x,
2263
                                        0
2264
                                    );
2265
                                    $tableHtml .= $votes;
2266
                                    array_push(
2267
                                        $chartData,
2268
                                        [
2269
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2270
                                            'option' => $x,
2271
                                            'votes' => $votes,
2272
                                        ]
2273
                                    );
2274
                                    $tableHtml .= '</td>';
2275
                                }
2276
                            }
2277
                        } else {
2278
                            if (0 == $ii) {
2279
                                $tableHtml .= '<th>'.$question_y['answers'][($ij)].'</th>';
2280
                            } else {
2281
                                $tableHtml .= '<td align="center">';
2282
                                $votes = self::comparative_check(
2283
                                    $answers_x,
2284
                                    $answers_y,
2285
                                    $question_x['answersid'][($ii - 1)],
2286
                                    $question_y['answersid'][($ij)]
2287
                                );
2288
                                $tableHtml .= $votes;
2289
                                array_push(
2290
                                    $chartData,
2291
                                    [
2292
                                        'serie' => $xOptions[$ii - 1],
2293
                                        'option' => $currentYQuestion,
2294
                                        'votes' => $votes,
2295
                                    ]
2296
                                );
2297
                                $tableHtml .= '</td>';
2298
                            }
2299
                        }
2300
                    }
2301
                    $tableHtml .= '</tr>';
2302
                }
2303
            }
2304
            $tableHtml .= '</table>';
2305
            echo '<div id="chartContainer" class="col-md-12">';
2306
            echo self::drawChart($chartData, true);
2307
            echo '</div>';
2308
            echo $tableHtml;
2309
        }
2310
    }
2311
2312
    /**
2313
     * Get all the answers of a question grouped by user.
2314
     *
2315
     * @param int $survey_id   Survey ID
2316
     * @param int $question_id Question ID
2317
     *
2318
     * @return array Array containing all answers of all users, grouped by user
2319
     *
2320
     * @author Patrick Cool <[email protected]>, Ghent University
2321
     *
2322
     * @version February 2007 - Updated March 2008
2323
     */
2324
    public static function get_answers_of_question_by_user($survey_id, $question_id, $lpItemId = 0)
2325
    {
2326
        $course_id = api_get_course_int_id();
2327
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
2328
2329
        $sessionCondition = '';
2330
        if (true === api_get_configuration_value('show_surveys_base_in_sessions')) {
2331
            $sessionId = api_get_session_id();
2332
            $sessionCondition = api_get_session_condition($sessionId);
2333
        }
2334
        $lpItemCondition = '';
2335
        if (!empty($lpItemId)) {
2336
            $lpItemCondition = " AND c_lp_item_id = $lpItemId";
2337
        }
2338
2339
        $sql = "SELECT * FROM $table_survey_answer
2340
                WHERE
2341
                  survey_id='".intval($survey_id)."' AND
2342
                  question_id='".intval($question_id)."'
2343
                  $sessionCondition
2344
                  $lpItemCondition
2345
                ORDER BY USER ASC";
2346
        $result = Database::query($sql);
2347
        $return = [];
2348
        while ($row = Database::fetch_array($result)) {
2349
            if (0 == $row['value']) {
2350
                $return[$row['user']][] = $row['option_id'];
2351
            } else {
2352
                $return[$row['user']][] = $row['option_id'].'*'.$row['value'];
2353
            }
2354
        }
2355
2356
        return $return;
2357
    }
2358
2359
    /**
2360
     * Count the number of users who answer positively on both options.
2361
     *
2362
     * @param array All answers of the x axis
2363
     * @param array All answers of the y axis
2364
     * @param int x axis value (= the option_id of the first question)
2365
     * @param int y axis value (= the option_id of the second question)
2366
     *
2367
     * @return int Number of users who have answered positively to both options
2368
     *
2369
     * @author Patrick Cool <[email protected]>, Ghent University
2370
     *
2371
     * @version February 2007
2372
     */
2373
    public static function comparative_check(
2374
        $answers_x,
2375
        $answers_y,
2376
        $option_x,
2377
        $option_y,
2378
        $value_x = 0,
2379
        $value_y = 0
2380
    ) {
2381
        if (0 == $value_x) {
2382
            $check_x = $option_x;
2383
        } else {
2384
            $check_x = $option_x.'*'.$value_x;
2385
        }
2386
        if (0 == $value_y) {
2387
            $check_y = $option_y;
2388
        } else {
2389
            $check_y = $option_y.'*'.$value_y;
2390
        }
2391
2392
        $counter = 0;
2393
        if (is_array($answers_x)) {
2394
            foreach ($answers_x as $user => &$answers) {
2395
                // Check if the user has given $option_x as answer
2396
                if (in_array($check_x, $answers)) {
2397
                    // Check if the user has given $option_y as an answer
2398
                    if (!is_null($answers_y[$user]) &&
2399
                        in_array($check_y, $answers_y[$user])
2400
                    ) {
2401
                        $counter++;
2402
                    }
2403
                }
2404
            }
2405
        }
2406
2407
        return $counter;
2408
    }
2409
2410
    public static function saveInviteMail(CSurvey $survey, $content, $subject, $remind)
2411
    {
2412
        // Database table definition
2413
        if ($remind) {
2414
            $survey->setReminderMail($content);
2415
        } else {
2416
            $survey->setInviteMail($content);
2417
        }
2418
2419
        $survey->setMailSubject($subject);
2420
        $em = Database::getManager();
2421
        $em->persist($survey);
2422
        $em->flush();
2423
    }
2424
2425
    /**
2426
     * This function saves all the invitations of course users
2427
     * and additional users in the database
2428
     * and sends the invitations by email.
2429
     *
2430
     * @param int    $surveyId
2431
     * @param array  $users_array       Users array can be both a list of course uids AND a list of additional email
2432
     *                                  addresses
2433
     * @param string $invitation_title  title of the mail
2434
     * @param string $invitation_text   text of the mail has to contain a **link** string or
2435
     *                                  this will automatically be added to the end
2436
     * @param int    $reminder
2437
     * @param bool   $sendmail
2438
     * @param int    $remindUnAnswered
2439
     * @param bool   $isAdditionalEmail
2440
     * @param bool   $hideLink
2441
     *
2442
     * @author Patrick Cool <[email protected]>, Ghent University
2443
     * @author Julio Montoya - Adding auto-generated link support
2444
     *
2445
     * @version January 2007
2446
     */
2447
    public static function saveInvitations(
2448
        CSurvey $survey,
2449
        $users_array,
2450
        $invitation_title,
2451
        $invitation_text,
2452
        $reminder = 0,
2453
        $sendmail = false,
2454
        $remindUnAnswered = 0,
2455
        $isAdditionalEmail = false,
2456
        $hideLink = false
2457
    ) {
2458
        $surveyId = $survey->getIid();
2459
2460
        if (!is_array($users_array)) {
2461
            return 0;
2462
        }
2463
        $course = api_get_course_entity();
2464
        $session = api_get_session_entity();
2465
        $survey_invitations = self::get_invitations($surveyId);
2466
        $already_invited = self::get_invited_users($survey);
2467
2468
        // Remind unanswered is a special version of remind all reminder
2469
        $exclude_users = [];
2470
        if (1 == $remindUnAnswered) {
2471
            // Remind only unanswered users
2472
            $reminder = 1;
2473
            $exclude_users = SurveyManager::get_people_who_filled_survey($surveyId);
2474
        }
2475
2476
        $counter = 0; // Nr of invitations "sent" (if sendmail option)
2477
        $course_id = api_get_course_int_id();
2478
        $session_id = api_get_session_id();
2479
2480
        if (false == $isAdditionalEmail) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
2481
            $result = AbstractResource::separateUsersGroups($users_array);
2482
            $groupList = $result['groups'];
2483
            $users_array = $result['users'];
2484
2485
            foreach ($groupList as $groupId) {
2486
                $group = api_get_group_entity($groupId);
2487
                $userGroupList = GroupManager::getStudents($groupId, true);
2488
                $userGroupIdList = array_column($userGroupList, 'user_id');
2489
                $users_array = array_merge($users_array, $userGroupIdList);
2490
2491
                /*$params = [
2492
                    'c_id' => $course_id,
2493
                    'session_id' => $session_id,
2494
                    'group_id' => $groupId,
2495
                    'survey_code' => $survey_data['code'],
2496
                ];*/
2497
2498
                $invitationExists = self::invitationExists(
2499
                    $course_id,
2500
                    $session_id,
2501
                    $groupId,
2502
                    $survey->getIid()
2503
                );
2504
                if (empty($invitationExists)) {
2505
                    self::saveInvitation(
2506
                        '',
2507
                        '',
2508
                        api_get_utc_datetime(time(), false, true),
2509
                        $survey,
2510
                        $course,
2511
                        $session,
2512
                        $group
2513
                    );
2514
                }
2515
            }
2516
        }
2517
2518
        $users_array = array_unique($users_array);
2519
        foreach ($users_array as $value) {
2520
            if (empty($value)) {
2521
                continue;
2522
            }
2523
2524
            // Skip user if reminding only unanswered people
2525
            if (in_array($value, $exclude_users)) {
2526
                continue;
2527
            }
2528
2529
            // Get the unique invitation code if we already have it
2530
            if (1 == $reminder && array_key_exists($value, $survey_invitations)) {
2531
                $invitation_code = $survey_invitations[$value]['invitation_code'];
2532
            } else {
2533
                $invitation_code = md5($value.microtime());
2534
            }
2535
            $new_user = false; // User not already invited
2536
            // Store the invitation if user_id not in $already_invited['course_users'] OR
2537
            // email is not in $already_invited['additional_users']
2538
            $addit_users_array = isset($already_invited['additional_users']) && !empty($already_invited['additional_users'])
2539
                    ? explode(';', $already_invited['additional_users'])
2540
                    : [];
2541
            $my_alredy_invited = $already_invited['course_users'] ?? [];
2542
2543
            $userId = 0;
2544
            if (is_string($value) && filter_var($value, FILTER_VALIDATE_EMAIL)) {
2545
                $userInfo = api_get_user_info_from_email($value);
2546
                if ($userInfo && isset($userInfo['id'])) {
2547
                    $userId = $userInfo['id'];
2548
                }
2549
            } elseif (is_numeric($value)) {
2550
                $userId = $value;
2551
            }
2552
2553
            if ($userId && !in_array($userId, $my_alredy_invited)) {
2554
                $new_user = true;
2555
                if (!array_key_exists($userId, $survey_invitations)) {
2556
                    self::saveInvitation(
2557
                        api_get_user_entity($userId),
2558
                        $invitation_code,
2559
                        api_get_utc_datetime(time(), null, true),
2560
                        $survey,
2561
                        $course,
2562
                        $session
2563
                    );
2564
                }
2565
            }
2566
2567
            // Send the email if checkboxed
2568
            if (($new_user || 1 == $reminder) && $sendmail) {
2569
                // Make a change for absolute url
2570
                if (isset($invitation_text)) {
2571
                    $invitation_text = api_html_entity_decode($invitation_text, ENT_QUOTES);
2572
                    $invitation_text = str_replace('src="../../', 'src="'.api_get_path(WEB_PATH), $invitation_text);
2573
                    $invitation_text = trim(stripslashes($invitation_text));
2574
                }
2575
                self::sendInvitationMail(
2576
                    $survey,
2577
                    $value,
2578
                    $course,
2579
                    $invitation_code,
2580
                    $invitation_title,
2581
                    $invitation_text,
2582
                    $hideLink
2583
                );
2584
                $counter++;
2585
            }
2586
        }
2587
2588
        return $counter; // Number of invitations sent
2589
    }
2590
2591
    public static function saveInvitation(
2592
        User $user,
2593
        $invitationCode,
2594
        $reminderDate,
2595
        CSurvey $survey,
2596
        Course $course,
2597
        SessionEntity $session = null,
2598
        CGroup $group = null
2599
    ): ?CSurveyInvitation {
2600
        $invitation = new CSurveyInvitation();
2601
        $invitation
2602
            ->setUser($user)
2603
            ->setInvitationCode($invitationCode)
2604
            ->setReminderDate($reminderDate)
2605
            ->setSurvey($survey)
2606
            ->setCourse($course)
2607
            ->setSession($session)
2608
            ->setGroup($group)
2609
        ;
2610
2611
        $em = Database::getManager();
2612
        $em->persist($invitation);
2613
        $em->flush();
2614
2615
        return $invitation;
2616
    }
2617
2618
    /**
2619
     * @param int $courseId
2620
     * @param int $sessionId
2621
     * @param int $groupId
2622
     * @param int $surveyId
2623
     *
2624
     * @return int
2625
     */
2626
    public static function invitationExists($courseId, $sessionId, $groupId, $surveyId)
2627
    {
2628
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2629
        $courseId = (int) $courseId;
2630
        $sessionId = (int) $sessionId;
2631
        $groupId = (int) $groupId;
2632
        $surveyId = (int) $surveyId;
2633
2634
        $sql = "SELECT iid FROM $table
2635
                WHERE
2636
                    c_id = $courseId AND
2637
                    session_id = $sessionId AND
2638
                    group_id = $groupId AND
2639
                    survey_id = $surveyId
2640
                ";
2641
        $result = Database::query($sql);
2642
2643
        return Database::num_rows($result);
2644
    }
2645
2646
    /**
2647
     * Send the invitation by mail.
2648
     *
2649
     * @param int invitedUser - the userId (course user) or emailaddress of additional user
2650
     * @param string $invitation_code - the unique invitation code for the URL
2651
     */
2652
    public static function sendInvitationMail(
2653
        CSurvey $survey,
2654
        $invitedUser,
2655
        Course $course,
2656
        $invitation_code,
2657
        $invitation_title,
2658
        $invitation_text,
2659
        $hideLink = false
2660
    ) {
2661
        $_user = api_get_user_info();
2662
        $sessionId = api_get_session_id();
2663
2664
        // Replacing the **link** part with a valid link for the user
2665
        $link = self::generateFillSurveyLink($survey, $invitation_code, $course, $sessionId);
2666
        if ($hideLink) {
2667
            $full_invitation_text = str_replace('**link**', '', $invitation_text);
2668
        } else {
2669
            $text_link = '<a href="'.$link.'">'.get_lang('Click here to answer the survey')."</a><br />\r\n<br />\r\n"
2670
                .get_lang('or copy paste the following url :')." <br /> \r\n <br /> \r\n ".$link;
2671
2672
            $replace_count = 0;
2673
            $full_invitation_text = api_str_ireplace('**link**', $text_link, $invitation_text, $replace_count);
2674
            if ($replace_count < 1) {
2675
                $full_invitation_text = $full_invitation_text."<br />\r\n<br />\r\n".$text_link;
0 ignored issues
show
Bug introduced by
Are you sure $full_invitation_text of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2675
                $full_invitation_text = /** @scrutinizer ignore-type */ $full_invitation_text."<br />\r\n<br />\r\n".$text_link;
Loading history...
2676
            }
2677
        }
2678
2679
        // Sending the mail
2680
        $sender_user_id = api_get_user_id();
2681
2682
        if ('noreply' === api_get_setting('survey_email_sender_noreply')) {
2683
            $sender_user_id = null;
2684
        }
2685
2686
        // Optionally: finding the e-mail of the course user
2687
        if (is_numeric($invitedUser)) {
2688
            MessageManager::send_message(
2689
                $invitedUser,
2690
                $invitation_title,
2691
                $full_invitation_text,
2692
                [],
2693
                [],
2694
                null,
2695
                null,
2696
                null,
2697
                null,
2698
                $sender_user_id,
2699
                true
2700
            );
2701
        } else {
2702
            @api_mail_html(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for api_mail_html(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

2702
            /** @scrutinizer ignore-unhandled */ @api_mail_html(

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2703
                '',
2704
                $invitedUser,
2705
                $invitation_title,
2706
                $full_invitation_text,
2707
            );
2708
        }
2709
    }
2710
2711
    /**
2712
     * This function recalculates the number of users who have been invited and updates the survey table with this
2713
     * value.
2714
     */
2715
    public static function updateInvitedCount(CSurvey $survey, $courseId = 0, $sessionId = 0)
2716
    {
2717
        $surveyId = $survey->getIid();
2718
        $courseId = (int) $courseId;
2719
        $sessionId = (int) $sessionId;
2720
2721
        $courseId = $courseId ?: api_get_course_int_id();
2722
        $sessionId = $sessionId ?: api_get_session_id();
2723
        $sessionCondition = api_get_session_condition($sessionId);
2724
2725
        // Database table definition
2726
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
2727
        $table_survey = Database::get_course_table(TABLE_SURVEY);
2728
2729
        // Counting the number of people that are invited
2730
        $sql = "SELECT count(user_id) as total
2731
                FROM $table_survey_invitation
2732
		        WHERE
2733
		            c_id = $courseId AND
2734
		            survey_id = '".$surveyId."' AND
2735
		            user_id <> ''
2736
		            $sessionCondition
2737
                ";
2738
        $result = Database::query($sql);
2739
        $row = Database::fetch_array($result);
2740
        $total_invited = $row['total'];
2741
2742
        // Updating the field in the survey table
2743
        $sql = "UPDATE $table_survey
2744
		        SET invited = '".Database::escape_string($total_invited)."'
2745
		        WHERE
2746
		            iid = '".$surveyId."'
2747
                ";
2748
        Database::query($sql);
2749
2750
        return $total_invited;
2751
    }
2752
2753
    /**
2754
     * This function gets all the invited users for a given survey code.
2755
     *
2756
     * @return array Array containing the course users and additional users (non course users)
2757
     */
2758
    public static function get_invited_users(CSurvey $survey, $course_code = '', $session_id = 0)
2759
    {
2760
        $session_id = (int) $session_id;
2761
        $surveyId = $survey->getIid();
2762
2763
        $course_code = Database::escape_string($course_code);
2764
        $course_id = api_get_course_int_id();
2765
2766
        if (!empty($course_code)) {
2767
            $course_info = api_get_course_info($course_code);
2768
            if ($course_info) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $course_info of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2769
                $course_id = $course_info['real_id'];
2770
            }
2771
        }
2772
2773
        if (empty($session_id)) {
2774
            $session_id = api_get_session_id();
2775
        }
2776
2777
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
2778
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2779
        $sessionCondition = api_get_session_condition($session_id);
2780
2781
        // Selecting all the invitations of this survey AND the additional emailaddresses (the left join)
2782
        $order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname' : ' ORDER BY lastname, firstname';
2783
        $sql = "SELECT user_id, group_id
2784
				FROM $table_survey_invitation as table_invitation
2785
				WHERE
2786
				    table_invitation.c_id = $course_id AND
2787
                    survey_id = ".$surveyId."
2788
                    $sessionCondition
2789
                ";
2790
2791
        $defaults = [];
2792
        $defaults['course_users'] = [];
2793
        $defaults['additional_users'] = ''; // Textarea
2794
        $defaults['users'] = []; // user and groups
2795
2796
        $result = Database::query($sql);
2797
        while ($row = Database::fetch_array($result)) {
2798
            if (is_numeric($row['user_id'])) {
2799
                $defaults['course_users'][] = $row['user_id'];
2800
                $defaults['users'][] = 'USER:'.$row['user_id'];
2801
            } else {
2802
                if (!empty($row['user_id'])) {
2803
                    $defaults['additional_users'][] = $row['user_id'];
2804
                }
2805
            }
2806
2807
            if (isset($row['group_id']) && !empty($row['group_id'])) {
2808
                $defaults['users'][] = 'GROUP:'.$row['group_id'];
2809
            }
2810
        }
2811
2812
        if (!empty($defaults['course_users'])) {
2813
            $user_ids = implode("','", $defaults['course_users']);
2814
            $sql = "SELECT id FROM $table_user WHERE id IN ('$user_ids') $order_clause";
2815
            $result = Database::query($sql);
2816
            $fixed_users = [];
2817
            while ($row = Database::fetch_array($result)) {
2818
                $fixed_users[] = $row['id'];
2819
            }
2820
            $defaults['course_users'] = $fixed_users;
2821
        }
2822
2823
        if (!empty($defaults['additional_users'])) {
2824
            $defaults['additional_users'] = implode(';', $defaults['additional_users']);
2825
        }
2826
2827
        return $defaults;
2828
    }
2829
2830
    /**
2831
     * Get all the invitations.
2832
     *
2833
     * @param int $surveyId
2834
     *
2835
     * @return array Database rows matching the survey code
2836
     *
2837
     * @author Patrick Cool <[email protected]>, Ghent University
2838
     *
2839
     * @version September 2007
2840
     */
2841
    public static function get_invitations($surveyId)
2842
    {
2843
        $course_id = api_get_course_int_id();
2844
        $sessionId = api_get_session_id();
2845
        // Database table definition
2846
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
2847
2848
        $sql = "SELECT * FROM $table_survey_invitation
2849
		        WHERE
2850
		            c_id = $course_id AND
2851
                    session_id = $sessionId AND
2852
		            survey_id = '".(int) $surveyId."'";
2853
        $result = Database::query($sql);
2854
        $return = [];
2855
        while ($row = Database::fetch_array($result)) {
2856
            $return[$row['user_id']] = $row;
2857
        }
2858
2859
        return $return;
2860
    }
2861
2862
    /**
2863
     * This function displays the form for searching a survey.
2864
     *
2865
     * @author Patrick Cool <[email protected]>, Ghent University
2866
     *
2867
     * @version January 2007
2868
     *
2869
     * @todo consider moving this to surveymanager.inc.lib.php
2870
     */
2871
    public static function display_survey_search_form()
2872
    {
2873
        $url = api_get_path(WEB_CODE_PATH).'survey/survey_list.php?search=advanced&'.api_get_cidreq();
2874
        $form = new FormValidator('search', 'get', $url);
2875
        $form->addHeader(get_lang('Search a survey'));
2876
        $form->addText('keyword_title', get_lang('Title'));
2877
        $form->addText('keyword_code', get_lang('Course code'));
2878
        $form->addSelectLanguage('keyword_language', get_lang('Language'));
2879
        $form->addHidden('cid', api_get_course_int_id());
2880
        $form->addButtonSearch(get_lang('Search'), 'do_search');
2881
        $form->display();
2882
    }
2883
2884
    /**
2885
     * Show table only visible by DRH users.
2886
     */
2887
    public static function displaySurveyListForDrh()
2888
    {
2889
        $parameters = [];
2890
        $parameters['cidReq'] = api_get_course_id();
2891
2892
        // Create a sortable table with survey-data
2893
        $table = new SortableTable(
2894
            'surveys',
2895
            'get_number_of_surveys',
2896
            'get_survey_data_drh',
2897
            2
2898
        );
2899
        $table->set_additional_parameters($parameters);
2900
        $table->set_header(0, '', false);
2901
        $table->set_header(1, get_lang('Survey name'));
2902
        $table->set_header(2, get_lang('Code'));
2903
        $table->set_header(3, get_lang('Questions'));
2904
        $table->set_header(4, get_lang('Author'));
2905
        $table->set_header(5, get_lang('Available from'));
2906
        $table->set_header(6, get_lang('Until'));
2907
        $table->set_header(7, get_lang('Invite'));
2908
        $table->set_header(8, get_lang('Anonymous'));
2909
2910
        if ('true' === api_get_setting('survey.allow_mandatory_survey')) {
2911
            $table->set_header(9, get_lang('Mandatory?'));
2912
            $table->set_header(10, get_lang('Edit'), false, 'width="150"');
2913
            $table->set_column_filter(9, 'anonymous_filter');
2914
            $table->set_column_filter(10, 'modify_filter_drh');
2915
        } else {
2916
            $table->set_header(9, get_lang('Edit'), false, 'width="150"');
2917
            $table->set_column_filter(9, 'modify_filter_drh');
2918
        }
2919
2920
        $table->set_column_filter(8, 'anonymous_filter');
2921
        $table->display();
2922
    }
2923
2924
    /**
2925
     * This function displays the sortable table with all the surveys.
2926
     *
2927
     * @author Patrick Cool <[email protected]>, Ghent University
2928
     *
2929
     * @version January 2007
2930
     */
2931
    public static function display_survey_list()
2932
    {
2933
        $parameters = [];
2934
        $parameters['cid'] = api_get_course_int_id();
2935
        $parameters['sid'] = api_get_session_id();
2936
        $parameters['gid'] = api_get_group_id();
2937
        if (isset($_GET['do_search']) && $_GET['do_search']) {
2938
            $message = get_lang('Display search results').'<br />';
2939
            $message .= '<a href="'.api_get_self().'?'.api_get_cidreq().'">'.get_lang('Display all').'</a>';
2940
            echo Display::return_message($message, 'normal', false);
2941
        }
2942
2943
        // Create a sortable table with survey-data
2944
        $table = new SortableTable(
2945
            'surveys',
2946
            'get_number_of_surveys',
2947
            'get_survey_data',
2948
            2
2949
        );
2950
        $table->set_additional_parameters($parameters);
2951
        $table->set_header(0, '', false);
2952
        $table->set_header(1, get_lang('Survey name'));
2953
        $table->set_header(2, get_lang('Code'));
2954
        $table->set_header(3, get_lang('Questions'));
2955
        $table->set_header(4, get_lang('Author'));
2956
        $table->set_header(5, get_lang('Available from'));
2957
        $table->set_header(6, get_lang('Until'));
2958
        $table->set_header(7, get_lang('Invite'));
2959
        $table->set_header(8, get_lang('Anonymous'));
2960
2961
        if ('true' === api_get_setting('survey.allow_mandatory_survey')) {
2962
            $table->set_header(9, get_lang('Mandatory?'));
2963
            $table->set_header(10, get_lang('Edit'), false, 'width="150"');
2964
            $table->set_column_filter(8, 'anonymous_filter');
2965
            $table->set_column_filter(10, 'modify_filter');
2966
        } else {
2967
            $table->set_header(9, get_lang('Edit'), false, 'width="150"');
2968
            $table->set_column_filter(9, 'modify_filter');
2969
        }
2970
2971
        $table->set_column_filter(8, 'anonymous_filter');
2972
        $actions = [
2973
            'export_all' => get_lang('Export results'),
2974
            'export_by_class' => get_lang('Export by class'),
2975
            'send_to_tutors' => get_lang('Publish for group tutors'),
2976
            'multiplicate' => get_lang('Multiply questions'),
2977
            'delete' => get_lang('Delete survey'),
2978
        ];
2979
        $table->set_form_actions($actions);
2980
        $table->display();
2981
    }
2982
2983
    /**
2984
     * Survey list for coach.
2985
     */
2986
    public static function display_survey_list_for_coach()
2987
    {
2988
        $parameters = [];
2989
        $parameters['cidReq'] = api_get_course_id();
2990
        if (isset($_GET['do_search'])) {
2991
            $message = get_lang('Display search results').'<br />';
2992
            $message .= '<a href="'.api_get_self().'?'.api_get_cidreq().'">'.get_lang('Display all').'</a>';
2993
            echo Display::return_message($message, 'normal', false);
2994
        }
2995
2996
        // Create a sortable table with survey-data
2997
        $table = new SortableTable(
2998
            'surveys_coach',
2999
            'get_number_of_surveys_for_coach',
3000
            'get_survey_data_for_coach',
3001
            2
3002
        );
3003
        $table->set_additional_parameters($parameters);
3004
        $table->set_header(0, '', false);
3005
        $table->set_header(1, get_lang('Survey name'));
3006
        $table->set_header(2, get_lang('Code'));
3007
        $table->set_header(3, get_lang('Questions'));
3008
        $table->set_header(4, get_lang('Author'));
3009
        $table->set_header(5, get_lang('Available from'));
3010
        $table->set_header(6, get_lang('Until'));
3011
        $table->set_header(7, get_lang('Invite'));
3012
        $table->set_header(8, get_lang('Anonymous'));
3013
3014
        if ('true' === api_get_setting('survey.allow_mandatory_survey')) {
3015
            $table->set_header(9, get_lang('Edit'), false, 'width="130"');
3016
            $table->set_header(10, get_lang('Edit'), false, 'width="130"');
3017
            $table->set_column_filter(8, 'anonymous_filter');
3018
            $table->set_column_filter(10, 'modify_filter_for_coach');
3019
        } else {
3020
            $table->set_header(9, get_lang('Edit'), false, 'width="130"');
3021
            $table->set_column_filter(9, 'modify_filter_for_coach');
3022
        }
3023
3024
        $table->set_column_filter(8, 'anonymous_filter');
3025
        $table->display();
3026
    }
3027
3028
    /**
3029
     * Check if the hide_survey_edition configurations setting is enabled.
3030
     *
3031
     * @param string $surveyCode
3032
     *
3033
     * @return bool
3034
     */
3035
    public static function checkHideEditionToolsByCode($surveyCode)
3036
    {
3037
        $hideSurveyEdition = api_get_setting('survey.hide_survey_edition', true);
3038
3039
        if (empty($hideSurveyEdition) || 'false' === $hideSurveyEdition) {
3040
            return false;
3041
        }
3042
3043
        if (is_array($hideSurveyEdition)) {
3044
            if ('*' === $hideSurveyEdition['codes']) {
3045
                return true;
3046
            }
3047
3048
            if (in_array($surveyCode, $hideSurveyEdition['codes'])) {
3049
                return true;
3050
            }
3051
        }
3052
3053
        return false;
3054
    }
3055
3056
    /**
3057
     * This function changes the modify column of the sortable table.
3058
     *
3059
     * @param int  $survey_id the id of the survey
3060
     * @param bool $drh
3061
     *
3062
     * @return string html code that are the actions that can be performed on any survey
3063
     *
3064
     * @author Patrick Cool <[email protected]>, Ghent University
3065
     *
3066
     * @version January 2007
3067
     */
3068
    public static function modify_filter($survey_id, $url_params, $row)
3069
    {
3070
        $repo = Container::getSurveyRepository();
3071
        /** @var CSurvey|null $survey */
3072
        $survey = $repo->find($survey_id);
3073
3074
        if (null === $survey) {
3075
            return '';
3076
        }
3077
3078
        $hideSurveyEdition = self::checkHideEditionToolsByCode($survey->getCode());
3079
3080
        if ($hideSurveyEdition) {
3081
            return '';
3082
        }
3083
3084
        $survey_id = $survey->getIid();
3085
        $actions = [];
3086
        $hideReportingButton = ('true' === api_get_setting('survey.hide_survey_reporting_button'));
3087
        $codePath = api_get_path(WEB_CODE_PATH);
3088
        $params = [];
3089
        parse_str(api_get_cidreq(), $params);
3090
3091
        $reportingLink = Display::url(
3092
            Display::getMdiIcon(ToolIcon::TRACKING, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Reporting')),
3093
            $codePath.'survey/reporting.php?'.http_build_query($params + ['survey_id' => $survey_id])
3094
        );
3095
3096
        if (!$row['can_edit']) {
3097
            return $hideReportingButton ? '-' : $reportingLink;
3098
        }
3099
3100
        $type = $survey->getSurveyType();
3101
3102
        // Coach can see that only if the survey is in his session
3103
        if (api_is_allowed_to_edit() || api_is_element_in_the_session(TOOL_SURVEY, $survey_id)) {
3104
            $configUrl = $codePath.'survey/create_new_survey.php?'.
3105
                http_build_query($params + ['action' => 'edit', 'survey_id' => $survey_id]);
3106
            $editUrl = $codePath.'survey/survey.php?'.
3107
                http_build_query($params + ['survey_id' => $survey_id]);
3108
            if (3 == $type) {
3109
                $configUrl = $codePath.'survey/edit_meeting.php?'.
3110
                    http_build_query($params + ['action' => 'edit', 'survey_id' => $survey_id]);
3111
            }
3112
3113
            $actions[] = Display::url(
3114
                Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Edit')),
3115
                $editUrl
3116
            );
3117
            $actions[] = Display::url(
3118
                Display::getMdiIcon(ToolIcon::SETTINGS, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Configure')),
3119
                $configUrl
3120
            );
3121
3122
            if (SurveyManager::survey_generation_hash_available()) {
3123
                $actions[] = Display::url(
3124
                    Display::getMdiIcon(ToolIcon::LINK, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Generate survey access link')),
3125
                    $codePath.'survey/generate_link.php?'.http_build_query($params + ['survey_id' => $survey_id])
3126
                );
3127
            }
3128
3129
            if (3 != $type) {
3130
                $actions[] = Display::url(
3131
                    Display::getMdiIcon(ActionIcon::COPY_CONTENT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Copy survey')),
3132
                    $codePath.'survey/copy_survey.php?'.http_build_query($params + ['survey_id' => $survey_id])
3133
                );
3134
3135
                $actions[] = Display::url(
3136
                    Display::getMdiIcon(ObjectIcon::MULTI_ELEMENT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Duplicate survey')),
3137
                    $codePath.'survey/survey_list.php?'
3138
                    .http_build_query($params + ['action' => 'copy_survey', 'survey_id' => $survey_id])
3139
                );
3140
3141
                $actions[] = Display::url(
3142
                    Display::getMdiIcon('view-grid-plus-outline', 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Multiply questions')),
3143
                    $codePath.'survey/survey_list.php?'
3144
                    .http_build_query($params + ['action' => 'multiplicate', 'survey_id' => $survey_id])
3145
                );
3146
3147
                $actions[] = Display::url(
3148
                    Display::getMdiIcon('view-grid-plus-outline', 'ch-tool-icon-disabled', null, ICON_SIZE_SMALL, get_lang('Remove multiplied questions')),
3149
                    $codePath.'survey/survey_list.php?'
3150
                    .http_build_query($params + ['action' => 'remove_multiplicate', 'survey_id' => $survey_id])
3151
                );
3152
3153
                $warning = addslashes(api_htmlentities(get_lang('Empty survey').'?', ENT_QUOTES));
3154
                $actions[] = Display::url(
3155
                    Display::getMdiIcon(ActionIcon::RESET, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Empty survey')),
3156
                    $codePath.'survey/survey_list.php?'
3157
                    .http_build_query($params + ['action' => 'empty', 'survey_id' => $survey_id]),
3158
                    [
3159
                        'onclick' => "javascript: if (!confirm('".$warning."')) return false;",
3160
                    ]
3161
                );
3162
            }
3163
        }
3164
3165
        if (3 != $type) {
3166
            $actions[] = Display::url(
3167
                Display::getMdiIcon(ActionIcon::PREVIEW_CONTENT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Preview')),
3168
                $codePath.'survey/preview.php?'.http_build_query($params + ['survey_id' => $survey_id])
3169
            );
3170
        }
3171
3172
        $actions[] = Display::url(
3173
            Display::getMdiIcon(StateIcon::MAIL_NOTIFICATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Publish')),
3174
            $codePath.'survey/survey_invite.php?'.http_build_query($params + ['survey_id' => $survey_id])
3175
        );
3176
3177
        $extraFieldValue = new ExtraFieldValue('survey');
3178
        $groupData = $extraFieldValue->get_values_by_handler_and_field_variable($survey_id, 'group_id');
3179
        if ($groupData && !empty($groupData['value'])) {
3180
            $actions[] = Display::url(
3181
                Display::getMdiIcon(ObjectIcon::TEACHER, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Publish for group tutors')),
3182
                $codePath.'survey/survey_list.php?action=send_to_tutors&'.http_build_query($params + ['survey_id' => $survey_id])
3183
            );
3184
        }
3185
3186
        if (3 != $type) {
3187
            $actions[] = $hideReportingButton ? null : $reportingLink;
3188
        }
3189
3190
        if (api_is_allowed_to_edit() ||
3191
            api_is_element_in_the_session(TOOL_SURVEY, $survey_id)
3192
        ) {
3193
            $actions[] = self::getAdditionalTeacherActions($survey_id);
3194
3195
            $warning = addslashes(api_htmlentities(get_lang('Delete survey').'?', ENT_QUOTES));
3196
            $actions[] = Display::url(
3197
                Display::getMdiIcon(ActionIcon::DELETE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Delete')),
3198
                $codePath.'survey/survey_list.php?'
3199
                .http_build_query($params + ['action' => 'delete', 'survey_id' => $survey_id]),
3200
                [
3201
                    'onclick' => "javascript: if (!confirm('".$warning."')) return false;",
3202
                ]
3203
            );
3204
        }
3205
3206
        return implode(PHP_EOL, $actions);
3207
    }
3208
3209
    /**
3210
     * Get the additional actions added in survey_additional_teacher_modify_actions configuration.
3211
     *
3212
     * @param int $surveyId
3213
     * @param int $iconSize
3214
     *
3215
     * @return string
3216
     */
3217
    public static function getAdditionalTeacherActions($surveyId, $iconSize = ICON_SIZE_SMALL)
3218
    {
3219
        $additionalActions = api_get_setting('survey.survey_additional_teacher_modify_actions', true) ?: [];
3220
3221
        if (empty($additionalActions) || ('false' === $additionalActions)) {
3222
            return '';
3223
        }
3224
3225
        $action = '';
3226
        if (is_array($additionalActions)) {
3227
            $actions = [];
3228
            foreach ($additionalActions as $additionalAction) {
3229
                $actions[] = call_user_func(
3230
                    $additionalAction,
3231
                    ['survey_id' => $surveyId, 'icon_size' => $iconSize]
3232
                );
3233
            }
3234
            $action = implode(PHP_EOL, $actions);
3235
        }
3236
3237
3238
        return $action;
3239
    }
3240
3241
    /**
3242
     * @param int $survey_id
3243
     *
3244
     * @return string
3245
     */
3246
    public static function modify_filter_for_coach($survey_id)
3247
    {
3248
        $survey_id = (int) $survey_id;
3249
        $actions = [];
3250
        $codePath = api_get_path(WEB_CODE_PATH);
3251
        $params = [];
3252
        parse_str(api_get_cidreq(), $params);
3253
        $actions[] = Display::url(
3254
            Display::getMdiIcon(ActionIcon::PREVIEW_CONTENT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Preview')),
3255
            $codePath.'survey/preview.php?'.http_build_query($params + ['survey_id' => $survey_id])
3256
        );
3257
        $actions[] = Display::url(
3258
            Display::getMdiIcon(StateIcon::MAIL_NOTIFICATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Publish')),
3259
            $codePath.'survey/survey_invite.php?'.http_build_query($params + ['survey_id' => $survey_id])
3260
        );
3261
        $warning = addslashes(api_htmlentities(get_lang('Empty survey').'?', ENT_QUOTES));
3262
        $actions[] = Display::url(
3263
            Display::getMdiIcon(ActionIcon::RESET, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Empty survey')),
3264
            $codePath.'survey/survey_list.php?'
3265
                .http_build_query($params + ['action' => 'empty', 'survey_id' => $survey_id]),
3266
            [
3267
                'onclick' => "javascript: if(!confirm('".$warning."')) return false;",
3268
            ]
3269
        );
3270
3271
        return implode(PHP_EOL, $actions);
3272
    }
3273
3274
    /**
3275
     * Returns "yes" when given parameter is one, "no" for any other value.
3276
     *
3277
     * @param int Whether anonymous or not
3278
     *
3279
     * @return string "Yes" or "No" in the current language
3280
     */
3281
    public static function anonymous_filter($anonymous)
3282
    {
3283
        if (1 == $anonymous) {
3284
            return get_lang('Yes');
3285
        }
3286
3287
        return get_lang('No');
3288
    }
3289
3290
    public static function survey_search_restriction()
3291
    {
3292
        if (isset($_GET['do_search'])) {
3293
            if ('' != $_GET['keyword_title']) {
3294
                $search_term[] = 'title like "%" \''.Database::escape_string($_GET['keyword_title']).'\' "%"';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$search_term was never initialized. Although not strictly required by PHP, it is generally a good practice to add $search_term = array(); before regardless.
Loading history...
3295
            }
3296
            if ('' != $_GET['keyword_code']) {
3297
                $search_term[] = 'code =\''.Database::escape_string($_GET['keyword_code']).'\'';
3298
            }
3299
            if ('%' != $_GET['keyword_language']) {
3300
                $search_term[] = 'lang =\''.Database::escape_string($_GET['keyword_language']).'\'';
3301
            }
3302
            $my_search_term = (null == $search_term) ? [] : $search_term;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $search_term does not seem to be defined for all execution paths leading up to this point.
Loading history...
3303
            $search_restriction = implode(' AND ', $my_search_term);
3304
3305
            return $search_restriction;
3306
        } else {
3307
            return false;
3308
        }
3309
    }
3310
3311
    public static function get_number_of_surveys()
3312
    {
3313
        $repo = Container::getSurveyRepository();
3314
        $course = api_get_course_entity();
3315
        $session = api_get_session_entity();
3316
        $qb = $repo->findAllByCourse($course, $session);
3317
3318
        return $repo->getCount($qb);
3319
3320
        /*$table_survey = Database::get_course_table(TABLE_SURVEY);
3321
        $course_id = api_get_course_int_id();
3322
3323
        $search_restriction = self::survey_search_restriction();
3324
        if ($search_restriction) {
3325
            $search_restriction = 'WHERE c_id = '.$course_id.' AND '.$search_restriction;
3326
        } else {
3327
            $search_restriction = "WHERE c_id = $course_id";
3328
        }
3329
        $sql = "SELECT count(iid) AS total_number_of_items
3330
                FROM $table_survey $search_restriction";
3331
        $res = Database::query($sql);
3332
        $obj = Database::fetch_object($res);
3333
3334
        return $obj->total_number_of_items;*/
3335
    }
3336
3337
    /**
3338
     * @return int
3339
     */
3340
    public static function get_number_of_surveys_for_coach()
3341
    {
3342
        $repo = Container::getSurveyRepository();
3343
        $course = api_get_course_entity();
3344
        $session = api_get_session_entity();
3345
        $qb = $repo->findAllByCourse($course, $session);
3346
3347
        return $repo->getCount($qb);
3348
3349
        /*$survey_tree = new SurveyTree();
3350
        return count($survey_tree->surveylist);*/
3351
    }
3352
3353
    /**
3354
     * This function gets all the survey data that is to be displayed in the sortable table.
3355
     *
3356
     * @param int    $from
3357
     * @param int    $number_of_items
3358
     * @param int    $column
3359
     * @param string $direction
3360
     * @param bool   $isDrh
3361
     *
3362
     * @return array
3363
     *
3364
     * @author Patrick Cool <[email protected]>, Ghent University
3365
     * @author Julio Montoya <[email protected]>, Beeznest - Adding intvals
3366
     *
3367
     * @version January 2007
3368
     */
3369
    public static function get_survey_data(
3370
        int    $from,
3371
        int    $number_of_items,
3372
        int    $column,
3373
        string $direction,
3374
        bool $isDrh = false
3375
    ): array {
3376
        $repo = Container::getSurveyRepository();
3377
        $course = api_get_course_entity();
3378
        $sessionId = api_get_session_id();
3379
        $session = api_get_session_entity();
3380
3381
        $qb = $repo->findAllByCourse($course, $session);
3382
        /** @var CSurvey[] $surveys */
3383
        $surveys = $qb->getQuery()->getResult();
3384
3385
        $mandatoryAllowed = ('true' === api_get_setting('survey.allow_mandatory_survey'));
3386
3387
        $from = (int) $from;
3388
        $number_of_items = (int) $number_of_items;
3389
        $column = (int) $column;
3390
        if (!in_array(strtolower($direction), ['asc', 'desc'])) {
3391
            $direction = 'asc';
3392
        }
3393
3394
        $efv = new ExtraFieldValue('survey');
3395
        $list = [];
3396
3397
        if ($sessionId > 0) {
3398
            foreach ($surveys as $survey) {
3399
                $surveySession = $survey->getFirstResourceLink()->getSession();
3400
                if ($surveySession && $surveySession->getId() == $sessionId) {
3401
                    $list[] = self::prepare_survey_array($survey, $efv, $mandatoryAllowed, $isDrh);
3402
                }
3403
            }
3404
3405
            $lpRepo = Container::getLpRepository();
3406
            $lpsInSessionQb = $lpRepo->findAllByCourse($course, $session);
3407
            $lpsInSession = $lpsInSessionQb->getQuery()->getResult();
3408
3409
            foreach ($lpsInSession as $lpInSession) {
3410
                $lpInSessionSession = $lpInSession->getFirstResourceLink()->getSession();
3411
3412
                if ($lpInSessionSession && $lpInSessionSession->getId() == $sessionId) {
3413
                    foreach ($lpInSession->getItems() as $sessionItem) {
3414
                        if ($sessionItem->getItemType() === 'survey') {
3415
                            $itemId = (int) $sessionItem->getPath();
3416
                            $survey = $repo->find($itemId);
3417
                            if ($survey && $survey->getFirstResourceLink()->getSession() == null) {
3418
                                $list[] = self::prepare_survey_array($survey, $efv, $mandatoryAllowed, $isDrh, false);
3419
                            }
3420
                        }
3421
                    }
3422
                }
3423
            }
3424
        } else {
3425
            foreach ($surveys as $survey) {
3426
                $list[] = self::prepare_survey_array($survey, $efv, $mandatoryAllowed, $isDrh);
3427
            }
3428
        }
3429
3430
        return $list;
3431
    }
3432
3433
3434
    private static function prepare_survey_array($survey, $efv, $mandatoryAllowed, $isDrh, $canEdit = true) {
3435
        $array = [];
3436
        $surveyId = $survey->getIid();
3437
        $array[0] = $surveyId;
3438
        $type = $survey->getSurveyType();
3439
3440
        $title = $survey->getTitle();
3441
        if (self::checkHideEditionToolsByCode($survey->getCode())) {
3442
            $array[1] = $title;
3443
        } else {
3444
            // Doodle
3445
            if (3 == $type) {
3446
                $array[1] = Display::url(
3447
                    $title,
3448
                    api_get_path(WEB_CODE_PATH).'survey/meeting.php?survey_id='.$surveyId.'&'.api_get_cidreq()
3449
                );
3450
            } else {
3451
                $array[1] = Display::url(
3452
                    $title,
3453
                    api_get_path(WEB_CODE_PATH).'survey/survey.php?survey_id='.$surveyId.'&'.api_get_cidreq()
3454
                );
3455
            }
3456
        }
3457
3458
        $array[2] = $survey->getCode();
3459
        $array[3] = $survey->getQuestions()->count();
3460
        $array[4] = UserManager::formatUserFullName($survey->getCreator());
3461
3462
        $array[5] = '';
3463
        $from = $survey->getAvailFrom() ? $survey->getAvailFrom()->format('Y-m-d H:i:s') : null;
3464
        if (null !== $from) {
3465
            $array[5] = api_convert_and_format_date(
3466
                $from,
3467
                DATE_TIME_FORMAT_LONG
3468
            );
3469
        }
3470
3471
        $array[6] = '';
3472
        $till = $survey->getAvailTill() ? $survey->getAvailTill()->format('Y-m-d H:i:s') : null;
3473
        if (null !== $till) {
3474
            $array[6] = api_convert_and_format_date(
3475
                $till,
3476
                DATE_TIME_FORMAT_LONG
3477
            );
3478
        }
3479
3480
        $array[7] = Display::url(
3481
                $survey->getAnswered(),
3482
                api_get_path(WEB_CODE_PATH).'survey/survey_invitation.php?view=answered&survey_id='.$surveyId.'&'.api_get_cidreq()
3483
            ).' / '.
3484
            Display::url(
3485
                $survey->getInvited(),
3486
                api_get_path(WEB_CODE_PATH).'survey/survey_invitation.php?view=invited&survey_id='.$surveyId.'&'.api_get_cidreq()
3487
            );
3488
3489
        $array[8] = $survey->getAnonymous();
3490
        if ($mandatoryAllowed) {
3491
            $efvMandatory = $efv->get_values_by_handler_and_field_variable(
3492
                $surveyId,
3493
                'is_mandatory'
3494
            );
3495
3496
            $array[9] = $efvMandatory ? $efvMandatory['value'] : 0;
3497
            $array[10] = $surveyId;
3498
        } else {
3499
            $array[9] = $surveyId;
3500
        }
3501
3502
        if ($isDrh) {
3503
            $array[1] = $title;
3504
            $array[7] = strip_tags($survey->getInvited());
3505
        }
3506
3507
        $array['can_edit'] = $canEdit;
3508
3509
        return $array;
3510
    }
3511
3512
    /**
3513
     * @param $from
3514
     * @param $number_of_items
3515
     * @param $column
3516
     * @param $direction
3517
     *
3518
     * @return array
3519
     */
3520
    public static function get_survey_data_for_coach($from, $number_of_items, $column, $direction)
3521
    {
3522
        $mandatoryAllowed = ('true' === api_get_setting('survey.allow_mandatory_survey'));
3523
        $repo = Container::getSurveyRepository();
3524
        $qb = $repo->findAllByCourse(
3525
            api_get_course_entity(),
3526
            api_get_session_entity(),
3527
            null,
3528
            null,
3529
            api_get_user_entity()
3530
        );
3531
3532
        /** @var CSurvey[] $surveys */
3533
        $surveys = $qb->getQuery()->getResult();
3534
        $list = [];
3535
        foreach ($surveys as $survey) {
3536
            $list[] = $survey->getIid();
3537
        }
3538
        $list_condition = '';
3539
        if (count($list) > 0) {
3540
            $list_condition = " AND survey.iid IN (".implode(',', $list).") ";
3541
        }
3542
        $from = (int) $from;
3543
        $number_of_items = (int) $number_of_items;
3544
        $column = (int) $column;
3545
        if (!in_array(strtolower($direction), ['asc', 'desc'])) {
3546
            $direction = 'asc';
3547
        }
3548
3549
        $table_survey = Database::get_course_table(TABLE_SURVEY);
3550
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
3551
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
3552
        $course_id = api_get_course_int_id();
3553
        $efv = new ExtraFieldValue('survey');
3554
3555
        $sql = "
3556
            SELECT
3557
            survey.iid AS col0,
3558
                survey.title AS col1,
3559
                survey.code AS col2,
3560
                count(survey_question.iid) AS col3,
3561
        "
3562
            .(api_is_western_name_order()
3563
                ? "CONCAT(user.firstname, ' ', user.lastname)"
3564
                : "CONCAT(user.lastname, ' ', user.firstname)")
3565
            ."	AS col4,
3566
                survey.avail_from AS col5,
3567
                survey.avail_till AS col6,
3568
                CONCAT('<a href=\"survey_invitation.php?view=answered&survey_id=',survey.iid,'\">',survey.answered,'</a> / <a href=\"survey_invitation.php?view=invited&survey_id=',survey.iid,'\">',survey.invited, '</a>') AS col7,
3569
                survey.anonymous AS col8,
3570
                survey.iid AS col9
3571
            FROM $table_survey survey
3572
            LEFT JOIN $table_survey_question survey_question
3573
            ON (survey.iid = survey_question.survey_id),
3574
            $table_user user
3575
            WHERE survey.author = user.id AND survey.c_id = $course_id $list_condition
3576
        ";
3577
        $sql .= ' GROUP BY survey.iid';
3578
        $sql .= " ORDER BY col$column $direction ";
3579
        $sql .= " LIMIT $from,$number_of_items";
3580
3581
        $res = Database::query($sql);
3582
        $surveys = [];
3583
        while ($survey = Database::fetch_array($res)) {
3584
            $survey['col5'] = api_convert_and_format_date(
3585
                $survey['col5'],
3586
                DATE_TIME_FORMAT_LONG
3587
            );
3588
            $survey['col6'] = api_convert_and_format_date(
3589
                $survey['col6'],
3590
                DATE_TIME_FORMAT_LONG
3591
            );
3592
3593
            if ($mandatoryAllowed) {
3594
                $survey['col10'] = $survey['col9'];
3595
                $efvMandatory = $efv->get_values_by_handler_and_field_variable(
3596
                    $survey['col9'],
3597
                    'is_mandatory'
3598
                );
3599
                $survey['col9'] = $efvMandatory['value'];
3600
            }
3601
            $surveys[] = $survey;
3602
        }
3603
3604
        return $surveys;
3605
    }
3606
3607
    /**
3608
     * Display all the active surveys for the given course user.
3609
     *
3610
     * @param int $user_id
3611
     *
3612
     * @author Patrick Cool <[email protected]>, Ghent University
3613
     *
3614
     * @version April 2007
3615
     */
3616
    public static function getSurveyList($user_id)
3617
    {
3618
        $course = api_get_course_entity();
3619
        $_course = api_get_course_info();
3620
        $course_id = $_course['real_id'];
3621
        $user_id = (int) $user_id;
3622
        $sessionId = api_get_session_id();
3623
        $mandatoryAllowed = ('true' === api_get_setting('survey.allow_mandatory_survey'));
3624
3625
        // Database table definitions
3626
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
3627
        $table_survey = Database::get_course_table(TABLE_SURVEY);
3628
3629
        echo '<table id="list-survey" class="table">';
3630
        echo '<thead>';
3631
        echo '<tr>';
3632
        echo '	<th>'.get_lang('Survey name').'</th>';
3633
        echo '	<th class="text-center">'.get_lang('Anonymous').'</th>';
3634
        if ($mandatoryAllowed) {
3635
            echo '<th class="text-center">'.get_lang('Mandatory?').'</th>';
3636
        }
3637
        echo '</tr>';
3638
        echo '</thead>';
3639
        echo '<tbody>';
3640
3641
        /** @var \DateTime $now */
3642
        $now = api_get_utc_datetime(null, false, true);
3643
        $filterDate = $now->format('Y-m-d H:i');
3644
        $sessionCondition = api_get_session_condition($sessionId, true, false, 'survey_invitation.session_id');
3645
3646
        $sql = "SELECT
3647
                    survey_invitation.answered,
3648
                    survey_invitation.invitation_code,
3649
                    survey_invitation.session_id,
3650
                    survey.title,
3651
                    survey.visible_results,
3652
                    survey.iid,
3653
                    survey.anonymous
3654
                FROM $table_survey survey
3655
                INNER JOIN
3656
                $table_survey_invitation survey_invitation
3657
                ON (
3658
                    survey.iid = survey_invitation.survey_id
3659
                )
3660
				WHERE
3661
                    survey_invitation.user_id = $user_id AND
3662
                    survey.avail_from <= '$filterDate' AND
3663
                    survey.avail_till >= '$filterDate' AND
3664
                    survey_invitation.c_id = $course_id
3665
                    $sessionCondition
3666
				";
3667
        $result = Database::query($sql);
3668
        $efv = new ExtraFieldValue('survey');
3669
        $surveyIds = [];
3670
        $repo = Container::getSurveyRepository();
3671
        while ($row = Database::fetch_assoc($result)) {
3672
            $surveyId = $row['iid'];
3673
            if (in_array($surveyId, $surveyIds)) {
3674
                continue;
3675
            }
3676
3677
            /** @var CSurvey $survey */
3678
            $survey = $repo->find($surveyId);
3679
3680
            echo '<tr>';
3681
            if (0 == $survey->getAnswered()) {
3682
                echo '<td>';
3683
                $url = self::generateFillSurveyLink($survey, $row['invitation_code'], $course, $row['session_id']);
3684
                $icon = Display::getMdiIcon(ToolIcon::SURVEY, 'ch-tool-icon', null, ICON_SIZE_TINY, get_lang('Click here to answer the survey'));
3685
                echo '<a href="'.$url.'">
3686
                    '.$icon
3687
                    .$row['title']
3688
                    .'</a></td>';
3689
            } else {
3690
                $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
3691
                    $user_id,
3692
                    $_course
3693
                );
3694
                $icon = Display::getMdiIcon(ObjectIcon::SURVEY, 'ch-tool-icon-disabled', null, ICON_SIZE_TINY, get_lang('Completed surveys'));
3695
                $showLink = (!api_is_allowed_to_edit(false, true) || $isDrhOfCourse)
3696
                    && SURVEY_VISIBLE_TUTOR != $row['visible_results'];
3697
3698
                echo '<td>';
3699
                echo $showLink
3700
                    ? Display::url(
3701
                        $icon.PHP_EOL.$row['title'],
3702
                        api_get_path(WEB_CODE_PATH).'survey/reporting.php?'.api_get_cidreq().'&'.http_build_query([
3703
                            'action' => 'questionreport',
3704
                            'survey_id' => $surveyId,
3705
                        ])
3706
                    )
3707
                    : $icon.PHP_EOL.$row['title'];
3708
                echo '</td>';
3709
            }
3710
            echo '<td class="text-center">';
3711
            echo 1 == $row['anonymous'] ? get_lang('Yes') : get_lang('No');
3712
            echo '</td>';
3713
            if ($mandatoryAllowed) {
3714
                $efvMandatory = $efv->get_values_by_handler_and_field_variable(
3715
                    $row['survey_id'],
3716
                    'is_mandatory'
3717
                );
3718
                echo '<td class="text-center">'.($efvMandatory['value'] ? get_lang('Yes') : get_lang('No')).'</td>';
3719
            }
3720
            echo '</tr>';
3721
            $surveyIds[] = $surveyId;
3722
        }
3723
        echo '</tbody>';
3724
        echo '</table>';
3725
    }
3726
3727
    /**
3728
     * Creates a multi array with the user fields that we can show.
3729
     * We look the visibility with the api_get_setting function
3730
     * The username is always NOT able to change it.
3731
     *
3732
     * @author Julio Montoya Armas <[email protected]>, Chamilo: Personality Test modification
3733
     *
3734
     * @return array array[value_name][name], array[value_name][visibilty]
3735
     */
3736
    public static function make_field_list()
3737
    {
3738
        //	LAST NAME and FIRST NAME
3739
        $field_list_array = [];
3740
        $field_list_array['lastname']['name'] = get_lang('Last name');
3741
        $field_list_array['firstname']['name'] = get_lang('First name');
3742
3743
        if ('true' != api_get_setting('profile', 'name')) {
3744
            $field_list_array['firstname']['visibility'] = 0;
3745
            $field_list_array['lastname']['visibility'] = 0;
3746
        } else {
3747
            $field_list_array['firstname']['visibility'] = 1;
3748
            $field_list_array['lastname']['visibility'] = 1;
3749
        }
3750
3751
        $field_list_array['username']['name'] = get_lang('Username');
3752
        $field_list_array['username']['visibility'] = 0;
3753
3754
        //	OFFICIAL CODE
3755
        $field_list_array['official_code']['name'] = get_lang('Official code');
3756
3757
        if ('true' != api_get_setting('profile', 'officialcode')) {
3758
            $field_list_array['official_code']['visibility'] = 1;
3759
        } else {
3760
            $field_list_array['official_code']['visibility'] = 0;
3761
        }
3762
3763
        // EMAIL
3764
        $field_list_array['email']['name'] = get_lang('E-mail');
3765
        if ('true' != api_get_setting('profile', 'email')) {
3766
            $field_list_array['email']['visibility'] = 1;
3767
        } else {
3768
            $field_list_array['email']['visibility'] = 0;
3769
        }
3770
3771
        // PHONE
3772
        $field_list_array['phone']['name'] = get_lang('Phone');
3773
        if ('true' != api_get_setting('profile', 'phone')) {
3774
            $field_list_array['phone']['visibility'] = 0;
3775
        } else {
3776
            $field_list_array['phone']['visibility'] = 1;
3777
        }
3778
        //	LANGUAGE
3779
        $field_list_array['language']['name'] = get_lang('Language');
3780
        if ('true' != api_get_setting('profile', 'language')) {
3781
            $field_list_array['language']['visibility'] = 0;
3782
        } else {
3783
            $field_list_array['language']['visibility'] = 1;
3784
        }
3785
3786
        // EXTRA FIELDS
3787
        $extra = UserManager::get_extra_fields(0, 50, 5, 'ASC');
3788
3789
        foreach ($extra as $id => $field_details) {
3790
            if (0 == $field_details[6]) {
3791
                continue;
3792
            }
3793
            switch ($field_details[2]) {
3794
                case UserManager::USER_FIELD_TYPE_TEXT:
3795
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
3796
                    if (0 == $field_details[7]) {
3797
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
3798
                    } else {
3799
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
3800
                    }
3801
                    break;
3802
                case UserManager::USER_FIELD_TYPE_TEXTAREA:
3803
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
3804
                    if (0 == $field_details[7]) {
3805
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
3806
                    } else {
3807
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
3808
                    }
3809
                    break;
3810
                case UserManager::USER_FIELD_TYPE_RADIO:
3811
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
3812
                    if (0 == $field_details[7]) {
3813
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
3814
                    } else {
3815
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
3816
                    }
3817
                    break;
3818
                case UserManager::USER_FIELD_TYPE_SELECT:
3819
                    $get_lang_variables = false;
3820
                    if (in_array(
3821
                        $field_details[1],
3822
                        ['mail_notify_message', 'mail_notify_invitation', 'mail_notify_group_message']
3823
                    )
3824
                    ) {
3825
                        $get_lang_variables = true;
3826
                    }
3827
3828
                    if ($get_lang_variables) {
3829
                        $field_list_array['extra_'.$field_details[1]]['name'] = get_lang($field_details[3]);
3830
                    } else {
3831
                        $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
3832
                    }
3833
3834
                    if (0 == $field_details[7]) {
3835
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
3836
                    } else {
3837
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
3838
                    }
3839
                    break;
3840
                case UserManager::USER_FIELD_TYPE_SELECT_MULTIPLE:
3841
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
3842
                    if (0 == $field_details[7]) {
3843
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
3844
                    } else {
3845
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
3846
                    }
3847
                    break;
3848
                case UserManager::USER_FIELD_TYPE_DATE:
3849
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
3850
                    if (0 == $field_details[7]) {
3851
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
3852
                    } else {
3853
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
3854
                    }
3855
                    break;
3856
                case UserManager::USER_FIELD_TYPE_DATETIME:
3857
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
3858
                    if (0 == $field_details[7]) {
3859
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
3860
                    } else {
3861
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
3862
                    }
3863
                    break;
3864
                case UserManager::USER_FIELD_TYPE_DOUBLE_SELECT:
3865
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
3866
                    if (0 == $field_details[7]) {
3867
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
3868
                    } else {
3869
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
3870
                    }
3871
                    break;
3872
                case UserManager::USER_FIELD_TYPE_DIVIDER:
3873
                    //$form->addElement('static',$field_details[1], '<br /><strong>'.$field_details[3].'</strong>');
3874
                    break;
3875
            }
3876
        }
3877
3878
        return $field_list_array;
3879
    }
3880
3881
    /**
3882
     * Display survey question chart.
3883
     *
3884
     * @param array  $chartData
3885
     * @param bool   $hasSerie         Tells if the chart has a serie. False by default
3886
     * @param string $chartContainerId
3887
     *
3888
     * @return string (direct output)
3889
     */
3890
    public static function drawChart($chartData, $hasSerie = false, $chartContainerId = 'chartContainer', $loadLibs = true)
3891
    {
3892
        $htmlChart = '';
3893
        //if (api_browser_support('svg')) {
3894
        if (true) {
3895
            $serie = [];
3896
            $order = [];
3897
            $data = '';
3898
            foreach ($chartData as $chartDataElement) {
3899
                $data .= '{"';
3900
                $option = str_replace(["\n", "\r"], '', $chartDataElement['option']);
3901
                $serieValue = isset($chartDataElement['serie']) ? $chartDataElement['serie'] : null;
3902
                if (!$hasSerie) {
3903
                    $data .= get_lang("Option").'":"'.$option.'", "';
3904
                    array_push($order, $option);
3905
                } else {
3906
                    if (!is_array($serieValue)) {
3907
                        $data .=
3908
                            get_lang("Option").'":"'.$serieValue.'", "'.
3909
                            get_lang("Score").'":"'.$option.'", "';
3910
                        array_push($serie, $serieValue);
3911
                    } else {
3912
                        $data .=
3913
                            get_lang("Serie").'":"'.$serieValue[0].'", "'.
3914
                            get_lang("Option").'":"'.$serieValue[1].'", "'.
3915
                            get_lang("Score").'":"'.$option.'", "';
3916
                    }
3917
                }
3918
                $data .= get_lang("Votes").'":"'.$chartDataElement['votes'].'"},';
3919
                rtrim($data, ",");
3920
            }
3921
            if ($loadLibs) {
3922
                $htmlChart .= api_get_js('d3/d3.v3.5.4.min.js');
3923
                $htmlChart .= api_get_js('dimple.v2.1.2.min.js');
3924
            }
3925
3926
            $htmlChart .= '
3927
            <script>
3928
                var svg = dimple.newSvg("#'.$chartContainerId.'", 600, 400);
3929
                var data = ['.$data.'];
3930
                var myChart = new dimple.chart(svg, data);
3931
                myChart.setBounds(50, 30, 550, 300);
3932
                var yAxis = myChart.addMeasureAxis("y", "'.get_lang('Votes').'");
3933
                yAxis.fontSize = "14px";
3934
            ';
3935
            if (!$hasSerie) {
3936
                $htmlChart .= '
3937
                    var xAxisCategory = myChart.addCategoryAxis("x", "'.get_lang("Option").'");
3938
                    xAxisCategory.fontSize = "14px";
3939
                    xAxisCategory.addOrderRule('.json_encode($order).');
3940
                    myChart.addSeries("'.get_lang("Option").'", dimple.plot.bar);';
3941
            } else {
3942
                if (!is_array($chartDataElement['serie'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $chartDataElement seems to be defined by a foreach iteration on line 3898. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
3943
                    $serie = array_values(array_unique($serie));
3944
                    $htmlChart .= '
3945
                        var xAxisCategory =
3946
                        myChart.addCategoryAxis("x", ["'.get_lang('Option').'","'.get_lang("Score").'"]);
3947
                        xAxisCategory.addOrderRule('.json_encode($serie).');
3948
                        xAxisCategory.addGroupOrderRule("'.get_lang('Score').'");
3949
3950
                        myChart.addSeries("'.get_lang('Option').'", dimple.plot.bar);';
3951
                } else {
3952
                    $htmlChart .= '
3953
                        myChart.addCategoryAxis("x", ["'.get_lang('Option').'","'.get_lang("Score").'"]);
3954
                        myChart.addSeries("'.get_lang('Serie').'", dimple.plot.bar);';
3955
                }
3956
            }
3957
            $htmlChart .= 'myChart.draw();';
3958
            $htmlChart .= '</script>';
3959
        }
3960
3961
        return $htmlChart;
3962
    }
3963
3964
    /**
3965
     * Set a flag to the current survey as answered by the current user.
3966
     */
3967
    public static function flagSurveyAsAnswered(string $surveyCode, int $courseId): void
3968
    {
3969
        $currentUserId = api_get_user_id();
3970
        $flag = sprintf('%s-%s-%d', $courseId, $surveyCode, $currentUserId);
3971
3972
        if (!isset($_SESSION['filled_surveys'])) {
3973
            $_SESSION['filled_surveys'] = [];
3974
        }
3975
3976
        $_SESSION['filled_surveys'][] = $flag;
3977
    }
3978
3979
    /**
3980
     * Check whether a survey was answered by the current user.
3981
     */
3982
    public static function isSurveyAnsweredFlagged(string $surveyCode, int $courseId): bool
3983
    {
3984
        $currentUserId = api_get_user_id();
3985
        $flagToCheck = sprintf('%s-%s-%d', $courseId, $surveyCode, $currentUserId);
3986
3987
        if (!isset($_SESSION['filled_surveys'])) {
3988
            return false;
3989
        }
3990
3991
        if (!is_array($_SESSION['filled_surveys'])) {
3992
            return false;
3993
        }
3994
3995
        foreach ($_SESSION['filled_surveys'] as $flag) {
3996
            if ($flagToCheck != $flag) {
3997
                continue;
3998
            }
3999
4000
            return true;
4001
        }
4002
4003
        return false;
4004
    }
4005
4006
    /**
4007
     * Check if the current survey has answers.
4008
     *
4009
     * @param int $surveyId
4010
     *
4011
     * @return bool return true if the survey has answers, false otherwise
4012
     */
4013
    public static function checkIfSurveyHasAnswers(int $surveyId): bool
4014
    {
4015
        $tableSurveyAnswer = Database::get_course_table(TABLE_SURVEY_ANSWER);
4016
4017
        if (empty($surveyId)) {
4018
            return false;
4019
        }
4020
4021
        $sql = "SELECT * FROM $tableSurveyAnswer
4022
                WHERE
4023
                    survey_id = '".$surveyId."'
4024
                ORDER BY iid, user ASC";
4025
        $result = Database::query($sql);
4026
        $response = Database::affected_rows($result);
4027
4028
        return $response > 0;
4029
    }
4030
4031
    /**
4032
     * @param int $surveyId
4033
     * @param int $courseId
4034
     * @param int $sessionId
4035
     *
4036
     * @return array
4037
     */
4038
    public static function getSentInvitations($surveyId, $courseId, $sessionId = 0)
4039
    {
4040
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
4041
        $tblSurveyInvitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
4042
4043
        $sessionCondition = api_get_session_condition($sessionId);
4044
        $surveyId = (int) $surveyId;
4045
        $courseId = (int) $courseId;
4046
4047
        $sql = "SELECT survey_invitation.*, user.firstname, user.lastname, user.email
4048
                FROM $tblSurveyInvitation survey_invitation
4049
                LEFT JOIN $tblUser user
4050
                ON (survey_invitation.user_id = user.id AND survey_invitation.c_id = $courseId)
4051
                WHERE
4052
                    survey_invitation.survey_id = $surveyId AND
4053
                    survey_invitation.c_id = $courseId
4054
                    $sessionCondition";
4055
4056
        $query = Database::query($sql);
4057
4058
        return Database::store_result($query);
4059
    }
4060
4061
    /**
4062
     * @param string $code      invitation code
4063
     * @param int    $sessionId
4064
     *
4065
     * @return string
4066
     */
4067
    public static function generateFillSurveyLink(CSurvey $survey, $invitationCode, Course $course, $sessionId = 0)
4068
    {
4069
        $invitationCode = Security::remove_XSS($invitationCode);
4070
        $sessionId = (int) $sessionId;
4071
4072
        $params = [
4073
            'iid' => $survey->getIid(),
4074
            'invitationcode' => $invitationCode,
4075
            'cid' => $course->getId(),
4076
            'course' => $course->getCode(),
4077
            'sid' => $sessionId,
4078
            'language' => $course->getCourseLanguage(),
4079
        ];
4080
4081
        return api_get_path(WEB_CODE_PATH).'survey/fillsurvey.php?'.http_build_query($params);
4082
    }
4083
}
4084