Passed
Push — 1.11.x ( cb872d...05a9d8 )
by Julito
13:03
created

SurveyUtil::displayCompleteReport()   F

Complexity

Conditions 56
Paths > 20000

Size

Total Lines 297
Code Lines 184

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 56
eloc 184
c 0
b 0
f 0
nc 345745
nop 5
dl 0
loc 297
rs 0

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\CourseBundle\Entity\CSurvey;
6
use ChamiloSession as Session;
7
8
/**
9
 * This class offers a series of general utility functions for survey querying and display.
10
 */
11
class SurveyUtil
12
{
13
    /**
14
     * Checks whether the given survey has a pagebreak question as the first
15
     * or the last question.
16
     * If so, break the current process, displaying an error message.
17
     *
18
     * @param int  $survey_id Survey ID (database ID)
19
     * @param bool $continue  Optional. Whether to continue the current
20
     *                        process or exit when breaking condition found. Defaults to true (do not break).
21
     */
22
    public static function check_first_last_question($survey_id, $continue = true)
23
    {
24
        // Table definitions
25
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
26
        $course_id = api_get_course_int_id();
27
        $survey_id = (int) $survey_id;
28
29
        // Getting the information of the question
30
        $sql = "SELECT * FROM $tbl_survey_question
31
                WHERE c_id = $course_id AND survey_id='".$survey_id."'
32
                ORDER BY sort ASC";
33
        $result = Database::query($sql);
34
        $total = Database::num_rows($result);
35
        $counter = 1;
36
        $error = false;
37
        while ($row = Database::fetch_array($result, 'ASSOC')) {
38
            if ($counter == 1 && $row['type'] == 'pagebreak') {
39
                echo Display::return_message(get_lang('PagebreakNotFirst'), 'error', false);
40
                $error = true;
41
            }
42
            if ($counter == $total && $row['type'] == 'pagebreak') {
43
                echo Display::return_message(get_lang('PagebreakNotLast'), 'error', false);
44
                $error = true;
45
            }
46
            $counter++;
47
        }
48
49
        if (!$continue && $error) {
50
            Display::display_footer();
51
            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...
52
        }
53
    }
54
55
    /**
56
     * This function removes an (or multiple) answer(s) of a user on a question of a survey.
57
     *
58
     * @param mixed   The user id or email of the person who fills the survey
59
     * @param int The survey id
60
     * @param int The question id
61
     * @param int The option id
62
     *
63
     * @author Patrick Cool <[email protected]>, Ghent University
64
     *
65
     * @version January 2007
66
     */
67
    public static function remove_answer($user, $survey_id, $question_id, $course_id)
68
    {
69
        $course_id = intval($course_id);
70
        // table definition
71
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
72
        $sql = "DELETE FROM $table
73
				WHERE
74
				    c_id = $course_id AND
75
                    user = '".Database::escape_string($user)."' AND
76
                    survey_id = '".intval($survey_id)."' AND
77
                    question_id = '".intval($question_id)."'";
78
        Database::query($sql);
79
    }
80
81
    /**
82
     * This function stores an answer of a user on a question of a survey.
83
     *
84
     * @param mixed   The user id or email of the person who fills the survey
85
     * @param int Survey id
86
     * @param int Question id
87
     * @param int Option id
88
     * @param string  Option value
89
     * @param array $survey_data Survey data settings
90
     *
91
     * @return bool False if insufficient data, true otherwise
92
     *
93
     * @author Patrick Cool <[email protected]>, Ghent University
94
     *
95
     * @version January 2007
96
     */
97
    public static function store_answer(
98
        $user,
99
        $survey_id,
100
        $question_id,
101
        $option_id,
102
        $option_value,
103
        $survey_data,
104
        $otherOption = ''
105
    ) {
106
        // If the question_id is empty, don't store an answer
107
        if (empty($question_id)) {
108
            return false;
109
        }
110
111
        // Table definition
112
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
113
114
        // Make the survey anonymous
115
        if (1 == $survey_data['anonymous']) {
116
            $surveyUser = Session::read('surveyuser');
117
            if (empty($surveyUser)) {
118
                $user = md5($user.time());
119
                Session::write('surveyuser', $user);
120
            } else {
121
                $user = Session::read('surveyuser');
122
            }
123
        }
124
125
        $course_id = $survey_data['c_id'];
126
127
        if (!empty($otherOption)) {
128
            $option_id = $option_id.'@:@'.$otherOption;
129
        }
130
131
        $sql = "INSERT INTO $table_survey_answer (c_id, user, survey_id, question_id, option_id, value) VALUES (
132
				$course_id,
133
				'".Database::escape_string($user)."',
134
				'".Database::escape_string($survey_id)."',
135
				'".Database::escape_string($question_id)."',
136
				'".Database::escape_string($option_id)."',
137
				'".Database::escape_string($option_value)."'
138
				)";
139
        Database::query($sql);
140
        $insertId = Database::insert_id();
141
        if ($insertId) {
142
            $sql = "UPDATE $table_survey_answer SET answer_id = $insertId
143
                    WHERE iid = $insertId";
144
            Database::query($sql);
145
146
            return true;
147
        }
148
149
        return false;
150
    }
151
152
    /**
153
     * This function checks the parameters that are used in this page.
154
     *
155
     * @return string $people_filled The header, an error and the footer if any parameter fails, else it returns true
156
     *
157
     * @author Patrick Cool <[email protected]>, Ghent University
158
     *
159
     * @version February 2007
160
     */
161
    public static function check_parameters($people_filled)
162
    {
163
        $error = false;
164
165
        // Getting the survey data
166
        $survey_data = SurveyManager::get_survey($_GET['survey_id']);
167
168
        // $_GET['survey_id'] has to be numeric
169
        if (!is_numeric($_GET['survey_id'])) {
170
            $error = get_lang('IllegalSurveyId');
171
        }
172
173
        // $_GET['action']
174
        $allowed_actions = [
175
            'overview',
176
            'questionreport',
177
            'userreport',
178
            'comparativereport',
179
            'completereport',
180
            'deleteuserreport',
181
        ];
182
        if (isset($_GET['action']) && !in_array($_GET['action'], $allowed_actions)) {
183
            $error = get_lang('ActionNotAllowed');
184
        }
185
186
        // User report
187
        if (isset($_GET['action']) && $_GET['action'] === 'userreport') {
188
            if ($survey_data['anonymous'] == 0) {
189
                foreach ($people_filled as $key => &$value) {
190
                    $people_filled_userids[] = $value['invited_user'];
191
                }
192
            } else {
193
                $people_filled_userids = $people_filled;
194
            }
195
196
            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...
197
                $error = get_lang('UnknowUser');
198
            }
199
        }
200
201
        // Question report
202
        if (isset($_GET['action']) && $_GET['action'] === 'questionreport') {
203
            if (isset($_GET['question']) && !is_numeric($_GET['question'])) {
204
                $error = get_lang('UnknowQuestion');
205
            }
206
        }
207
208
        if ($error) {
209
            $tool_name = get_lang('Reporting');
210
            Display::addFlash(
211
                Display::return_message(
212
                    get_lang('Error').': '.$error,
213
                    'error',
214
                    false
215
                )
216
            );
217
            Display::display_header($tool_name);
218
            Display::display_footer();
219
            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...
220
        }
221
222
        return true;
223
    }
224
225
    /**
226
     * This function deals with the action handling.
227
     *
228
     * @param array $survey_data
229
     * @param array $people_filled
230
     *
231
     * @author Patrick Cool <[email protected]>, Ghent University
232
     *
233
     * @version February 2007
234
     */
235
    public static function handle_reporting_actions($survey_data, $people_filled)
236
    {
237
        $action = isset($_GET['action']) ? $_GET['action'] : '';
238
239
        // Getting the number of question
240
        $questions = SurveyManager::get_questions($survey_data['survey_id']);
241
242
        $counter = 0;
243
        foreach ($questions as $key => $value) {
244
            if ($value['type'] !== 'pagebreak') {
245
                $counter++;
246
            }
247
        }
248
        // Counting the number of questions that are relevant for the reporting
249
        $survey_data['number_of_questions'] = $counter;
250
251
        switch ($action) {
252
            case 'questionreport':
253
                self::display_question_report($survey_data);
254
                break;
255
            case 'userreport':
256
                self::displayUserReport($survey_data, $people_filled);
257
                break;
258
            case 'comparativereport':
259
                self::display_comparative_report();
260
                break;
261
            case 'completereport':
262
                echo self::displayCompleteReport($survey_data);
263
                break;
264
            case 'deleteuserreport':
265
                self::delete_user_report($_GET['survey_id'], $_GET['user']);
266
                break;
267
        }
268
    }
269
270
    /**
271
     * This function deletes the report of an user who wants to retake the survey.
272
     *
273
     * @param int $survey_id
274
     * @param int $user_id
275
     *
276
     * @author Christian Fasanando Flores <[email protected]>
277
     *
278
     * @version November 2008
279
     */
280
    public static function delete_user_report($survey_id, $user_id)
281
    {
282
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
283
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
284
        $table_survey = Database::get_course_table(TABLE_SURVEY);
285
286
        $course_id = api_get_course_int_id();
287
        $survey_id = (int) $survey_id;
288
        $user_id = Database::escape_string($user_id);
289
290
        if (!empty($survey_id) && !empty($user_id)) {
291
            // delete data from survey_answer by user_id and survey_id
292
            $sql = "DELETE FROM $table_survey_answer
293
			        WHERE c_id = $course_id AND survey_id = '".$survey_id."' AND user = '".$user_id."'";
294
            Database::query($sql);
295
            // update field answered from survey_invitation by user_id and survey_id
296
            $sql = "UPDATE $table_survey_invitation SET answered = '0'
297
			        WHERE
298
			            c_id = $course_id AND
299
			            survey_code = (
300
                            SELECT code FROM $table_survey
301
                            WHERE
302
                                c_id = $course_id AND
303
                                survey_id = '".$survey_id."'
304
                        ) AND
305
			            user = '".$user_id."'";
306
            $result = Database::query($sql);
307
        }
308
309
        if ($result !== false) {
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...
310
            $message = get_lang('SurveyUserAnswersHaveBeenRemovedSuccessfully').'<br />
311
					<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=userreport&survey_id='
312
                .$survey_id.'">'.
313
                get_lang('GoBack').'</a>';
314
            echo Display::return_message($message, 'confirmation', false);
315
        }
316
    }
317
318
    /**
319
     * @param array $survey_data
320
     * @param array $people_filled
321
     *
322
     * @return string
323
     */
324
    public static function displayUserReportForm($survey_data, $people_filled)
325
    {
326
        $surveyId = $survey_data['survey_id'];
327
328
        if (empty($survey_data)) {
329
            return '';
330
        }
331
332
        // Step 1: selection of the user
333
        echo "<script>
334
        function jumpMenu(targ,selObj,restore) {
335
            eval(targ+\".location='\"+selObj.options[selObj.selectedIndex].value+\"'\");
336
            if (restore) selObj.selectedIndex=0;
337
        }
338
		</script>";
339
        echo get_lang('SelectUserWhoFilledSurvey').'<br />';
340
        echo '<select name="user" onchange="jumpMenu(\'parent\',this,0)">';
341
        echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
342
            .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">'
343
            .get_lang('SelectUser').'</option>';
344
345
        foreach ($people_filled as $key => &$person) {
346
            if ($survey_data['anonymous'] == 0) {
347
                $name = $person['user_info']['complete_name_with_username'];
348
                $id = $person['user_id'];
349
                if ($id == '') {
350
                    $id = $person['invited_user'];
351
                    $name = $person['invited_user'];
352
                }
353
            } else {
354
                $name = get_lang('Anonymous').' '.($key + 1);
355
                $id = $person;
356
            }
357
            echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
358
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&user='
359
                .Security::remove_XSS($id).'&'.api_get_cidreq().'" ';
360
            if (isset($_GET['user']) && $_GET['user'] == $id) {
361
                echo 'selected="selected"';
362
            }
363
            echo '>'.$name.'</option>';
364
        }
365
        echo '</select>';
366
    }
367
368
    /**
369
     * @param int   $userId
370
     * @param array $survey_data
371
     * @param bool  $addMessage
372
     */
373
    public static function displayUserReportAnswers($userId, $survey_data, $addMessage = true)
374
    {
375
        // Database table definitions
376
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
377
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
378
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
379
        $course_id = (int) $survey_data['c_id'];
380
        $surveyId = (int) $survey_data['survey_id'];
381
        $userId = Database::escape_string($userId);
382
383
        $content = '';
384
        // Step 2: displaying the survey and the answer of the selected users
385
        if (!empty($userId)) {
386
            if ($addMessage) {
387
                $content .= Display::return_message(
388
                    get_lang('AllQuestionsOnOnePage'),
389
                    'normal',
390
                    false
391
                );
392
            }
393
394
            // Getting all the questions and options
395
            $sql = "SELECT
396
			            survey_question.question_id,
397
			            survey_question.survey_id,
398
			            survey_question.survey_question,
399
			            survey_question.display,
400
			            survey_question.max_value,
401
			            survey_question.sort,
402
			            survey_question.type,
403
                        survey_question_option.question_option_id,
404
                        survey_question_option.option_text,
405
                        survey_question_option.sort as option_sort
406
					FROM $table_survey_question survey_question
407
					LEFT JOIN $table_survey_question_option survey_question_option
408
					ON
409
					    survey_question.question_id = survey_question_option.question_id AND
410
					    survey_question_option.c_id = $course_id
411
					WHERE
412
					    survey_question NOT LIKE '%{{%' AND
413
					    survey_question.survey_id = '".$surveyId."' AND
414
                        survey_question.c_id = $course_id
415
					ORDER BY survey_question.sort, survey_question_option.sort ASC";
416
            $result = Database::query($sql);
417
            while ($row = Database::fetch_array($result, 'ASSOC')) {
418
                if ($row['type'] != 'pagebreak') {
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
            // Getting all the answers of the user
430
            $sql = "SELECT * FROM $table_survey_answer
431
			        WHERE
432
                        c_id = $course_id AND
433
                        survey_id = '".$surveyId."' AND
434
                        user = '".$userId."'";
435
            $result = Database::query($sql);
436
            while ($row = Database::fetch_array($result, 'ASSOC')) {
437
                $answers[$row['question_id']][] = $row['option_id'];
438
                $all_answers[$row['question_id']][] = $row;
439
            }
440
441
            // Displaying all the questions
442
            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...
443
                // If the question type is a scoring then we have to format the answers differently
444
                switch ($question['type']) {
445
                    case 'score':
446
                        $finalAnswer = [];
447
                        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...
448
                            foreach ($all_answers[$question['question_id']] as $key => &$answer_array) {
449
                                $finalAnswer[$answer_array['option_id']] = $answer_array['value'];
450
                            }
451
                        }
452
                        break;
453
                    case 'multipleresponse':
454
                        $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...
455
                        break;
456
                    default:
457
                        $finalAnswer = '';
458
                        if (isset($all_answers[$question['question_id']])) {
459
                            $finalAnswer = $all_answers[$question['question_id']][0]['option_id'];
460
                        }
461
                        break;
462
                }
463
464
                $display = survey_question::createQuestion($question['type']);
465
                $url = api_get_self();
466
                $form = new FormValidator('question', 'post', $url);
467
                $form->addHtml('<div class="survey_question_wrapper"><div class="survey_question">');
468
                $form->addHtml($question['survey_question']);
469
                $display->render($form, $question, $finalAnswer);
470
                $form->addHtml('</div></div>');
471
                $content .= $form->returnForm();
472
            }
473
        }
474
475
        return $content;
476
    }
477
478
    /**
479
     * This function displays the user report which is basically nothing more
480
     * than a one-page display of all the questions
481
     * of the survey that is filled with the answers of the person who filled the survey.
482
     *
483
     * @return string html code of the one-page survey with the answers of the selected user
484
     *
485
     * @author Patrick Cool <[email protected]>, Ghent University
486
     *
487
     * @version February 2007 - Updated March 2008
488
     */
489
    public static function displayUserReport($survey_data, $people_filled, $addActionBar = true)
490
    {
491
        if (empty($survey_data)) {
492
            return '';
493
        }
494
495
        $surveyId = $survey_data['survey_id'];
496
        $reportingUrl = api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq();
497
498
        // Actions bar
499
        if ($addActionBar) {
500
            echo '<div class="actions">';
501
            echo '<a href="'.$reportingUrl.'">'.
502
                Display::return_icon(
503
                    'back.png',
504
                    get_lang('BackTo').' '.get_lang('ReportingOverview'),
505
                    '',
506
                    ICON_SIZE_MEDIUM
507
                )
508
                .'</a>';
509
            if (isset($_GET['user'])) {
510
                if (api_is_allowed_to_edit()) {
511
                    // The delete link
512
                    echo '<a href="'.$reportingUrl.'&action=deleteuserreport&user='.Security::remove_XSS($_GET['user']).'" >'.
513
                        Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_MEDIUM).'</a>';
514
                }
515
516
                // Export the user report
517
                echo '<a href="javascript: void(0);" onclick="document.form1a.submit();">'
518
                    .Display::return_icon('export_csv.png', get_lang('ExportAsCSV'), '', ICON_SIZE_MEDIUM).'</a> ';
519
                echo '<a href="javascript: void(0);" onclick="document.form1b.submit();">'
520
                    .Display::return_icon('export_excel.png', get_lang('ExportAsXLS'), '', ICON_SIZE_MEDIUM).'</a> ';
521
                echo '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='
522
                    .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
523
                    .Security::remove_XSS($_GET['user']).'">';
524
                echo '<input type="hidden" name="export_report" value="export_report">';
525
                echo '<input type="hidden" name="export_format" value="csv">';
526
                echo '</form>';
527
                echo '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='
528
                    .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
529
                    .Security::remove_XSS($_GET['user']).'">';
530
                echo '<input type="hidden" name="export_report" value="export_report">';
531
                echo '<input type="hidden" name="export_format" value="xls">';
532
                echo '</form>';
533
                echo '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='
534
                    .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
535
            }
536
            echo '</div>';
537
        }
538
539
        echo self::displayUserReportForm($survey_data, $people_filled);
540
        if (isset($_GET['user'])) {
541
            echo self::displayUserReportAnswers($_GET['user'], $survey_data);
542
        }
543
    }
544
545
    /**
546
     * This function displays the report by question.
547
     *
548
     * It displays a table with all the options of the question and the number of users who have answered positively on
549
     * the option. The number of users who answered positive on a given option is expressed in an absolute number, in a
550
     * percentage of the total and graphically using bars By clicking on the absolute number you get a list with the
551
     * persons who have answered this. You can then click on the name of the person and you will then go to the report
552
     * by user where you see all the answers of that user.
553
     *
554
     * @param    array    All the survey data
555
     *
556
     * @return string html code that displays the report by question
557
     *
558
     * @todo allow switching between horizontal and vertical.
559
     * @todo multiple response: percentage are probably not OK
560
     * @todo the question and option text have to be shortened and should expand when the user clicks on it.
561
     * @todo the pagebreak and comment question types should not be shown => removed from $survey_data before
562
     *
563
     * @author Patrick Cool <[email protected]>, Ghent University
564
     *
565
     * @version February 2007 - Updated March 2008
566
     */
567
    public static function display_question_report($survey_data)
568
    {
569
        $singlePage = isset($_GET['single_page']) ? (int) $_GET['single_page'] : 0;
570
        // Determining the offset of the sql statement (the n-th question of the survey)
571
        $offset = !isset($_GET['question']) ? 0 : (int) $_GET['question'];
572
        $currentQuestion = isset($_GET['question']) ? (int) $_GET['question'] : 0;
573
        $surveyId = (int) $survey_data['survey_id'];
574
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
575
        $course_id = api_get_course_int_id();
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
        $questions = [];
582
583
        echo '<div class="actions">';
584
        echo '<a
585
            href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'.
586
            Display::return_icon(
587
                'back.png',
588
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
589
                '',
590
                ICON_SIZE_MEDIUM
591
            ).'</a>';
592
593
        echo Display::url(
594
            Display::return_icon(
595
                'pdf.png',
596
                get_lang('ExportToPdf'),
597
                '',
598
                ICON_SIZE_MEDIUM
599
            ),
600
            'javascript: void(0);',
601
            ['onclick' => 'exportToPdf();']
602
        );
603
        echo '</div>';
604
605
        $fromUntil = sprintf(get_lang('FromXUntilY'), $survey_data['avail_from'], $survey_data['avail_till']);
606
        $max = 80;
607
        $data = [
608
            get_lang('SurveyTitle') => cut(strip_tags($survey_data['title']), $max),
609
            get_lang('SurveySubTitle') => cut(strip_tags($survey_data['subtitle']), $max),
610
            get_lang('Dates') => $fromUntil,
611
            get_lang('SurveyIntroduction') => cut(strip_tags($survey_data['intro']), $max),
612
        ];
613
614
        $table = new HTML_Table(['id' => 'pdf_table', 'class' => 'table']);
615
        $row = 0;
616
        foreach ($data as $label => $item) {
617
            $table->setCellContents($row, 0, $label);
618
            $table->setCellContents($row, 1, $item);
619
            $row++;
620
        }
621
622
        if ($survey_data['number_of_questions'] > 0) {
623
            $limitStatement = null;
624
            if (!$singlePage) {
625
                echo '<div id="question_report_questionnumbers" class="pagination">';
626
                if ($currentQuestion != 0) {
627
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
628
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset - 1).'">'
629
                        .get_lang('PreviousQuestion').'</a></li>';
630
                }
631
632
                for ($i = 1; $i <= $survey_data['number_of_questions']; $i++) {
633
                    if ($offset != $i - 1) {
634
                        echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
635
                            .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($i - 1).'">'.$i.'</a></li>';
636
                    } else {
637
                        echo '<li class="disabled"><a href="#">'.$i.'</a></li>';
638
                    }
639
                }
640
                if ($currentQuestion < ($survey_data['number_of_questions'] - 1)) {
641
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
642
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset + 1).'">'
643
                        .get_lang('NextQuestion').'</li></a>';
644
                }
645
                echo '</ul>';
646
                echo '</div>';
647
                $limitStatement = " LIMIT $offset, 1";
648
            }
649
650
            // Getting the question information
651
            $sql = "SELECT * FROM $table_survey_question
652
			        WHERE
653
			            c_id = $course_id AND
654
                        survey_id = $surveyId AND
655
                        survey_question NOT LIKE '%{{%' AND
656
                        type <>'pagebreak'
657
                    ORDER BY sort ASC
658
                    $limitStatement";
659
            $result = Database::query($sql);
660
            while ($row = Database::fetch_array($result)) {
661
                $questions[$row['question_id']] = $row;
662
            }
663
        }
664
665
        echo '<div id="question_results">';
666
        foreach ($questions as $question) {
667
            echo '<div class="question-item">';
668
            $chartData = [];
669
            $options = [];
670
            $questionId = (int) $question['question_id'];
671
672
            echo '<div class="title-question">';
673
            echo strip_tags(isset($question['survey_question']) ? $question['survey_question'] : null);
674
            echo '</div>';
675
676
            if ('score' === $question['type']) {
677
                /** @todo This function should return the options as this is needed further in the code */
678
                $options = self::display_question_report_score($survey_data, $question, $offset);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $options is correct as self::display_question_r...ta, $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...
679
            } elseif ($question['type'] === 'open' || $question['type'] === 'comment') {
680
                echo '<div class="open-question">';
681
                /** @todo Also get the user who has answered this */
682
                $sql = "SELECT * FROM $table_survey_answer
683
                        WHERE
684
                            c_id = $course_id AND
685
                            survey_id= $surveyId AND
686
                            question_id = $questionId ";
687
                $result = Database::query($sql);
688
                while ($row = Database::fetch_array($result, 'ASSOC')) {
689
                    echo $row['option_id'].'<hr noshade="noshade" size="1" />';
690
                }
691
                echo '</div>';
692
            } else {
693
                // Getting the options ORDER BY sort ASC
694
                $sql = "SELECT * FROM $table_survey_question_option
695
                        WHERE
696
                            c_id = $course_id AND
697
                            survey_id = $surveyId AND
698
                            question_id = $questionId
699
                        ORDER BY sort ASC";
700
                $result = Database::query($sql);
701
                while ($row = Database::fetch_array($result, 'ASSOC')) {
702
                    $options[$row['question_option_id']] = $row;
703
                }
704
                // Getting the answers
705
                $sql = "SELECT *, count(answer_id) as total
706
                        FROM $table_survey_answer
707
                        WHERE
708
                            c_id = $course_id AND
709
                            survey_id = $surveyId AND
710
                            question_id = $questionId
711
                        GROUP BY option_id, value";
712
                $result = Database::query($sql);
713
                $number_of_answers = [];
714
                $data = [];
715
                while ($row = Database::fetch_array($result, 'ASSOC')) {
716
                    if (!isset($number_of_answers[$row['question_id']])) {
717
                        $number_of_answers[$row['question_id']] = 0;
718
                    }
719
                    $number_of_answers[$row['question_id']] += $row['total'];
720
721
                    if ('multiplechoiceother' === $question['type']) {
722
                        $parts = ch_multiplechoiceother::decodeOptionValue($row['option_id']);
723
                        $row['option_id'] = $parts[0];
724
                    }
725
726
                    $data[$row['option_id']] = $row;
727
                }
728
729
                foreach ($options as $option) {
730
                    $optionText = strip_tags($option['option_text']);
731
                    $optionText = html_entity_decode($optionText);
732
                    $votes = 0;
733
                    if (isset($data[$option['question_option_id']]['total'])) {
734
                        $votes = $data[$option['question_option_id']]['total'];
735
                    }
736
                    array_push($chartData, ['option' => $optionText, 'votes' => $votes]);
737
                }
738
                $chartContainerId = 'chartContainer'.$question['question_id'];
739
                echo '<div id="'.$chartContainerId.'" style="text-align:center;">';
740
                echo self::drawChart($chartData, false, $chartContainerId, false);
741
                echo '</div>';
742
743
                // displaying the table: headers
744
                echo '<table class="display-survey table" id="table_'.$chartContainerId.'">';
745
                echo '';
746
                echo '	<tr>';
747
                echo '		<th style="width: 50%">&nbsp;</th>';
748
                echo '		<th style="width: 10%">'.get_lang('AbsoluteTotal').'</th>';
749
                echo '		<th style="width: 10%">'.get_lang('Percentage').'</th>';
750
                echo '		<th style="width: 30%">'.get_lang('VisualRepresentation').'</th>';
751
                echo '	</tr>';
752
753
                // Displaying the table: the content
754
                if (is_array($options)) {
755
                    foreach ($options as $key => &$value) {
756
                        if ('multiplechoiceother' === $question['type'] && 'other' === $value['option_text']) {
757
                            $value['option_text'] = get_lang('SurveyOtherAnswer');
758
                        }
759
760
                        $absolute_number = null;
761
                        if (isset($data[$value['question_option_id']])) {
762
                            $absolute_number = $data[$value['question_option_id']]['total'];
763
                        }
764
                        if ($question['type'] === 'percentage' && empty($absolute_number)) {
765
                            continue;
766
                        }
767
                        $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...
768
                            ? $number_of_answers[$option['question_id']]
769
                            : 0;
770
                        if ($number_of_answers[$option['question_id']] == 0) {
771
                            $answers_number = 0;
772
                        } else {
773
                            $answers_number = $absolute_number / $number_of_answers[$option['question_id']] * 100;
774
                        }
775
                        echo '<tr>';
776
                        echo '<td>'.$value['option_text'].'</td>';
777
                        echo '<td>';
778
                        if ($absolute_number != 0) {
779
                            echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action
780
                                .'&survey_id='.$surveyId.'&question='.$offset.'&viewoption='
781
                                .$value['question_option_id'].'">'.$absolute_number.'</a>';
782
                        } else {
783
                            echo '0';
784
                        }
785
                        echo '</td>';
786
                        echo '<td>'.round($answers_number, 2).' %</td>';
787
                        echo '<td>';
788
                        $size = $answers_number * 2;
789
                        if ($size > 0) {
790
                            echo '<div
791
                                    style="border:1px solid #264269; background-color:#aecaf4; height:10px;
792
                                    width:'.$size.'px">
793
                                    &nbsp;
794
                                    </div>';
795
                        } else {
796
                            echo '<div style="text-align: left;">'.get_lang('NoDataAvailable').'</div>';
797
                        }
798
                        echo ' </td>';
799
                        echo ' </tr>';
800
                    }
801
                }
802
803
                $optionResult = '';
804
                if (isset($option['question_id']) && isset($number_of_answers[$option['question_id']])) {
805
                    if ($number_of_answers[$option['question_id']] == 0) {
806
                        $optionResult = '0';
807
                    } else {
808
                        $optionResult = $number_of_answers[$option['question_id']];
809
                    }
810
                }
811
812
                // displaying the table: footer (totals)
813
                echo '	<tr>
814
                            <td><b>'.get_lang('Total').'</b></td>
815
                            <td><b>'.$optionResult.'</b></td>
816
                            <td>&nbsp;</td>
817
                            <td>&nbsp;</td>
818
                        </tr>
819
                        </table>';
820
            }
821
            echo '</div>';
822
        }
823
        echo '</div>';
824
825
        // Survey information, needed for the PDF export.
826
        echo Display::page_subheader(get_lang('Survey')).'<br />';
827
        $table->display();
828
829
        if (isset($_GET['viewoption'])) {
830
            echo '<div class="answered-people">';
831
            echo '<h4>'.get_lang('PeopleWhoAnswered').': '
832
                .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 666. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
833
834
            if (is_numeric($_GET['value'])) {
835
                $sql_restriction = "AND value='".Database::escape_string($_GET['value'])."'";
836
            }
837
838
            $sql = "SELECT user FROM $table_survey_answer
839
                    WHERE
840
                        c_id = $course_id AND
841
                        option_id = '".Database::escape_string($_GET['viewoption'])."'
842
                        $sql_restriction";
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...
843
            $result = Database::query($sql);
844
            echo '<ul>';
845
            while ($row = Database::fetch_array($result, 'ASSOC')) {
846
                $user_info = api_get_user_info($row['user']);
847
                echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=userreport&survey_id='
848
                    .$surveyId.'&user='.$row['user'].'">'
849
                    .$user_info['complete_name_with_username']
850
                    .'</a></li>';
851
            }
852
            echo '</ul>';
853
            echo '</div>';
854
        }
855
    }
856
857
    /**
858
     * Display score data about a survey question.
859
     *
860
     * @param    array    Question info
861
     * @param    int    The offset of results shown
862
     */
863
    public static function display_question_report_score($survey_data, $question, $offset)
864
    {
865
        // Database table definitions
866
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
867
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
868
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
869
        $course_id = api_get_course_int_id();
870
        $surveyId = $survey_data['survey_id'];
871
872
        // Getting the options
873
        $sql = "SELECT * FROM $table_survey_question_option
874
                WHERE
875
                    c_id = $course_id AND
876
                    survey_id= $surveyId AND
877
                    question_id = '".intval($question['question_id'])."'
878
                ORDER BY sort ASC";
879
        $result = Database::query($sql);
880
        while ($row = Database::fetch_array($result)) {
881
            $options[$row['question_option_id']] = $row;
882
        }
883
884
        // Getting the answers
885
        $sql = "SELECT *, count(answer_id) as total
886
                FROM $table_survey_answer
887
                WHERE
888
                   c_id = $course_id AND
889
                   survey_id= $surveyId AND
890
                   question_id = '".Database::escape_string($question['question_id'])."'
891
                GROUP BY option_id, value";
892
        $result = Database::query($sql);
893
        $number_of_answers = 0;
894
        while ($row = Database::fetch_array($result)) {
895
            $number_of_answers += $row['total'];
896
            $data[$row['option_id']][$row['value']] = $row;
897
        }
898
899
        $chartData = [];
900
        foreach ($options as $option) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $options does not seem to be defined for all execution paths leading up to this point.
Loading history...
901
            $optionText = strip_tags($option['option_text']);
902
            $optionText = html_entity_decode($optionText);
903
            for ($i = 1; $i <= $question['max_value']; $i++) {
904
                $votes = null;
905
                if (isset($data[$option['question_option_id']][$i])) {
906
                    $votes = $data[$option['question_option_id']][$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...
907
                }
908
909
                if (empty($votes)) {
910
                    $votes = '0';
911
                }
912
                array_push(
913
                    $chartData,
914
                    [
915
                        'serie' => $optionText,
916
                        'option' => $i,
917
                        'votes' => $votes,
918
                    ]
919
                );
920
            }
921
        }
922
        echo '<div id="chartContainer" class="col-md-12">';
923
        echo self::drawChart($chartData, true);
924
        echo '</div>';
925
926
        // Displaying the table: headers
927
        echo '<table class="table">';
928
        echo '	<tr>';
929
        echo '		<th>&nbsp;</th>';
930
        echo '		<th>'.get_lang('Score').'</th>';
931
        echo '		<th>'.get_lang('AbsoluteTotal').'</th>';
932
        echo '		<th>'.get_lang('Percentage').'</th>';
933
        echo '		<th>'.get_lang('VisualRepresentation').'</th>';
934
        echo '	</tr>';
935
936
        // Displaying the table: the content
937
        foreach ($options as $key => &$value) {
938
            for ($i = 1; $i <= $question['max_value']; $i++) {
939
                $absolute_number = null;
940
                if (isset($data[$value['question_option_id']][$i])) {
941
                    $absolute_number = $data[$value['question_option_id']][$i]['total'];
942
                }
943
944
                echo '	<tr>';
945
                echo '		<td>'.$value['option_text'].'</td>';
946
                echo '		<td>'.$i.'</td>';
947
                echo '		<td><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action
948
                    .'&survey_id='.$surveyId.'&question='.Security::remove_XSS($offset)
949
                    .'&viewoption='.$value['question_option_id'].'&value='.$i.'">'.$absolute_number.'</a></td>';
950
                echo '		<td>'.round($absolute_number / $number_of_answers * 100, 2).' %</td>';
951
                echo '		<td>';
952
                $size = ($absolute_number / $number_of_answers * 100 * 2);
953
                if ($size > 0) {
954
                    echo '<div style="border:1px solid #264269; background-color:#aecaf4; height:10px; width:'.$size.'px">&nbsp;</div>';
955
                }
956
                echo '		</td>';
957
                echo '	</tr>';
958
            }
959
        }
960
        // Displaying the table: footer (totals)
961
        echo '	<tr>';
962
        echo '		<td style="border-top:1px solid black"><b>'.get_lang('Total').'</b></td>';
963
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
964
        echo '		<td style="border-top:1px solid black"><b>'.$number_of_answers.'</b></td>';
965
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
966
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
967
        echo '	</tr>';
968
        echo '</table>';
969
    }
970
971
    /**
972
     * This functions displays the complete reporting.
973
     *
974
     * @param array $survey_data
975
     * @param int   $userId
976
     * @param bool  $addActionBar
977
     * @param bool  $addFilters
978
     * @param bool  $addExtraFields
979
     *
980
     * @return string
981
     */
982
    public static function displayCompleteReport(
983
        $survey_data,
984
        $userId = 0,
985
        $addActionBar = true,
986
        $addFilters = true,
987
        $addExtraFields = true
988
    ) {
989
        // Database table definitions
990
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
991
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
992
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
993
994
        $surveyId = (int) $survey_data['survey_id'];
995
        $course_id = (int) $survey_data['c_id'];
996
997
        if (empty($surveyId) || empty($course_id)) {
998
            return '';
999
        }
1000
1001
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
1002
        $content = '';
1003
        if ($addActionBar) {
1004
            $content .= '<div class="actions">';
1005
            $content .= '<a
1006
                href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'
1007
                .Display::return_icon(
1008
                    'back.png',
1009
                    get_lang('BackTo').' '.get_lang('ReportingOverview'),
1010
                    [],
1011
                    ICON_SIZE_MEDIUM
1012
                )
1013
                .'</a>';
1014
            $content .= '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1a.submit();">'
1015
                .Display::return_icon('export_csv.png', get_lang('ExportAsCSV'), '', ICON_SIZE_MEDIUM).'</a>';
1016
            $content .= '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1b.submit();">'
1017
                .Display::return_icon('export_excel.png', get_lang('ExportAsXLS'), '', ICON_SIZE_MEDIUM).'</a>';
1018
            $content .= '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1c.submit();">'
1019
                .Display::return_icon('export_compact_csv.png', get_lang('ExportAsCompactCSV'), '', ICON_SIZE_MEDIUM).'</a>';
1020
            $content .= '</div>';
1021
1022
            // The form
1023
            $content .= '<form id="form1a" name="form1a" method="post" action="'.api_get_self(
1024
                ).'?action='.$action.'&survey_id='
1025
                .$surveyId.'&'.api_get_cidreq().'">';
1026
            $content .= '<input type="hidden" name="export_report" value="export_report">';
1027
            $content .= '<input type="hidden" name="export_format" value="csv">';
1028
            $content .= '</form>';
1029
            $content .= '<form id="form1b" name="form1b" method="post" action="'.api_get_self(
1030
                ).'?action='.$action.'&survey_id='
1031
                .$surveyId.'&'.api_get_cidreq().'">';
1032
            $content .= '<input type="hidden" name="export_report" value="export_report">';
1033
            $content .= '<input type="hidden" name="export_format" value="xls">';
1034
            $content .= '</form>';
1035
            $content .= '<form id="form1c" name="form1c" method="post" action="'.api_get_self(
1036
                ).'?action='.$action.'&survey_id='
1037
                .$surveyId.'&'.api_get_cidreq().'">';
1038
            $content .= '<input type="hidden" name="export_report" value="export_report">';
1039
            $content .= '<input type="hidden" name="export_format" value="csv-compact">';
1040
            $content .= '</form>';
1041
        }
1042
1043
        $content .= '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
1044
            .$surveyId.'&'.api_get_cidreq().'">';
1045
1046
        // The table
1047
        $content .= '<br /><table class="table table-hover table-striped data_table" border="1">';
1048
        // Getting the number of options per question
1049
        $content .= '	<tr>';
1050
        $content .= '		<th>';
1051
1052
        if ($addFilters) {
1053
            if ((isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
1054
                (isset($_POST['export_report']) && $_POST['export_report'])
1055
            ) {
1056
                $content .= '<button class="cancel"
1057
                                type="submit"
1058
                                name="reset_question_filter" value="'.get_lang('ResetQuestionFilter').'">'.
1059
                                get_lang('ResetQuestionFilter').'</button>';
1060
            }
1061
            $content .= '<button
1062
                            class = "save"
1063
                            type="submit" name="submit_question_filter" value="'.get_lang('SubmitQuestionFilter').'">'.
1064
                            get_lang('SubmitQuestionFilter').'</button>';
1065
            $content .= '</th>';
1066
        }
1067
1068
        $display_extra_user_fields = false;
1069
        if ($addExtraFields) {
1070
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
1071
                    isset($_POST['export_report']) && $_POST['export_report']) ||
1072
                !empty($_POST['fields_filter'])
1073
            ) {
1074
                // Show user fields section with a big th colspan that spans over all fields
1075
                $extra_user_fields = UserManager::get_extra_fields(
1076
                    0,
1077
                    0,
1078
                    5,
1079
                    'ASC',
1080
                    false,
1081
                    true
1082
                );
1083
                $num = count($extra_user_fields);
1084
                if ($num > 0) {
1085
                    $content .= '<th '.($num > 0 ? ' colspan="'.$num.'"' : '').'>';
1086
                    $content .= '<label>';
1087
                    if ($addFilters) {
1088
                        $content .= '<input type="checkbox" name="fields_filter" value="1" checked="checked"/> ';
1089
                    }
1090
                    $content .= get_lang('UserFields');
1091
                    $content .= '</label>';
1092
                    $content .= '</th>';
1093
                    $display_extra_user_fields = true;
1094
                }
1095
            }
1096
        }
1097
1098
        $sql = "SELECT
1099
                  q.question_id,
1100
                  q.type,
1101
                  q.survey_question,
1102
                  count(o.question_option_id) as number_of_options
1103
				FROM $table_survey_question q
1104
				LEFT JOIN $table_survey_question_option o
1105
				ON q.question_id = o.question_id AND q.c_id = o.c_id
1106
				WHERE
1107
				    survey_question NOT LIKE '%{{%' AND
1108
				    q.survey_id = '".$surveyId."' AND
1109
				    q.c_id = $course_id
1110
				GROUP BY q.question_id
1111
				ORDER BY q.sort ASC";
1112
        $result = Database::query($sql);
1113
        $questions = [];
1114
        while ($row = Database::fetch_array($result)) {
1115
            // We show the questions if
1116
            // 1. there is no question filter and the export button has not been clicked
1117
            // 2. there is a quesiton filter but the question is selected for display
1118
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
1119
                (is_array($_POST['questions_filter']) &&
1120
                in_array($row['question_id'], $_POST['questions_filter']))
1121
            ) {
1122
                // We do not show comment and pagebreak question types
1123
                if ('pagebreak' != $row['type']) {
1124
                    $content .= ' <th';
1125
                    if ($row['number_of_options'] > 0 && 'percentage' != $row['type']) {
1126
                        $content .= ' colspan="'.$row['number_of_options'].'"';
1127
                    }
1128
                    $content .= '>';
1129
                    $content .= '<label>';
1130
                    if ($addFilters) {
1131
                        $content .= '<input
1132
                                type="checkbox"
1133
                                name="questions_filter[]" value="'.$row['question_id'].'" checked="checked"/>';
1134
                    }
1135
                    $content .= $row['survey_question'];
1136
                    $content .= '</label>';
1137
                    $content .= '</th>';
1138
                }
1139
                // No column at all if it's not a question
1140
            }
1141
            $questions[$row['question_id']] = $row;
1142
        }
1143
        $content .= '	</tr>';
1144
1145
        // Getting all the questions and options
1146
        $content .= '	<tr>';
1147
        $content .= '		<th>&nbsp;</th>'; // the user column
1148
1149
        if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
1150
            isset($_POST['export_report']) && $_POST['export_report']) || !empty($_POST['fields_filter'])
1151
        ) {
1152
            if ($addExtraFields) {
1153
                // show the fields names for user fields
1154
                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...
1155
                    $content .= '<th>'.$field[3].'</th>';
1156
                }
1157
            }
1158
        }
1159
1160
        // cells with option (none for open question)
1161
        $sql = "SELECT
1162
                    sq.question_id,
1163
                    sq.survey_id,
1164
                    sq.survey_question,
1165
                    sq.display,
1166
                    sq.sort,
1167
                    sq.type,
1168
                    sqo.question_option_id,
1169
                    sqo.option_text,
1170
                    sqo.sort as option_sort
1171
				FROM $table_survey_question sq
1172
				LEFT JOIN $table_survey_question_option sqo
1173
				ON sq.question_id = sqo.question_id AND sq.c_id = sqo.c_id
1174
				WHERE
1175
				    survey_question NOT LIKE '%{{%' AND
1176
				    sq.survey_id = '".$surveyId."' AND
1177
                    sq.c_id = $course_id
1178
				ORDER BY sq.sort ASC, sqo.sort ASC";
1179
        $result = Database::query($sql);
1180
1181
        $display_percentage_header = 1;
1182
        $possible_answers = [];
1183
        // in order to display only once the cell option (and not 100 times)
1184
        while ($row = Database::fetch_array($result)) {
1185
            // We show the options if
1186
            // 1. there is no question filter and the export button has not been clicked
1187
            // 2. there is a question filter but the question is selected for display
1188
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
1189
                (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))
1190
            ) {
1191
                // we do not show comment and pagebreak question types
1192
                if ('open' == $row['type'] || 'comment' == $row['type']) {
1193
                    $content .= '<th>&nbsp;-&nbsp;</th>';
1194
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1195
                    $display_percentage_header = 1;
1196
                } elseif ($row['type'] == 'percentage' && $display_percentage_header) {
1197
                    $content .= '<th>&nbsp;%&nbsp;</th>';
1198
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1199
                    $display_percentage_header = 0;
1200
                } elseif ($row['type'] === 'percentage') {
1201
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1202
                } elseif ($row['type'] !== 'pagebreak' && $row['type'] !== 'percentage') {
1203
                    $content .= '<th>';
1204
                    $content .= $row['option_text'];
1205
                    $content .= '</th>';
1206
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1207
                    $display_percentage_header = 1;
1208
                }
1209
            }
1210
        }
1211
1212
        $content .= '	</tr>';
1213
1214
        $userCondition = '';
1215
        if (!empty($userId)) {
1216
            $userId = (int) $userId;
1217
            $userCondition = " AND user = $userId ";
1218
        }
1219
1220
        // Getting all the answers of the users
1221
        $old_user = '';
1222
        $answers_of_user = [];
1223
        $sql = "SELECT * FROM $table_survey_answer
1224
                WHERE
1225
                    c_id = $course_id AND
1226
                    survey_id = $surveyId
1227
                    $userCondition
1228
                ORDER BY answer_id, user ASC";
1229
        $result = Database::query($sql);
1230
        $i = 1;
1231
        while ($row = Database::fetch_array($result)) {
1232
            if ($old_user != $row['user'] && $old_user != '') {
1233
                $userParam = $old_user;
1234
                if ($survey_data['anonymous'] != 0) {
1235
                    $userParam = $i;
1236
                    $i++;
1237
                }
1238
                $content .= self::display_complete_report_row(
1239
                    $survey_data,
1240
                    $possible_answers,
1241
                    $answers_of_user,
1242
                    $userParam,
1243
                    $questions,
1244
                    $display_extra_user_fields
1245
                );
1246
                $answers_of_user = [];
1247
            }
1248
            if (isset($questions[$row['question_id']]) &&
1249
                'open' != $questions[$row['question_id']]['type'] &&
1250
                'comment' != $questions[$row['question_id']]['type']
1251
            ) {
1252
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1253
            } else {
1254
                $answers_of_user[$row['question_id']][0] = $row;
1255
            }
1256
            $old_user = $row['user'];
1257
        }
1258
1259
        $userParam = $old_user;
1260
        if (0 != $survey_data['anonymous']) {
1261
            $userParam = $i;
1262
            $i++;
1263
        }
1264
1265
        $content .= self::display_complete_report_row(
1266
            $survey_data,
1267
            $possible_answers,
1268
            $answers_of_user,
1269
            $userParam,
1270
            $questions,
1271
            $display_extra_user_fields
1272
        );
1273
1274
        // This is to display the last user
1275
        $content .= '</table>';
1276
        $content .= '</form>';
1277
1278
        return $content;
1279
    }
1280
1281
    /**
1282
     * Return user answers in a row.
1283
     *
1284
     * @param      $survey_data
1285
     * @param      $possible_options
1286
     * @param      $answers_of_user
1287
     * @param      $user
1288
     * @param      $questions
1289
     * @param bool $display_extra_user_fields
1290
     *
1291
     * @return string
1292
     */
1293
    public static function display_complete_report_row(
1294
        $survey_data,
1295
        $possible_options,
1296
        $answers_of_user,
1297
        $user,
1298
        $questions,
1299
        $display_extra_user_fields = false
1300
    ) {
1301
        $user = Security::remove_XSS($user);
1302
        $surveyId = (int) $survey_data['survey_id'];
1303
1304
        if (empty($surveyId)) {
1305
            return '';
1306
        }
1307
1308
        $content = '<tr>';
1309
        $url = api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq();
1310
        if ($survey_data['anonymous'] == 0) {
1311
            if (intval($user) !== 0) {
1312
                $userInfo = api_get_user_info($user);
1313
                $user_displayed = '-';
1314
                if (!empty($userInfo)) {
1315
                    $user_displayed = $userInfo['complete_name_with_username'];
1316
                }
1317
1318
                $content .= '<th>
1319
                    <a href="'.$url.'&action=userreport&user='.$user.'">'
1320
                        .$user_displayed.'
1321
                    </a>
1322
                    </th>'; // the user column
1323
            } else {
1324
                $content .= '<th>'.$user.'</th>'; // the user column
1325
            }
1326
        } else {
1327
            $content .= '<th>'.get_lang('Anonymous').' '.$user.'</th>';
1328
        }
1329
1330
        if ($display_extra_user_fields) {
1331
            // Show user fields data, if any, for this user
1332
            $user_fields_values = UserManager::get_extra_user_data(
1333
                $user,
1334
                false,
1335
                false,
1336
                false,
1337
                true
1338
            );
1339
            foreach ($user_fields_values as &$value) {
1340
                $content .= '<td align="center">'.$value.'</td>';
1341
            }
1342
        }
1343
1344
        if (is_array($possible_options)) {
1345
            foreach ($possible_options as $question_id => $possible_option) {
1346
                if ($questions[$question_id]['type'] === 'open' || $questions[$question_id]['type'] === 'comment') {
1347
                    $content .= '<td align="center">';
1348
                    if (isset($answers_of_user[$question_id]) && isset($answers_of_user[$question_id]['0'])) {
1349
                        $content .= $answers_of_user[$question_id]['0']['option_id'];
1350
                    }
1351
                    $content .= '</td>';
1352
                } else {
1353
                    foreach ($possible_option as $option_id => $value) {
1354
                        if ($questions[$question_id]['type'] === 'multiplechoiceother') {
1355
                            foreach ($answers_of_user[$question_id] as $key => $newValue) {
1356
                                $parts = ch_multiplechoiceother::decodeOptionValue($key);
1357
                                if (isset($parts[0])) {
1358
                                    $data = $answers_of_user[$question_id][$key];
1359
                                    unset($answers_of_user[$question_id][$key]);
1360
                                    $newKey = $parts[0];
1361
                                    $answers_of_user[$question_id][$newKey] = $data;
1362
                                }
1363
                            }
1364
                        }
1365
                        if ($questions[$question_id]['type'] === 'percentage') {
1366
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1367
                                $content .= "<td align='center'>";
1368
                                $content .= $answers_of_user[$question_id][$option_id]['value'];
1369
                                $content .= "</td>";
1370
                            }
1371
                        } else {
1372
                            $content .= '<td align="center">';
1373
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1374
                                if (0 != $answers_of_user[$question_id][$option_id]['value']) {
1375
                                    $content .= $answers_of_user[$question_id][$option_id]['value'];
1376
                                } else {
1377
                                    $content .= 'v';
1378
                                }
1379
                            }
1380
                        }
1381
                    }
1382
                }
1383
            }
1384
        }
1385
1386
        $content .= '</tr>';
1387
1388
        return $content;
1389
    }
1390
1391
    /**
1392
     * Quite similar to display_complete_report(), returns an HTML string
1393
     * that can be used in a csv file.
1394
     *
1395
     * @param array $survey_data The basic survey data as initially obtained by SurveyManager::get_survey()
1396
     * @param int   $user_id     The ID of the user asking for the report
1397
     * @param bool  $compact     Whether to present the long (v marks with multiple columns per question) or compact (one column per question) answers format
1398
     *
1399
     * @todo consider merging this function with display_complete_report
1400
     *
1401
     * @throws Exception
1402
     *
1403
     * @return string The contents of a csv file
1404
     *
1405
     * @author Patrick Cool <[email protected]>, Ghent University
1406
     *
1407
     * @version February 2007
1408
     */
1409
    public static function export_complete_report($survey_data, $user_id = 0, $compact = false)
1410
    {
1411
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1412
1413
        if (empty($surveyId)) {
1414
            return false;
1415
        }
1416
1417
        $course = api_get_course_info();
1418
        $course_id = $course['real_id'];
1419
1420
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1421
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1422
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1423
1424
        $translate = false;
1425
        if (api_get_configuration_value('translate_html') == true) {
1426
            $translate = true;
1427
        }
1428
1429
        // The first column
1430
        $return = ';';
1431
1432
        // Show extra fields blank space (enough for extra fields on next line)
1433
        $extra_user_fields = UserManager::get_extra_fields(
1434
            0,
1435
            0,
1436
            5,
1437
            'ASC',
1438
            false,
1439
            true
1440
        );
1441
1442
        $num = count($extra_user_fields);
1443
        $return .= str_repeat(';', $num);
1444
1445
        $sql = "SELECT
1446
                    questions.question_id,
1447
                    questions.type,
1448
                    questions.survey_question,
1449
                    count(options.question_option_id) as number_of_options
1450
				FROM $table_survey_question questions
1451
                LEFT JOIN $table_survey_question_option options
1452
				ON
1453
				  questions.question_id = options.question_id AND
1454
				  options.c_id = questions.c_id
1455
				WHERE
1456
				    survey_question NOT LIKE '%{{%' AND
1457
				    questions.type <> 'pagebreak' AND
1458
				    questions.survey_id = $surveyId AND
1459
                    questions.c_id = $course_id
1460
				GROUP BY questions.question_id
1461
				ORDER BY questions.sort ASC";
1462
1463
        $result = Database::query($sql);
1464
        while ($row = Database::fetch_array($result)) {
1465
            if ($translate) {
1466
                $row['survey_question'] = api_get_filtered_multilingual_HTML_string($row['survey_question'], $course['language']);
1467
            }
1468
            // We show the questions if
1469
            // 1. there is no question filter and the export button has not been clicked
1470
            // 2. there is a question filter but the question is selected for display
1471
            if (!(isset($_POST['submit_question_filter'])) ||
1472
                (isset($_POST['submit_question_filter']) &&
1473
                    is_array($_POST['questions_filter']) &&
1474
                    in_array($row['question_id'], $_POST['questions_filter']))
1475
            ) {
1476
                if ($row['number_of_options'] == 0 || $compact) {
1477
                    $return .= str_replace(
1478
                        "\r\n",
1479
                        '  ',
1480
                        api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1481
                    )
1482
                    .';';
1483
                } else {
1484
                    for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1485
                        $return .= str_replace(
1486
                            "\r\n",
1487
                            '  ',
1488
                            api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1489
                        )
1490
                        .';';
1491
                    }
1492
                }
1493
            }
1494
        }
1495
1496
        $return .= "\n";
1497
        // Getting all the questions and options
1498
        $return .= ';';
1499
        // Show the fields names for user fields
1500
        if (!empty($extra_user_fields)) {
1501
            foreach ($extra_user_fields as &$field) {
1502
                if ($translate) {
1503
                    $field[3] = api_get_filtered_multilingual_HTML_string($field[3], $course['language']);
1504
                }
1505
                $return .= '"'
1506
                    .str_replace(
1507
                        "\r\n",
1508
                        '  ',
1509
                        api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1510
                    )
1511
                    .'";';
1512
            }
1513
        }
1514
1515
        $sql = "SELECT DISTINCT
1516
		            survey_question.question_id,
1517
		            survey_question.survey_id,
1518
		            survey_question.survey_question,
1519
		            survey_question.display,
1520
		            survey_question.sort,
1521
		            survey_question.type,
1522
                    survey_question_option.question_option_id,
1523
                    survey_question_option.option_text,
1524
                    survey_question_option.sort as option_sort
1525
				FROM $table_survey_question survey_question
1526
				LEFT JOIN $table_survey_question_option survey_question_option
1527
				ON
1528
				    survey_question.question_id = survey_question_option.question_id AND
1529
				    survey_question_option.c_id = survey_question.c_id
1530
				WHERE
1531
				    survey_question NOT LIKE '%{{%' AND
1532
				    survey_question.type <> 'pagebreak' AND
1533
				    survey_question.survey_id = $surveyId AND
1534
				    survey_question.c_id = $course_id
1535
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1536
        $result = Database::query($sql);
1537
        $possible_answers = [];
1538
        $possible_answers_type = [];
1539
        while ($row = Database::fetch_array($result)) {
1540
            // We show the options if
1541
            // 1. there is no question filter and the export button has not been clicked
1542
            // 2. there is a question filter but the question is selected for display
1543
            if ($translate) {
1544
                $row['option_text'] = api_get_filtered_multilingual_HTML_string($row['option_text'], $course['language']);
1545
            }
1546
            if (!(isset($_POST['submit_question_filter'])) || (
1547
                is_array($_POST['questions_filter']) &&
1548
                in_array($row['question_id'], $_POST['questions_filter'])
1549
            )
1550
            ) {
1551
                $row['option_text'] = str_replace(["\r", "\n"], ['', ''], $row['option_text']);
1552
                if (!$compact) {
1553
                    $return .= api_html_entity_decode(strip_tags($row['option_text']), ENT_QUOTES).';';
1554
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1555
                } else {
1556
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['option_text'];
1557
                }
1558
                $possible_answers_type[$row['question_id']] = $row['type'];
1559
            }
1560
        }
1561
1562
        $return .= "\n";
1563
1564
        // Getting all the answers of the users
1565
        $old_user = '';
1566
        $answers_of_user = [];
1567
        $sql = "SELECT * FROM $table_survey_answer
1568
		        WHERE
1569
		          c_id = $course_id AND
1570
		          survey_id = $surveyId
1571
		          ";
1572
        if ($user_id != 0) {
1573
            $user_id = (int) $user_id;
1574
            $sql .= " AND user = $user_id ";
1575
        }
1576
        $sql .= ' ORDER BY user ASC ';
1577
1578
        $questionIdList = array_keys($possible_answers_type);
1579
        $open_question_iterator = 1;
1580
        $result = Database::query($sql);
1581
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1582
            if (!in_array($row['question_id'], $questionIdList)) {
1583
                continue;
1584
            }
1585
            if ($old_user != $row['user'] && $old_user != '') {
1586
                $return .= self::export_complete_report_row(
1587
                    $survey_data,
1588
                    $possible_answers,
1589
                    $answers_of_user,
1590
                    $old_user,
1591
                    true,
1592
                    $compact
1593
                );
1594
                $answers_of_user = [];
1595
            }
1596
1597
            if ('open' === $possible_answers_type[$row['question_id']] ||
1598
                'comment' === $possible_answers_type[$row['question_id']]
1599
            ) {
1600
                $temp_id = 'open'.$open_question_iterator;
1601
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1602
                $open_question_iterator++;
1603
            } else {
1604
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1605
            }
1606
            $old_user = $row['user'];
1607
        }
1608
1609
        // This is to display the last user
1610
        $return .= self::export_complete_report_row(
1611
            $survey_data,
1612
            $possible_answers,
1613
            $answers_of_user,
1614
            $old_user,
1615
            true,
1616
            $compact
1617
        );
1618
1619
        return $return;
1620
    }
1621
1622
    /**
1623
     * Add a line to the csv file.
1624
     *
1625
     * @param array $survey_data               Basic survey data (we're mostly interested in the 'anonymous' index)
1626
     * @param array $possible_options          Possible answers
1627
     * @param array $answers_of_user           User's answers
1628
     * @param mixed $user                      User ID or user details as string - Used as a string in the result string
1629
     * @param bool  $display_extra_user_fields Whether to display user fields or not
1630
     * @param bool  $compact                   Whether to show answers as different column values (true) or one column per option (false, default)
1631
     *
1632
     * @return string One line of the csv file
1633
     *
1634
     * @author Patrick Cool <[email protected]>, Ghent University
1635
     *
1636
     * @version February 2007
1637
     */
1638
    public static function export_complete_report_row(
1639
        $survey_data,
1640
        $possible_options,
1641
        $answers_of_user,
1642
        $user,
1643
        $display_extra_user_fields = false,
1644
        $compact = false
1645
    ) {
1646
        $return = '';
1647
        if (0 == $survey_data['anonymous']) {
1648
            if (0 !== intval($user)) {
1649
                $userInfo = api_get_user_info($user);
1650
                if (!empty($userInfo)) {
1651
                    $user_displayed = $userInfo['complete_name_with_username'];
1652
                } else {
1653
                    $user_displayed = '-';
1654
                }
1655
                $return .= $user_displayed.';';
1656
            } else {
1657
                $return .= $user.';';
1658
            }
1659
        } else {
1660
            $return .= '-;'; // The user column
1661
        }
1662
1663
        if ($display_extra_user_fields) {
1664
            // Show user fields data, if any, for this user
1665
            $user_fields_values = UserManager::get_extra_user_data(
1666
                $user,
1667
                false,
1668
                false,
1669
                false,
1670
                true
1671
            );
1672
            foreach ($user_fields_values as &$value) {
1673
                $return .= '"'.str_replace('"', '""', api_html_entity_decode(strip_tags($value), ENT_QUOTES)).'";';
1674
            }
1675
        }
1676
1677
        // Run through possible options
1678
        if (is_array($possible_options)) {
1679
            foreach ($possible_options as $question_id => $possible_option) {
1680
                if (is_array($possible_option) && count($possible_option) > 0) {
1681
                    foreach ($possible_option as $option_id => &$value) {
1682
                        // For each option of this question, look if it matches the user's answer
1683
                        $my_answer_of_user = !isset($answers_of_user[$question_id]) || isset($answers_of_user[$question_id]) && $answers_of_user[$question_id] == null ? [] : $answers_of_user[$question_id];
1684
                        $key = array_keys($my_answer_of_user);
1685
                        if (isset($key[0]) && substr($key[0], 0, 4) === 'open') {
1686
                            // If this is an open type question (type starts by 'open'), take whatever answer is given
1687
                            $return .= '"'.
1688
                                str_replace(
1689
                                    '"',
1690
                                    '""',
1691
                                    api_html_entity_decode(
1692
                                        strip_tags(
1693
                                            $answers_of_user[$question_id][$key[0]]['option_id']
1694
                                        ),
1695
                                        ENT_QUOTES
1696
                                    )
1697
                                ).
1698
                                '";';
1699
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
1700
                            // If this is a selected option from a list...
1701
                            if ($compact) {
1702
                                // If we asked for a compact view, show only one column for the question
1703
                                // and fill it with the text of the selected option (i.e. "Yes") instead of an ID
1704
                                if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1705
                                    $return .= $answers_of_user[$question_id][$option_id]['value'].";";
1706
                                } else {
1707
                                    $return .= '"'.
1708
                                        str_replace(
1709
                                            '"',
1710
                                            '""',
1711
                                            api_html_entity_decode(
1712
                                                strip_tags(
1713
                                                    $possible_option[$option_id]
1714
                                                ),
1715
                                                ENT_QUOTES
1716
                                            )
1717
                                        ).
1718
                                        '";';
1719
                                }
1720
                            } else {
1721
                                // If we don't want a compact view, show one column per possible option and mark a 'v'
1722
                                // or the defined value in the corresponding column if the user selected it
1723
                                if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1724
                                    $return .= '"'.$answers_of_user[$question_id][$option_id]['value'].'";';
1725
                                } else {
1726
                                    $return .= 'v;';
1727
                                }
1728
                            }
1729
                        } else {
1730
                            if (!$compact) {
1731
                                $return .= ';';
1732
                            }
1733
                        }
1734
                    }
1735
                }
1736
            }
1737
        }
1738
        $return .= "\n";
1739
1740
        return $return;
1741
    }
1742
1743
    /**
1744
     * Quite similar to display_complete_report(), returns an HTML string
1745
     * that can be used in a csv file.
1746
     *
1747
     * @todo consider merging this function with display_complete_report
1748
     *
1749
     * @return string The contents of a csv file
1750
     *
1751
     * @author Patrick Cool <[email protected]>, Ghent University
1752
     *
1753
     * @version February 2007
1754
     */
1755
    public static function export_complete_report_xls($survey_data, $filename, $user_id = 0, $returnFile = false)
1756
    {
1757
        $course_id = api_get_course_int_id();
1758
        $user_id = (int) $user_id;
1759
        $surveyId = $survey_data['survey_id'];
1760
1761
        if (empty($course_id) || empty($surveyId)) {
1762
            return false;
1763
        }
1764
1765
        $spreadsheet = new PHPExcel();
1766
        $spreadsheet->setActiveSheetIndex(0);
1767
        $worksheet = $spreadsheet->getActiveSheet();
1768
        $line = 1;
1769
        $column = 1; // Skip the first column (row titles)
1770
1771
        // Show extra fields blank space (enough for extra fields on next line)
1772
        // Show user fields section with a big th colspan that spans over all fields
1773
        $extra_user_fields = UserManager::get_extra_fields(
1774
            0,
1775
            0,
1776
            5,
1777
            'ASC',
1778
            false,
1779
            true
1780
        );
1781
        $num = count($extra_user_fields);
1782
        for ($i = 0; $i < $num; $i++) {
1783
            $worksheet->setCellValueByColumnAndRow($column, $line, '');
1784
            $column++;
1785
        }
1786
1787
        $display_extra_user_fields = true;
1788
1789
        // Database table definitions
1790
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1791
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1792
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1793
1794
        // First line (questions)
1795
        $sql = "SELECT
1796
                    questions.question_id,
1797
                    questions.type,
1798
                    questions.survey_question,
1799
                    count(options.question_option_id) as number_of_options
1800
				FROM $table_survey_question questions
1801
				LEFT JOIN $table_survey_question_option options
1802
                ON
1803
                  questions.question_id = options.question_id AND
1804
                  options.c_id = questions.c_id
1805
				WHERE
1806
				    survey_question NOT LIKE '%{{%' AND
1807
				    questions.type <> 'pagebreak' AND
1808
				    questions.survey_id = $surveyId AND
1809
				    questions.c_id = $course_id
1810
				GROUP BY questions.question_id
1811
				ORDER BY questions.sort ASC";
1812
        $result = Database::query($sql);
1813
        while ($row = Database::fetch_array($result)) {
1814
            // We show the questions if
1815
            // 1. there is no question filter and the export button has not been clicked
1816
            // 2. there is a question filter but the question is selected for display
1817
            if (!(isset($_POST['submit_question_filter'])) ||
1818
                (isset($_POST['submit_question_filter']) && is_array($_POST['questions_filter']) &&
1819
                in_array($row['question_id'], $_POST['questions_filter']))
1820
            ) {
1821
                if ($row['number_of_options'] == 0 && ($row['type'] === 'open' || $row['type'] === 'comment')) {
1822
                    $worksheet->setCellValueByColumnAndRow(
1823
                        $column,
1824
                        $line,
1825
                        api_html_entity_decode(
1826
                            strip_tags($row['survey_question']),
1827
                            ENT_QUOTES
1828
                        )
1829
                    );
1830
                    $column++;
1831
                } else {
1832
                    for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1833
                        $worksheet->setCellValueByColumnAndRow(
1834
                            $column,
1835
                            $line,
1836
                            api_html_entity_decode(
1837
                                strip_tags($row['survey_question']),
1838
                                ENT_QUOTES
1839
                            )
1840
                        );
1841
                        $column++;
1842
                    }
1843
                }
1844
            }
1845
        }
1846
1847
        $line++;
1848
        $column = 1;
1849
        // Show extra field values
1850
        if ($display_extra_user_fields) {
1851
            // Show the fields names for user fields
1852
            foreach ($extra_user_fields as &$field) {
1853
                $worksheet->setCellValueByColumnAndRow(
1854
                    $column,
1855
                    $line,
1856
                    api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1857
                );
1858
                $column++;
1859
            }
1860
        }
1861
1862
        // Getting all the questions and options (second line)
1863
        $sql = "SELECT
1864
                    survey_question.question_id,
1865
                    survey_question.survey_id,
1866
                    survey_question.survey_question,
1867
                    survey_question.display,
1868
                    survey_question.sort,
1869
                    survey_question.type,
1870
                    survey_question_option.question_option_id,
1871
                    survey_question_option.option_text,
1872
                    survey_question_option.sort as option_sort
1873
				FROM $table_survey_question survey_question
1874
				LEFT JOIN $table_survey_question_option survey_question_option
1875
				ON
1876
				    survey_question.question_id = survey_question_option.question_id AND
1877
				    survey_question_option.c_id = survey_question.c_id
1878
				WHERE
1879
				    survey_question NOT LIKE '%{{%' AND
1880
				    survey_question.type <> 'pagebreak' AND
1881
				    survey_question.survey_id = $surveyId AND
1882
				    survey_question.c_id = $course_id
1883
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1884
        $result = Database::query($sql);
1885
        $possible_answers = [];
1886
        $possible_answers_type = [];
1887
        while ($row = Database::fetch_array($result)) {
1888
            // We show the options if
1889
            // 1. there is no question filter and the export button has not been clicked
1890
            // 2. there is a quesiton filter but the question is selected for display
1891
            if (!isset($_POST['submit_question_filter']) ||
1892
                (isset($_POST['questions_filter']) && is_array($_POST['questions_filter']) &&
1893
                in_array($row['question_id'], $_POST['questions_filter']))
1894
            ) {
1895
                $worksheet->setCellValueByColumnAndRow(
1896
                    $column,
1897
                    $line,
1898
                    api_html_entity_decode(
1899
                        strip_tags($row['option_text']),
1900
                        ENT_QUOTES
1901
                    )
1902
                );
1903
                $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1904
                $possible_answers_type[$row['question_id']] = $row['type'];
1905
                $column++;
1906
            }
1907
        }
1908
1909
        // Getting all the answers of the users
1910
        $line++;
1911
        $column = 0;
1912
        $old_user = '';
1913
        $answers_of_user = [];
1914
        $sql = "SELECT * FROM $table_survey_answer
1915
                WHERE c_id = $course_id AND survey_id = $surveyId";
1916
        if ($user_id != 0) {
1917
            $sql .= " AND user='".$user_id."' ";
1918
        }
1919
        $sql .= ' ORDER BY user ASC';
1920
1921
        $open_question_iterator = 1;
1922
        $result = Database::query($sql);
1923
        while ($row = Database::fetch_array($result)) {
1924
            if ($old_user != $row['user'] && $old_user != '') {
1925
                $return = self::export_complete_report_row_xls(
1926
                    $survey_data,
1927
                    $possible_answers,
1928
                    $answers_of_user,
1929
                    $old_user,
1930
                    true
1931
                );
1932
                foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
1933
                    $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
1934
                    $column++;
1935
                }
1936
                $answers_of_user = [];
1937
                $line++;
1938
                $column = 0;
1939
            }
1940
            if ($possible_answers_type[$row['question_id']] === 'open' ||
1941
                $possible_answers_type[$row['question_id']] === 'comment'
1942
            ) {
1943
                $temp_id = 'open'.$open_question_iterator;
1944
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1945
                $open_question_iterator++;
1946
            } else {
1947
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1948
            }
1949
            $old_user = $row['user'];
1950
        }
1951
1952
        $return = self::export_complete_report_row_xls(
1953
            $survey_data,
1954
            $possible_answers,
1955
            $answers_of_user,
1956
            $old_user,
1957
            true
1958
        );
1959
1960
        // this is to display the last user
1961
        foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
1962
            $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
1963
            $column++;
1964
        }
1965
1966
        $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
1967
        $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
1968
        $writer->save($file);
1969
1970
        if ($returnFile) {
1971
            return $file;
1972
        }
1973
1974
        DocumentManager::file_send_for_download($file, true, $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 string One line of the csv file
1988
     */
1989
    public static function export_complete_report_row_xls(
1990
        $survey_data,
1991
        $possible_options,
1992
        $answers_of_user,
1993
        $user,
1994
        $display_extra_user_fields = false
1995
    ) {
1996
        $return = [];
1997
        if ($survey_data['anonymous'] == 0) {
1998
            if (intval($user) !== 0) {
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 = isset($answers_of_user[$question_id])
2032
                            ? $answers_of_user[$question_id]
2033
                            : [];
2034
                        $key = array_keys($my_answers_of_user);
2035
                        if (isset($key[0]) && substr($key[0], 0, 4) == 'open') {
2036
                            $return[] = api_html_entity_decode(
2037
                                strip_tags($answers_of_user[$question_id][$key[0]]['option_id']),
2038
                                ENT_QUOTES
2039
                            );
2040
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
2041
                            if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
2042
                                $return[] = $answers_of_user[$question_id][$option_id]['value'];
2043
                            } else {
2044
                                $return[] = 'v';
2045
                            }
2046
                        } else {
2047
                            $return[] = '';
2048
                        }
2049
                    }
2050
                }
2051
            }
2052
        }
2053
2054
        return $return;
2055
    }
2056
2057
    /**
2058
     * This function displays the comparative report which
2059
     * allows you to compare two questions
2060
     * A comparative report creates a table where one question
2061
     * is on the x axis and a second question is on the y axis.
2062
     * In the intersection is the number of people who have
2063
     * answered positive on both options.
2064
     *
2065
     * @return string HTML code
2066
     *
2067
     * @author Patrick Cool <[email protected]>, Ghent University
2068
     *
2069
     * @version February 2007
2070
     */
2071
    public static function display_comparative_report()
2072
    {
2073
        // Allowed question types for comparative report
2074
        $allowed_question_types = [
2075
            'yesno',
2076
            'multiplechoice',
2077
            'multipleresponse',
2078
            'dropdown',
2079
            'percentage',
2080
            'score',
2081
        ];
2082
2083
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
2084
2085
        // Getting all the questions
2086
        $questions = SurveyManager::get_questions($surveyId);
2087
2088
        // Actions bar
2089
        echo '<div class="actions">';
2090
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq()
2091
            .'">'
2092
            .Display::return_icon(
2093
                'back.png',
2094
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
2095
                [],
2096
                ICON_SIZE_MEDIUM
2097
            )
2098
            .'</a>';
2099
        echo '</div>';
2100
2101
        // Displaying an information message that only the questions with predefined answers can be used in a comparative report
2102
        echo Display::return_message(get_lang('OnlyQuestionsWithPredefinedAnswers'), 'normal', false);
2103
2104
        $xAxis = isset($_GET['xaxis']) ? Security::remove_XSS($_GET['xaxis']) : '';
2105
        $yAxis = isset($_GET['yaxis']) ? Security::remove_XSS($_GET['yaxis']) : '';
2106
2107
        $url = api_get_self().'?'.api_get_cidreq().'&action='.Security::remove_XSS($_GET['action'])
2108
            .'&survey_id='.$surveyId.'&xaxis='.$xAxis.'&y='.$yAxis;
2109
2110
        $form = new FormValidator('compare', 'get', $url);
2111
        $form->addHidden('action', Security::remove_XSS($_GET['action']));
2112
        $form->addHidden('survey_id', $surveyId);
2113
        $optionsX = ['----'];
2114
        $optionsY = ['----'];
2115
        $defaults = [];
2116
        foreach ($questions as $key => &$question) {
2117
            // Ignored tagged questions
2118
            if ($question) {
2119
                if (strpos($question['question'], '{{') !== false) {
2120
                    $question = null;
2121
                    continue;
2122
                }
2123
            }
2124
            if (is_array($allowed_question_types)) {
2125
                if (in_array($question['type'], $allowed_question_types)) {
2126
                    if (isset($_GET['xaxis']) && $_GET['xaxis'] == $question['question_id']) {
2127
                        $defaults['xaxis'] = $question['question_id'];
2128
                    }
2129
2130
                    if (isset($_GET['yaxis']) && $_GET['yaxis'] == $question['question_id']) {
2131
                        $defaults['yaxis'] = $question['question_id'];
2132
                    }
2133
2134
                    $optionsX[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
2135
                    $optionsY[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
2136
                }
2137
            }
2138
        }
2139
2140
        $form->addSelect('xaxis', get_lang('SelectXAxis'), $optionsX);
2141
        $form->addSelect('yaxis', get_lang('SelectYAxis'), $optionsY);
2142
2143
        $form->addButtonSearch(get_lang('CompareQuestions'));
2144
        $form->setDefaults($defaults);
2145
        $form->display();
2146
2147
        // Getting all the information of the x axis
2148
        if (is_numeric($xAxis)) {
2149
            $question_x = SurveyManager::get_question($xAxis);
2150
        }
2151
2152
        // Getting all the information of the y axis
2153
        if (is_numeric($yAxis)) {
2154
            $question_y = SurveyManager::get_question($yAxis);
2155
        }
2156
2157
        if (is_numeric($xAxis) && is_numeric($yAxis)) {
2158
            // Getting the answers of the two questions
2159
            $answers_x = self::get_answers_of_question_by_user($surveyId, $xAxis);
2160
            $answers_y = self::get_answers_of_question_by_user($surveyId, $yAxis);
2161
2162
            // Displaying the table
2163
            $tableHtml = '<table border="1" class="table table-hover table-striped data_table">';
2164
            $xOptions = [];
2165
            // The header
2166
            $tableHtml .= '<tr>';
2167
            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...
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...
2168
                if ($ii == 0) {
2169
                    $tableHtml .= '<th>&nbsp;</th>';
2170
                } else {
2171
                    if ($question_x['type'] == 'score') {
2172
                        for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2173
                            $tableHtml .= '<th>'.$question_x['answers'][($ii - 1)].'<br />'.$x.'</th>';
2174
                        }
2175
                        $x = '';
2176
                    } else {
2177
                        $tableHtml .= '<th>'.$question_x['answers'][($ii - 1)].'</th>';
2178
                    }
2179
                    $optionText = strip_tags($question_x['answers'][$ii - 1]);
2180
                    $optionText = html_entity_decode($optionText);
2181
                    array_push($xOptions, trim($optionText));
2182
                }
2183
            }
2184
            $tableHtml .= '</tr>';
2185
            $chartData = [];
2186
            // The main part
2187
            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...
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...
2188
                $currentYQuestion = strip_tags($question_y['answers'][$ij]);
2189
                $currentYQuestion = html_entity_decode($currentYQuestion);
2190
                // The Y axis is a scoring question type so we have more rows than the options (actually options * maximum score)
2191
                if ($question_y['type'] == 'score') {
2192
                    for ($y = 1; $y <= $question_y['maximum_score']; $y++) {
2193
                        $tableHtml .= '<tr>';
2194
                        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...
2195
                            if ($question_x['type'] == 'score') {
2196
                                for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2197
                                    if ($ii == 0) {
2198
                                        $tableHtml .= '<th>'.$question_y['answers'][($ij)].' '.$y.'</th>';
2199
                                        break;
2200
                                    } else {
2201
                                        $tableHtml .= '<td align="center">';
2202
                                        $votes = self::comparative_check(
2203
                                            $answers_x,
2204
                                            $answers_y,
2205
                                            $question_x['answersid'][($ii - 1)],
2206
                                            $question_y['answersid'][($ij)],
2207
                                            $x,
2208
                                            $y
2209
                                        );
2210
                                        $tableHtml .= $votes;
2211
                                        array_push(
2212
                                            $chartData,
2213
                                            [
2214
                                                'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2215
                                                'option' => $x,
2216
                                                'votes' => $votes,
2217
                                            ]
2218
                                        );
2219
                                        $tableHtml .= '</td>';
2220
                                    }
2221
                                }
2222
                            } else {
2223
                                if ($ii == 0) {
2224
                                    $tableHtml .= '<th>'.$question_y['answers'][$ij].' '.$y.'</th>';
2225
                                } else {
2226
                                    $tableHtml .= '<td align="center">';
2227
                                    $votes = self::comparative_check(
2228
                                        $answers_x,
2229
                                        $answers_y,
2230
                                        $question_x['answersid'][($ii - 1)],
2231
                                        $question_y['answersid'][($ij)],
2232
                                        0,
2233
                                        $y
2234
                                    );
2235
                                    $tableHtml .= $votes;
2236
                                    array_push(
2237
                                        $chartData,
2238
                                        [
2239
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2240
                                            'option' => $y,
2241
                                            'votes' => $votes,
2242
                                        ]
2243
                                    );
2244
                                    $tableHtml .= '</td>';
2245
                                }
2246
                            }
2247
                        }
2248
                        $tableHtml .= '</tr>';
2249
                    }
2250
                } else {
2251
                    // The Y axis is NOT a score question type so the number of rows = the number of options
2252
                    $tableHtml .= '<tr>';
2253
                    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...
2254
                        if ($question_x['type'] === 'score') {
2255
                            for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2256
                                if ($ii == 0) {
2257
                                    $tableHtml .= '<th>'.$question_y['answers'][$ij].'</th>';
2258
                                    break;
2259
                                } else {
2260
                                    $tableHtml .= '<td align="center">';
2261
                                    $votes = self::comparative_check(
2262
                                        $answers_x,
2263
                                        $answers_y,
2264
                                        $question_x['answersid'][($ii - 1)],
2265
                                        $question_y['answersid'][($ij)],
2266
                                        $x,
2267
                                        0
2268
                                    );
2269
                                    $tableHtml .= $votes;
2270
                                    array_push(
2271
                                        $chartData,
2272
                                        [
2273
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2274
                                            'option' => $x,
2275
                                            'votes' => $votes,
2276
                                        ]
2277
                                    );
2278
                                    $tableHtml .= '</td>';
2279
                                }
2280
                            }
2281
                        } else {
2282
                            if ($ii == 0) {
2283
                                $tableHtml .= '<th>'.$question_y['answers'][($ij)].'</th>';
2284
                            } else {
2285
                                $tableHtml .= '<td align="center">';
2286
                                $votes = self::comparative_check(
2287
                                    $answers_x,
2288
                                    $answers_y,
2289
                                    $question_x['answersid'][($ii - 1)],
2290
                                    $question_y['answersid'][($ij)]
2291
                                );
2292
                                $tableHtml .= $votes;
2293
                                array_push(
2294
                                    $chartData,
2295
                                    [
2296
                                        'serie' => $xOptions[$ii - 1],
2297
                                        'option' => $currentYQuestion,
2298
                                        'votes' => $votes,
2299
                                    ]
2300
                                );
2301
                                $tableHtml .= '</td>';
2302
                            }
2303
                        }
2304
                    }
2305
                    $tableHtml .= '</tr>';
2306
                }
2307
            }
2308
            $tableHtml .= '</table>';
2309
            echo '<div id="chartContainer" class="col-md-12">';
2310
            echo self::drawChart($chartData, true);
2311
            echo '</div>';
2312
            echo $tableHtml;
2313
        }
2314
    }
2315
2316
    /**
2317
     * Get all the answers of a question grouped by user.
2318
     *
2319
     * @param int $survey_id   Survey ID
2320
     * @param int $question_id Question ID
2321
     *
2322
     * @return array Array containing all answers of all users, grouped by user
2323
     *
2324
     * @author Patrick Cool <[email protected]>, Ghent University
2325
     *
2326
     * @version February 2007 - Updated March 2008
2327
     */
2328
    public static function get_answers_of_question_by_user($survey_id, $question_id)
2329
    {
2330
        $course_id = api_get_course_int_id();
2331
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
2332
2333
        $sql = "SELECT * FROM $table_survey_answer
2334
                WHERE
2335
                  c_id = $course_id AND
2336
                  survey_id='".intval($survey_id)."' AND
2337
                  question_id='".intval($question_id)."'
2338
                ORDER BY USER ASC";
2339
        $result = Database::query($sql);
2340
        $return = [];
2341
        while ($row = Database::fetch_array($result)) {
2342
            if ($row['value'] == 0) {
2343
                $return[$row['user']][] = $row['option_id'];
2344
            } else {
2345
                $return[$row['user']][] = $row['option_id'].'*'.$row['value'];
2346
            }
2347
        }
2348
2349
        return $return;
2350
    }
2351
2352
    /**
2353
     * Count the number of users who answer positively on both options.
2354
     *
2355
     * @param array All answers of the x axis
2356
     * @param array All answers of the y axis
2357
     * @param int x axis value (= the option_id of the first question)
2358
     * @param int y axis value (= the option_id of the second question)
2359
     *
2360
     * @return int Number of users who have answered positively to both options
2361
     *
2362
     * @author Patrick Cool <[email protected]>, Ghent University
2363
     *
2364
     * @version February 2007
2365
     */
2366
    public static function comparative_check(
2367
        $answers_x,
2368
        $answers_y,
2369
        $option_x,
2370
        $option_y,
2371
        $value_x = 0,
2372
        $value_y = 0
2373
    ) {
2374
        if ($value_x == 0) {
2375
            $check_x = $option_x;
2376
        } else {
2377
            $check_x = $option_x.'*'.$value_x;
2378
        }
2379
        if ($value_y == 0) {
2380
            $check_y = $option_y;
2381
        } else {
2382
            $check_y = $option_y.'*'.$value_y;
2383
        }
2384
2385
        $counter = 0;
2386
        if (is_array($answers_x)) {
2387
            foreach ($answers_x as $user => &$answers) {
2388
                // Check if the user has given $option_x as answer
2389
                if (in_array($check_x, $answers)) {
2390
                    // Check if the user has given $option_y as an answer
2391
                    if (!is_null($answers_y[$user]) &&
2392
                        in_array($check_y, $answers_y[$user])
2393
                    ) {
2394
                        $counter++;
2395
                    }
2396
                }
2397
            }
2398
        }
2399
2400
        return $counter;
2401
    }
2402
2403
    public static function saveInviteMail(CSurvey $survey, $content, $subject, $remind)
2404
    {
2405
        // Reminder or not
2406
        if ($remind) {
2407
            $survey->setReminderMail($content);
2408
        } else {
2409
            $survey->setInviteMail($content);
2410
        }
2411
2412
        $survey->setMailSubject($subject);
2413
        $em = Database::getManager();
2414
        $em->persist($survey);
2415
        $em->flush();
2416
    }
2417
2418
    /**
2419
     * This function saves all the invitations of course users
2420
     * and additional users in the database
2421
     * and sends the invitations by email.
2422
     *
2423
     * @param int    $surveyId
2424
     * @param array  $users_array       Users array can be both a list of course uids AND a list of additional email addresses
2425
     * @param string $invitation_title  title of the mail
2426
     * @param string $invitation_text   text of the mail has to contain a **link** string or
2427
     *                                  this will automatically be added to the end
2428
     * @param int    $reminder
2429
     * @param bool   $sendmail
2430
     * @param int    $remindUnAnswered
2431
     * @param bool   $isAdditionalEmail
2432
     * @param bool   $hideLink
2433
     *
2434
     * @author Patrick Cool <[email protected]>, Ghent University
2435
     * @author Julio Montoya - Adding auto-generated link support
2436
     *
2437
     * @version January 2007
2438
     */
2439
    public static function saveInvitations(
2440
        $surveyId,
2441
        $users_array,
2442
        $invitation_title,
2443
        $invitation_text,
2444
        $reminder = 0,
2445
        $sendmail = false,
2446
        $remindUnAnswered = 0,
2447
        $isAdditionalEmail = false,
2448
        $hideLink = false
2449
    ) {
2450
        $surveyId = (int) $surveyId;
2451
        if (!is_array($users_array)) {
2452
            return 0;
2453
        }
2454
2455
        // Getting the survey information
2456
        $survey_data = SurveyManager::get_survey($surveyId);
2457
        $survey_invitations = self::get_invitations($survey_data['survey_code']);
2458
        $already_invited = self::get_invited_users($survey_data['code']);
2459
2460
        // Remind unanswered is a special version of remind all reminder
2461
        $exclude_users = [];
2462
        if (1 == $remindUnAnswered) {
2463
            // Remind only unanswered users
2464
            $reminder = 1;
2465
            $exclude_users = SurveyManager::get_people_who_filled_survey($surveyId);
2466
        }
2467
2468
        $counter = 0; // Nr of invitations "sent" (if sendmail option)
2469
        $course_id = api_get_course_int_id();
2470
        $session_id = api_get_session_id();
2471
2472
        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...
2473
            $result = CourseManager::separateUsersGroups($users_array);
2474
            $groupList = $result['groups'];
2475
            $users_array = $result['users'];
2476
2477
            foreach ($groupList as $groupId) {
2478
                $userGroupList = GroupManager::getStudents($groupId, true);
2479
                $userGroupIdList = array_column($userGroupList, 'user_id');
2480
                $users_array = array_merge($users_array, $userGroupIdList);
2481
2482
                $params = [
2483
                    'c_id' => $course_id,
2484
                    'session_id' => $session_id,
2485
                    'group_id' => $groupId,
2486
                    'survey_code' => $survey_data['code'],
2487
                ];
2488
2489
                $invitationExists = self::invitationExists(
2490
                    $course_id,
2491
                    $session_id,
2492
                    $groupId,
2493
                    $survey_data['code']
2494
                );
2495
                if (empty($invitationExists)) {
2496
                    self::save_invitation($params);
2497
                }
2498
            }
2499
        }
2500
2501
        $users_array = array_unique($users_array);
2502
        foreach ($users_array as $key => $value) {
2503
            if (!isset($value) || '' == $value) {
2504
                continue;
2505
            }
2506
2507
            // Skip user if reminding only unanswered people
2508
            if (in_array($value, $exclude_users)) {
2509
                continue;
2510
            }
2511
            // Get the unique invitation code if we already have it
2512
            if ($reminder == 1 && array_key_exists($value, $survey_invitations)) {
2513
                $invitation_code = $survey_invitations[$value]['invitation_code'];
2514
            } else {
2515
                $invitation_code = md5($value.microtime());
2516
            }
2517
            $new_user = false; // User not already invited
2518
            // Store the invitation if user_id not in $already_invited['course_users'] OR email is not in $already_invited['additional_users']
2519
            $addit_users_array = isset($already_invited['additional_users']) && !empty($already_invited['additional_users'])
2520
                    ? explode(';', $already_invited['additional_users'])
2521
                    : [];
2522
            $my_alredy_invited = $already_invited['course_users'] == null ? [] : $already_invited['course_users'];
2523
            if ((is_numeric($value) && !in_array($value, $my_alredy_invited)) ||
2524
                (!is_numeric($value) && !in_array($value, $addit_users_array))
2525
            ) {
2526
                $new_user = true;
2527
                if (!array_key_exists($value, $survey_invitations)) {
2528
                    $params = [
2529
                        'c_id' => $course_id,
2530
                        'session_id' => $session_id,
2531
                        'user' => $value,
2532
                        'survey_code' => $survey_data['code'],
2533
                        'invitation_code' => $invitation_code,
2534
                        'invitation_date' => api_get_utc_datetime(),
2535
                    ];
2536
                    self::save_invitation($params);
2537
                }
2538
            }
2539
2540
            // Send the email if checkboxed
2541
            if (($new_user || $reminder == 1) && $sendmail) {
2542
                // Make a change for absolute url
2543
                if (isset($invitation_text)) {
2544
                    $invitation_text = api_html_entity_decode($invitation_text, ENT_QUOTES);
2545
                    $invitation_text = str_replace('src="../../', 'src="'.api_get_path(WEB_PATH), $invitation_text);
2546
                    $invitation_text = trim(stripslashes($invitation_text));
2547
                }
2548
                self::send_invitation_mail(
2549
                    $value,
2550
                    $invitation_code,
2551
                    $invitation_title,
2552
                    $invitation_text,
2553
                    $hideLink
2554
                );
2555
                $counter++;
2556
            }
2557
        }
2558
2559
        return $counter; // Number of invitations sent
2560
    }
2561
2562
    /**
2563
     * @param $params
2564
     *
2565
     * @return bool|int
2566
     */
2567
    public static function save_invitation($params)
2568
    {
2569
        // Database table to store the invitations data
2570
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2571
        if (!empty($params['c_id']) &&
2572
            (!empty($params['user']) || !empty($params['group_id'])) &&
2573
            !empty($params['survey_code'])
2574
        ) {
2575
            if (!isset($params['survey_invitation_id'])) {
2576
                $params['survey_invitation_id'] = 0;
2577
            }
2578
            if (!isset($params['answered'])) {
2579
                $params['answered'] = 0;
2580
            }
2581
            if (!isset($params['group_id'])) {
2582
                $params['group_id'] = 0;
2583
            }
2584
            $insertId = Database::insert($table, $params);
2585
            if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false 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...
2586
                $sql = "UPDATE $table
2587
                        SET survey_invitation_id = $insertId
2588
                        WHERE iid = $insertId";
2589
                Database::query($sql);
2590
            }
2591
2592
            return $insertId;
2593
        }
2594
2595
        return false;
2596
    }
2597
2598
    /**
2599
     * @param int    $courseId
2600
     * @param int    $sessionId
2601
     * @param int    $groupId
2602
     * @param string $surveyCode
2603
     *
2604
     * @return int
2605
     */
2606
    public static function invitationExists($courseId, $sessionId, $groupId, $surveyCode)
2607
    {
2608
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2609
        $courseId = (int) $courseId;
2610
        $sessionId = (int) $sessionId;
2611
        $groupId = (int) $groupId;
2612
        $surveyCode = Database::escape_string($surveyCode);
2613
2614
        $sql = "SELECT survey_invitation_id FROM $table
2615
                WHERE
2616
                    c_id = $courseId AND
2617
                    session_id = $sessionId AND
2618
                    group_id = $groupId AND
2619
                    survey_code = '$surveyCode'
2620
                ";
2621
        $result = Database::query($sql);
2622
2623
        return Database::num_rows($result);
2624
    }
2625
2626
    /**
2627
     * Send the invitation by mail.
2628
     *
2629
     * @param int invitedUser - the userId (course user) or emailaddress of additional user
2630
     * $param string $invitation_code - the unique invitation code for the URL
2631
     */
2632
    public static function send_invitation_mail(
2633
        $invitedUser,
2634
        $invitation_code,
2635
        $invitation_title,
2636
        $invitation_text,
2637
        $hideLink = false
2638
    ) {
2639
        $_user = api_get_user_info();
2640
        $_course = api_get_course_info();
2641
        $sessionId = api_get_session_id();
2642
2643
        // Replacing the **link** part with a valid link for the user
2644
        $link = self::generateFillSurveyLink($invitation_code, $_course, $sessionId);
2645
        if ($hideLink) {
2646
            $full_invitation_text = str_replace('**link**', '', $invitation_text);
2647
        } else {
2648
            $text_link = '<a href="'.$link.'">'.get_lang('ClickHereToAnswerTheSurvey')."</a><br />\r\n<br />\r\n"
2649
                .get_lang('OrCopyPasteTheFollowingUrl')." <br /> \r\n <br /> \r\n ".$link;
2650
2651
            $replace_count = 0;
2652
            $full_invitation_text = api_str_ireplace('**link**', $text_link, $invitation_text, $replace_count);
2653
            if ($replace_count < 1) {
2654
                $full_invitation_text = $full_invitation_text."<br />\r\n<br />\r\n".$text_link;
2655
            }
2656
        }
2657
2658
        // Sending the mail
2659
        $sender_name = api_get_person_name($_user['firstName'], $_user['lastName'], null, PERSON_NAME_EMAIL_ADDRESS);
2660
        $sender_email = $_user['mail'];
2661
        $sender_user_id = api_get_user_id();
2662
2663
        $replyto = [];
2664
        if (api_get_setting('survey_email_sender_noreply') == 'noreply') {
2665
            $noreply = api_get_setting('noreply_email_address');
2666
            if (!empty($noreply)) {
2667
                $replyto['Reply-to'] = $noreply;
2668
                $sender_name = $noreply;
2669
                $sender_email = $noreply;
2670
                $sender_user_id = null;
2671
            }
2672
        }
2673
2674
        // Optionally: finding the e-mail of the course user
2675
        if (is_numeric($invitedUser)) {
2676
            MessageManager::send_message(
2677
                $invitedUser,
2678
                $invitation_title,
2679
                $full_invitation_text,
2680
                [],
2681
                [],
2682
                null,
2683
                null,
2684
                null,
2685
                null,
2686
                $sender_user_id,
2687
                true
2688
            );
2689
        } else {
2690
            @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

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