Passed
Push — 1.11.x ( ce2278...d12871 )
by Julito
12:34
created

SurveyUtil::save_invite_mail()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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

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