Passed
Push — 1.11.x ( b9f532...7c1129 )
by Yannick
08:36
created

SurveyUtil   F

Complexity

Total Complexity 629

Size/Duplication

Total Lines 4605
Duplicated Lines 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
wmc 629
eloc 2572
c 3
b 2
f 0
dl 0
loc 4605
rs 0.8

52 Methods

Rating   Name   Duplication   Size   Complexity  
B check_first_last_question() 0 30 8
C check_parameters() 0 62 15
B store_answer() 0 67 8
A remove_answer() 0 26 3
B displayUserReportForm() 0 42 7
C displayUserReportAnswers() 0 118 17
B displayUserReport() 0 60 8
C handle_reporting_actions() 0 52 13
B delete_user_report() 0 48 6
C addSelectLpItemsForm() 0 69 13
A invitationExists() 0 18 1
A isSurveyAnsweredFlagged() 0 22 5
F make_field_list() 0 143 27
A display_survey_list_for_coach() 0 40 3
A saveInviteMail() 0 13 2
F saveInvitations() 0 121 24
B get_answers_of_question_by_user() 0 38 7
F display_comparative_report() 0 251 36
B drawChart() 0 75 9
F display_question_report() 0 319 49
A generateFillSurveyLink() 0 24 4
F display_question_report_score() 0 122 15
B save_invitation() 0 29 9
B comparative_check() 0 35 8
A getSentInvitations() 0 21 1
A checkIfSurveyHasAnswers() 0 27 4
F get_survey_data() 0 148 18
A modify_filter_for_coach() 0 26 1
B send_invitation_mail() 0 75 7
A displaySurveyListForDrh() 0 35 2
A checkHideEditionToolsByCode() 0 17 4
A get_number_of_surveys() 0 21 2
B get_survey_data_for_coach() 0 79 9
C getSurveyList() 0 123 12
D get_invited_users() 0 69 13
A getAdditionalTeacherActions() 0 17 4
A anonymous_filter() 0 6 2
B display_survey_list() 0 77 4
A display_survey_search_form() 0 11 1
F displayCompleteReport() 0 342 62
A flagSurveyAsAnswered() 0 10 2
A get_number_of_surveys_for_coach() 0 5 1
D display_complete_report_row() 0 99 23
A get_invitations() 0 19 2
A survey_search_restriction() 0 18 6
F modify_filter() 0 137 17
A getUserPendingInvitations() 0 22 1
A update_count_invited() 0 38 3
D export_complete_report_row() 0 124 30
F export_complete_report_xls() 0 272 39
F export_complete_report() 0 252 39
D export_complete_report_row_xls() 0 85 23

How to fix   Complexity   

Complex Class

Complex classes like SurveyUtil often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SurveyUtil, and based on these observations, apply Extract Interface, too.

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

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

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

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
Comprehensibility Best Practice introduced by
The variable $question_x does not seem to be defined for all execution paths leading up to this point.
Loading history...
2559
                if ($ii == 0) {
2560
                    $tableHtml .= '<th>&nbsp;</th>';
2561
                } else {
2562
                    if ($question_x['type'] === 'score') {
2563
                        for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2564
                            $tableHtml .= '<th>'.Security::remove_XSS($question_x['answers'][($ii - 1)]).'<br />'.$x.'</th>';
2565
                        }
2566
                        $x = '';
2567
                    } else {
2568
                        $tableHtml .= '<th>'.Security::remove_XSS($question_x['answers'][($ii - 1)]).'</th>';
2569
                    }
2570
                    $optionText = strip_tags($question_x['answers'][$ii - 1]);
2571
                    $optionText = html_entity_decode($optionText);
2572
                    $optionText = Security::remove_XSS($optionText);
2573
                    array_push($xOptions, trim($optionText));
2574
                }
2575
            }
2576
            $tableHtml .= '</tr>';
2577
            $chartData = [];
2578
            // The main part
2579
            for ($ij = 0; $ij < count($question_y['answers']); $ij++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

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

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

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
Comprehensibility Best Practice introduced by
The variable $question_y does not seem to be defined for all execution paths leading up to this point.
Loading history...
2580
                $currentYQuestion = strip_tags($question_y['answers'][$ij]);
2581
                $currentYQuestion = html_entity_decode($currentYQuestion);
2582
                // The Y axis is a scoring question type so we have more rows than the options (actually options * maximum score)
2583
                if ($question_y['type'] == 'score') {
2584
                    for ($y = 1; $y <= $question_y['maximum_score']; $y++) {
2585
                        $tableHtml .= '<tr>';
2586
                        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...
2587
                            if ($question_x['type'] == 'score') {
2588
                                for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2589
                                    if ($ii == 0) {
2590
                                        $tableHtml .= '<th>'.Security::remove_XSS($question_y['answers'][($ij)]).' '.$y.'</th>';
2591
                                        break;
2592
                                    } else {
2593
                                        $tableHtml .= '<td align="center">';
2594
                                        $votes = self::comparative_check(
2595
                                            $answers_x,
2596
                                            $answers_y,
2597
                                            $question_x['answersid'][($ii - 1)],
2598
                                            $question_y['answersid'][($ij)],
2599
                                            $x,
2600
                                            $y
2601
                                        );
2602
                                        $tableHtml .= $votes;
2603
                                        array_push(
2604
                                            $chartData,
2605
                                            [
2606
                                                'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2607
                                                'option' => $x,
2608
                                                'votes' => $votes,
2609
                                            ]
2610
                                        );
2611
                                        $tableHtml .= '</td>';
2612
                                    }
2613
                                }
2614
                            } else {
2615
                                if ($ii == 0) {
2616
                                    $tableHtml .= '<th>'.Security::remove_XSS($question_y['answers'][$ij]).' '.$y.'</th>';
2617
                                } else {
2618
                                    $tableHtml .= '<td align="center">';
2619
                                    $votes = self::comparative_check(
2620
                                        $answers_x,
2621
                                        $answers_y,
2622
                                        $question_x['answersid'][($ii - 1)],
2623
                                        $question_y['answersid'][($ij)],
2624
                                        0,
2625
                                        $y
2626
                                    );
2627
                                    $tableHtml .= $votes;
2628
                                    array_push(
2629
                                        $chartData,
2630
                                        [
2631
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2632
                                            'option' => $y,
2633
                                            'votes' => $votes,
2634
                                        ]
2635
                                    );
2636
                                    $tableHtml .= '</td>';
2637
                                }
2638
                            }
2639
                        }
2640
                        $tableHtml .= '</tr>';
2641
                    }
2642
                } else {
2643
                    // The Y axis is NOT a score question type so the number of rows = the number of options
2644
                    $tableHtml .= '<tr>';
2645
                    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...
2646
                        if ($question_x['type'] === 'score') {
2647
                            for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2648
                                if ($ii == 0) {
2649
                                    $tableHtml .= '<th>'.Security::remove_XSS($question_y['answers'][$ij]).'</th>';
2650
                                    break;
2651
                                } else {
2652
                                    $tableHtml .= '<td align="center">';
2653
                                    $votes = self::comparative_check(
2654
                                        $answers_x,
2655
                                        $answers_y,
2656
                                        $question_x['answersid'][($ii - 1)],
2657
                                        $question_y['answersid'][($ij)],
2658
                                        $x,
2659
                                        0
2660
                                    );
2661
                                    $tableHtml .= $votes;
2662
                                    array_push(
2663
                                        $chartData,
2664
                                        [
2665
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2666
                                            'option' => $x,
2667
                                            'votes' => $votes,
2668
                                        ]
2669
                                    );
2670
                                    $tableHtml .= '</td>';
2671
                                }
2672
                            }
2673
                        } else {
2674
                            if ($ii == 0) {
2675
                                $tableHtml .= '<th>'.Security::remove_XSS($question_y['answers'][($ij)]).'</th>';
2676
                            } else {
2677
                                $tableHtml .= '<td align="center">';
2678
                                $votes = self::comparative_check(
2679
                                    $answers_x,
2680
                                    $answers_y,
2681
                                    $question_x['answersid'][($ii - 1)],
2682
                                    $question_y['answersid'][($ij)]
2683
                                );
2684
                                $tableHtml .= $votes;
2685
                                array_push(
2686
                                    $chartData,
2687
                                    [
2688
                                        'serie' => $xOptions[$ii - 1],
2689
                                        'option' => $currentYQuestion,
2690
                                        'votes' => $votes,
2691
                                    ]
2692
                                );
2693
                                $tableHtml .= '</td>';
2694
                            }
2695
                        }
2696
                    }
2697
                    $tableHtml .= '</tr>';
2698
                }
2699
            }
2700
            $tableHtml .= '</table>';
2701
            echo '<div id="chartContainer" class="col-md-12">';
2702
            echo self::drawChart($chartData, true);
2703
            echo '</div>';
2704
            echo $tableHtml;
2705
        }
2706
    }
2707
2708
    /**
2709
     * Get all the answers of a question grouped by user.
2710
     *
2711
     * @param int $survey_id   Survey ID
2712
     * @param int $question_id Question ID
2713
     *
2714
     * @return array Array containing all answers of all users, grouped by user
2715
     *
2716
     * @author Patrick Cool <[email protected]>, Ghent University
2717
     *
2718
     * @version February 2007 - Updated March 2008
2719
     */
2720
    public static function get_answers_of_question_by_user($survey_id, $question_id, $lpItemId = 0)
2721
    {
2722
        $course_id = api_get_course_int_id();
2723
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
2724
        $sessionId = api_get_session_id();
2725
2726
        // To select the answers by session
2727
        $sessionCondition = '';
2728
        if (api_get_configuration_value('show_surveys_base_in_sessions')) {
2729
            if (!empty($sessionId)) {
2730
                $sessionCondition = api_get_session_condition($sessionId);
2731
            }
2732
        }
2733
        // To select the answers by Lp item
2734
        $lpItemCondition = '';
2735
        if (api_get_configuration_value('allow_survey_tool_in_lp') && !empty($lpItemId)) {
2736
            $lpItemCondition = " AND c_lp_item_id = $lpItemId";
2737
        }
2738
2739
        $sql = "SELECT * FROM $table_survey_answer
2740
                WHERE
2741
                  c_id = $course_id AND
2742
                  survey_id='".intval($survey_id)."' AND
2743
                  question_id='".intval($question_id)."'
2744
                  $sessionCondition
2745
                  $lpItemCondition
2746
                ORDER BY USER ASC";
2747
        $result = Database::query($sql);
2748
        $return = [];
2749
        while ($row = Database::fetch_array($result)) {
2750
            if ($row['value'] == 0) {
2751
                $return[$row['user']][] = $row['option_id'];
2752
            } else {
2753
                $return[$row['user']][] = $row['option_id'].'*'.$row['value'];
2754
            }
2755
        }
2756
2757
        return $return;
2758
    }
2759
2760
    /**
2761
     * Count the number of users who answer positively on both options.
2762
     *
2763
     * @param array All answers of the x axis
2764
     * @param array All answers of the y axis
2765
     * @param int x axis value (= the option_id of the first question)
2766
     * @param int y axis value (= the option_id of the second question)
2767
     *
2768
     * @return int Number of users who have answered positively to both options
2769
     *
2770
     * @author Patrick Cool <[email protected]>, Ghent University
2771
     *
2772
     * @version February 2007
2773
     */
2774
    public static function comparative_check(
2775
        $answers_x,
2776
        $answers_y,
2777
        $option_x,
2778
        $option_y,
2779
        $value_x = 0,
2780
        $value_y = 0
2781
    ) {
2782
        if ($value_x == 0) {
2783
            $check_x = $option_x;
2784
        } else {
2785
            $check_x = $option_x.'*'.$value_x;
2786
        }
2787
        if ($value_y == 0) {
2788
            $check_y = $option_y;
2789
        } else {
2790
            $check_y = $option_y.'*'.$value_y;
2791
        }
2792
2793
        $counter = 0;
2794
        if (is_array($answers_x)) {
2795
            foreach ($answers_x as $user => &$answers) {
2796
                // Check if the user has given $option_x as answer
2797
                if (in_array($check_x, $answers)) {
2798
                    // Check if the user has given $option_y as an answer
2799
                    if (!is_null($answers_y[$user]) &&
2800
                        in_array($check_y, $answers_y[$user])
2801
                    ) {
2802
                        $counter++;
2803
                    }
2804
                }
2805
            }
2806
        }
2807
2808
        return $counter;
2809
    }
2810
2811
    public static function saveInviteMail(CSurvey $survey, $content, $subject, $remind)
2812
    {
2813
        // Reminder or not
2814
        if ($remind) {
2815
            $survey->setReminderMail($content);
2816
        } else {
2817
            $survey->setInviteMail($content);
2818
        }
2819
2820
        $survey->setMailSubject($subject);
2821
        $em = Database::getManager();
2822
        $em->persist($survey);
2823
        $em->flush();
2824
    }
2825
2826
    /**
2827
     * This function saves all the invitations of course users
2828
     * and additional users in the database
2829
     * and sends the invitations by email.
2830
     *
2831
     * @param int    $surveyId
2832
     * @param array  $users_array       Users array can be both a list of course uids AND a list of additional email addresses
2833
     * @param string $invitation_title  title of the mail
2834
     * @param string $invitation_text   text of the mail has to contain a **link** string or
2835
     *                                  this will automatically be added to the end
2836
     * @param int    $reminder
2837
     * @param bool   $sendmail
2838
     * @param int    $remindUnAnswered
2839
     * @param bool   $isAdditionalEmail
2840
     * @param bool   $hideLink
2841
     *
2842
     * @author Patrick Cool <[email protected]>, Ghent University
2843
     * @author Julio Montoya - Adding auto-generated link support
2844
     *
2845
     * @version January 2007
2846
     */
2847
    public static function saveInvitations(
2848
        $surveyId,
2849
        $users_array,
2850
        $invitation_title,
2851
        $invitation_text,
2852
        $reminder = 0,
2853
        $sendmail = false,
2854
        $remindUnAnswered = 0,
2855
        $isAdditionalEmail = false,
2856
        $hideLink = false
2857
    ) {
2858
        $surveyId = (int) $surveyId;
2859
        if (!is_array($users_array)) {
2860
            return 0;
2861
        }
2862
2863
        // Getting the survey information
2864
        $survey_data = SurveyManager::get_survey($surveyId);
2865
        $survey_invitations = self::get_invitations($survey_data['survey_code']);
2866
        $already_invited = self::get_invited_users($survey_data['code']);
2867
2868
        // Remind unanswered is a special version of remind all reminder
2869
        $exclude_users = [];
2870
        if (1 == $remindUnAnswered) {
2871
            // Remind only unanswered users
2872
            $reminder = 1;
2873
            $exclude_users = SurveyManager::get_people_who_filled_survey($surveyId);
2874
        }
2875
2876
        $counter = 0; // Nr of invitations "sent" (if sendmail option)
2877
        $course_id = api_get_course_int_id();
2878
        $session_id = api_get_session_id();
2879
2880
        if (false == $isAdditionalEmail) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

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

Loading history...
2881
            $result = CourseManager::separateUsersGroups($users_array);
2882
            $groupList = $result['groups'];
2883
            $users_array = $result['users'];
2884
2885
            foreach ($groupList as $groupId) {
2886
                $userGroupList = GroupManager::getStudents($groupId, true);
2887
                $userGroupIdList = array_column($userGroupList, 'user_id');
2888
                $users_array = array_merge($users_array, $userGroupIdList);
2889
2890
                $params = [
2891
                    'c_id' => $course_id,
2892
                    'session_id' => $session_id,
2893
                    'group_id' => $groupId,
2894
                    'survey_code' => $survey_data['code'],
2895
                ];
2896
2897
                $invitationExists = self::invitationExists(
2898
                    $course_id,
2899
                    $session_id,
2900
                    $groupId,
2901
                    $survey_data['code']
2902
                );
2903
                if (empty($invitationExists)) {
2904
                    self::save_invitation($params);
2905
                }
2906
            }
2907
        }
2908
2909
        $users_array = array_unique($users_array);
2910
        foreach ($users_array as $key => $value) {
2911
            if (!isset($value) || '' == $value) {
2912
                continue;
2913
            }
2914
2915
            // Skip user if reminding only unanswered people
2916
            if (in_array($value, $exclude_users)) {
2917
                continue;
2918
            }
2919
            // Get the unique invitation code if we already have it
2920
            if ($reminder == 1 && array_key_exists($value, $survey_invitations)) {
2921
                $invitation_code = $survey_invitations[$value]['invitation_code'];
2922
            } else {
2923
                $invitation_code = md5($value.microtime());
2924
            }
2925
            $new_user = false; // User not already invited
2926
            // Store the invitation if user_id not in $already_invited['course_users'] OR email is not in $already_invited['additional_users']
2927
            $addit_users_array = isset($already_invited['additional_users']) && !empty($already_invited['additional_users'])
2928
                    ? explode(';', $already_invited['additional_users'])
2929
                    : [];
2930
            $my_alredy_invited = $already_invited['course_users'] == null ? [] : $already_invited['course_users'];
2931
            if ((is_numeric($value) && !in_array($value, $my_alredy_invited)) ||
2932
                (!is_numeric($value) && !in_array($value, $addit_users_array))
2933
            ) {
2934
                $new_user = true;
2935
                if (!array_key_exists($value, $survey_invitations)) {
2936
                    $params = [
2937
                        'c_id' => $course_id,
2938
                        'session_id' => $session_id,
2939
                        'user' => $value,
2940
                        'survey_code' => $survey_data['code'],
2941
                        'invitation_code' => $invitation_code,
2942
                        'invitation_date' => api_get_utc_datetime(),
2943
                    ];
2944
                    self::save_invitation($params);
2945
                }
2946
            }
2947
2948
            // Send the email if checkboxed
2949
            if (($new_user || $reminder == 1) && $sendmail) {
2950
                // Make a change for absolute url
2951
                if (isset($invitation_text)) {
2952
                    $invitation_text = api_html_entity_decode($invitation_text, ENT_QUOTES);
2953
                    $invitation_text = str_replace('src="../../', 'src="'.api_get_path(WEB_PATH), $invitation_text);
2954
                    $invitation_text = trim(stripslashes($invitation_text));
2955
                }
2956
                self::send_invitation_mail(
2957
                    $value,
2958
                    $invitation_code,
2959
                    $invitation_title,
2960
                    $invitation_text,
2961
                    $hideLink
2962
                );
2963
                $counter++;
2964
            }
2965
        }
2966
2967
        return $counter; // Number of invitations sent
2968
    }
2969
2970
    /**
2971
     * @param $params
2972
     *
2973
     * @return bool|int
2974
     */
2975
    public static function save_invitation($params)
2976
    {
2977
        // Database table to store the invitations data
2978
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2979
        if (!empty($params['c_id']) &&
2980
            (!empty($params['user']) || !empty($params['group_id'])) &&
2981
            !empty($params['survey_code'])
2982
        ) {
2983
            if (!isset($params['survey_invitation_id'])) {
2984
                $params['survey_invitation_id'] = 0;
2985
            }
2986
            if (!isset($params['answered'])) {
2987
                $params['answered'] = 0;
2988
            }
2989
            if (!isset($params['group_id'])) {
2990
                $params['group_id'] = 0;
2991
            }
2992
            $insertId = Database::insert($table, $params);
2993
            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...
2994
                $sql = "UPDATE $table
2995
                        SET survey_invitation_id = $insertId
2996
                        WHERE iid = $insertId";
2997
                Database::query($sql);
2998
            }
2999
3000
            return $insertId;
3001
        }
3002
3003
        return false;
3004
    }
3005
3006
    /**
3007
     * @param int    $courseId
3008
     * @param int    $sessionId
3009
     * @param int    $groupId
3010
     * @param string $surveyCode
3011
     *
3012
     * @return int
3013
     */
3014
    public static function invitationExists($courseId, $sessionId, $groupId, $surveyCode)
3015
    {
3016
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
3017
        $courseId = (int) $courseId;
3018
        $sessionId = (int) $sessionId;
3019
        $groupId = (int) $groupId;
3020
        $surveyCode = Database::escape_string($surveyCode);
3021
3022
        $sql = "SELECT survey_invitation_id FROM $table
3023
                WHERE
3024
                    c_id = $courseId AND
3025
                    session_id = $sessionId AND
3026
                    group_id = $groupId AND
3027
                    survey_code = '$surveyCode'
3028
                ";
3029
        $result = Database::query($sql);
3030
3031
        return Database::num_rows($result);
3032
    }
3033
3034
    /**
3035
     * Send the invitation by mail.
3036
     *
3037
     * @param int invitedUser - the userId (course user) or emailaddress of additional user
3038
     * $param string $invitation_code - the unique invitation code for the URL
3039
     */
3040
    public static function send_invitation_mail(
3041
        $invitedUser,
3042
        $invitation_code,
3043
        $invitation_title,
3044
        $invitation_text,
3045
        $hideLink = false
3046
    ) {
3047
        $_user = api_get_user_info();
3048
        $_course = api_get_course_info();
3049
        $sessionId = api_get_session_id();
3050
3051
        // Replacing the **link** part with a valid link for the user
3052
        $link = self::generateFillSurveyLink($invitation_code, $_course, $sessionId);
3053
        if ($hideLink) {
3054
            $full_invitation_text = str_replace('**link**', '', $invitation_text);
3055
        } else {
3056
            $text_link = '<a href="'.$link.'">'.get_lang('ClickHereToAnswerTheSurvey')."</a><br />\r\n<br />\r\n"
3057
                .get_lang('OrCopyPasteTheFollowingUrl')." <br /> \r\n <br /> \r\n ".$link;
3058
3059
            $replace_count = 0;
3060
            $full_invitation_text = api_str_ireplace('**link**', $text_link, $invitation_text, $replace_count);
3061
            if ($replace_count < 1) {
3062
                $full_invitation_text = $full_invitation_text."<br />\r\n<br />\r\n".$text_link;
3063
            }
3064
        }
3065
3066
        // Sending the mail
3067
        $sender_name = api_get_person_name($_user['firstName'], $_user['lastName'], null, PERSON_NAME_EMAIL_ADDRESS);
3068
        $sender_email = $_user['mail'];
3069
        $sender_user_id = api_get_user_id();
3070
3071
        $replyto = [];
3072
        if (api_get_setting('survey_email_sender_noreply') == 'noreply') {
3073
            $noreply = api_get_setting('noreply_email_address');
3074
            if (!empty($noreply)) {
3075
                $replyto['Reply-to'] = $noreply;
3076
                $sender_name = $noreply;
3077
                $sender_email = $noreply;
3078
                $sender_user_id = null;
3079
            }
3080
        }
3081
3082
        // Optionally: finding the e-mail of the course user
3083
        if (is_numeric($invitedUser)) {
3084
            MessageManager::send_message(
3085
                $invitedUser,
3086
                $invitation_title,
3087
                $full_invitation_text,
3088
                [],
3089
                [],
3090
                null,
3091
                null,
3092
                null,
3093
                null,
3094
                $sender_user_id,
3095
                true
3096
            );
3097
        } else {
3098
            $extraParameters = [];
3099
            if (api_get_configuration_value('mail_header_from_custom_course_logo') == true) {
3100
                $extraParameters = ['logo' => CourseManager::getCourseEmailPicture($_course)];
3101
            }
3102
3103
            @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

3103
            /** @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...
3104
                '',
3105
                $invitedUser,
3106
                $invitation_title,
3107
                $full_invitation_text,
3108
                $sender_name,
3109
                $sender_email,
3110
                $replyto,
3111
                [],
3112
                false,
3113
                $extraParameters,
3114
                ''
3115
            );
3116
        }
3117
    }
3118
3119
    /**
3120
     * This function recalculates the number of users who have been invited and updates the survey table with this
3121
     * value.
3122
     *
3123
     * @param string Survey code
3124
     * @param int $courseId
3125
     * @param int $sessionId
3126
     *
3127
     * @return int
3128
     *
3129
     * @author Patrick Cool <[email protected]>, Ghent University
3130
     *
3131
     * @version January 2007
3132
     */
3133
    public static function update_count_invited($survey_code, $courseId = 0, $sessionId = 0)
3134
    {
3135
        $survey_code = Database::escape_string($survey_code);
3136
        $courseId = (int) $courseId;
3137
        $sessionId = (int) $sessionId;
3138
3139
        $courseId = $courseId ?: api_get_course_int_id();
3140
        $sessionId = $sessionId ?: api_get_session_id();
3141
        $sessionCondition = api_get_session_condition($sessionId);
3142
3143
        // Database table definition
3144
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
3145
        $table_survey = Database::get_course_table(TABLE_SURVEY);
3146
3147
        // Counting the number of people that are invited
3148
        $sql = "SELECT count(user) as total
3149
                FROM $table_survey_invitation
3150
		        WHERE
3151
		            c_id = $courseId AND
3152
		            survey_code = '".$survey_code."' AND
3153
		            user <> ''
3154
		            $sessionCondition
3155
                ";
3156
        $result = Database::query($sql);
3157
        $row = Database::fetch_array($result);
3158
        $total_invited = $row['total'];
3159
3160
        // Updating the field in the survey table
3161
        $sql = "UPDATE $table_survey
3162
		        SET invited = '".Database::escape_string($total_invited)."'
3163
		        WHERE
3164
		            c_id = $courseId AND
3165
		            code = '".$survey_code."'
3166
		            $sessionCondition
3167
                ";
3168
        Database::query($sql);
3169
3170
        return $total_invited;
3171
    }
3172
3173
    /**
3174
     * This function gets all the invited users for a given survey code.
3175
     *
3176
     * @param string Survey code
3177
     * @param string optional - course database
3178
     *
3179
     * @return array Array containing the course users and additional users (non course users)
3180
     *
3181
     * @todo consider making $defaults['additional_users'] also an array
3182
     *
3183
     * @author Patrick Cool <[email protected]>, Ghent University
3184
     * @author Julio Montoya, adding c_id fixes - Dec 2012
3185
     *
3186
     * @version January 2007
3187
     */
3188
    public static function get_invited_users($survey_code, $course_code = '', $session_id = 0)
3189
    {
3190
        $session_id = (int) $session_id;
3191
        $survey_code = Database::escape_string($survey_code);
3192
        $course_code = Database::escape_string($course_code);
3193
3194
        $course_id = api_get_course_int_id();
3195
3196
        if (!empty($course_code)) {
3197
            $course_info = api_get_course_info($course_code);
3198
            if ($course_info) {
3199
                $course_id = $course_info['real_id'];
3200
            }
3201
        }
3202
3203
        if (empty($session_id)) {
3204
            $session_id = api_get_session_id();
3205
        }
3206
3207
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
3208
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
3209
3210
        // Selecting all the invitations of this survey AND the additional emailaddresses (the left join)
3211
        $order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname' : ' ORDER BY lastname, firstname';
3212
        $sql = "SELECT user, group_id
3213
				FROM $table_survey_invitation as table_invitation
3214
				WHERE
3215
				    table_invitation.c_id = $course_id AND
3216
                    survey_code='".$survey_code."' AND
3217
                    session_id = $session_id
3218
                ";
3219
3220
        $defaults = [];
3221
        $defaults['course_users'] = [];
3222
        $defaults['additional_users'] = []; // Textarea
3223
        $defaults['users'] = []; // user and groups
3224
3225
        $result = Database::query($sql);
3226
        while ($row = Database::fetch_array($result)) {
3227
            if (is_numeric($row['user'])) {
3228
                $defaults['course_users'][] = $row['user'];
3229
                $defaults['users'][] = 'USER:'.$row['user'];
3230
            } else {
3231
                if (!empty($row['user'])) {
3232
                    $defaults['additional_users'][] = $row['user'];
3233
                }
3234
            }
3235
3236
            if (isset($row['group_id']) && !empty($row['group_id'])) {
3237
                $defaults['users'][] = 'GROUP:'.$row['group_id'];
3238
            }
3239
        }
3240
3241
        if (!empty($defaults['course_users'])) {
3242
            $user_ids = implode("','", $defaults['course_users']);
3243
            $sql = "SELECT user_id FROM $table_user WHERE user_id IN ('$user_ids') $order_clause";
3244
            $result = Database::query($sql);
3245
            $fixed_users = [];
3246
            while ($row = Database::fetch_array($result)) {
3247
                $fixed_users[] = $row['user_id'];
3248
            }
3249
            $defaults['course_users'] = $fixed_users;
3250
        }
3251
3252
        if (!empty($defaults['additional_users'])) {
3253
            $defaults['additional_users'] = implode(';', $defaults['additional_users']);
3254
        }
3255
3256
        return $defaults;
3257
    }
3258
3259
    /**
3260
     * Get all the invitations.
3261
     *
3262
     * @param string Survey code
3263
     *
3264
     * @return array Database rows matching the survey code
3265
     *
3266
     * @author Patrick Cool <[email protected]>, Ghent University
3267
     *
3268
     * @version September 2007
3269
     */
3270
    public static function get_invitations($survey_code)
3271
    {
3272
        $course_id = api_get_course_int_id();
3273
        $sessionId = api_get_session_id();
3274
        // Database table definition
3275
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
3276
3277
        $sql = "SELECT * FROM $table_survey_invitation
3278
		        WHERE
3279
		            c_id = $course_id AND
3280
                    session_id = $sessionId AND
3281
		            survey_code = '".Database::escape_string($survey_code)."'";
3282
        $result = Database::query($sql);
3283
        $return = [];
3284
        while ($row = Database::fetch_array($result)) {
3285
            $return[$row['user']] = $row;
3286
        }
3287
3288
        return $return;
3289
    }
3290
3291
    /**
3292
     * This function displays the form for searching a survey.
3293
     *
3294
     * @author Patrick Cool <[email protected]>, Ghent University
3295
     *
3296
     * @version January 2007
3297
     *
3298
     * @todo consider moving this to surveymanager.inc.lib.php
3299
     */
3300
    public static function display_survey_search_form()
3301
    {
3302
        $url = api_get_path(WEB_CODE_PATH).'survey/survey_list.php?search=advanced&'.api_get_cidreq();
3303
        $form = new FormValidator('search', 'get', $url);
3304
        $form->addHeader(get_lang('SearchASurvey'));
3305
        $form->addText('keyword_title', get_lang('Title'));
3306
        $form->addText('keyword_code', get_lang('Code'));
3307
        $form->addSelectLanguage('keyword_language', get_lang('Language'));
3308
        $form->addHidden('cidReq', api_get_course_id());
3309
        $form->addButtonSearch(get_lang('Search'), 'do_search');
3310
        $form->display();
3311
    }
3312
3313
    /**
3314
     * Show table only visible by DRH users.
3315
     */
3316
    public static function displaySurveyListForDrh()
3317
    {
3318
        $parameters = [];
3319
        $parameters['cidReq'] = api_get_course_id();
3320
3321
        // Create a sortable table with survey-data
3322
        $table = new SortableTable(
3323
            'surveys',
3324
            'get_number_of_surveys',
3325
            'get_survey_data_drh',
3326
            2
3327
        );
3328
        $table->set_additional_parameters($parameters);
3329
        $table->set_header(0, '', false);
3330
        $table->set_header(1, get_lang('SurveyName'));
3331
        $table->set_header(2, get_lang('SurveyCode'));
3332
        $table->set_header(3, get_lang('NumberOfQuestions'));
3333
        $table->set_header(4, get_lang('Author'));
3334
        $table->set_header(5, get_lang('AvailableFrom'));
3335
        $table->set_header(6, get_lang('AvailableUntil'));
3336
        $table->set_header(7, get_lang('Invite'));
3337
        $table->set_header(8, get_lang('Anonymous'));
3338
3339
        if (api_get_configuration_value('allow_mandatory_survey')) {
3340
            $table->set_header(9, get_lang('IsMandatory'));
3341
            $table->set_header(10, get_lang('Modify'), false, 'width="150"');
3342
            $table->set_column_filter(9, 'anonymous_filter');
3343
            $table->set_column_filter(10, 'modify_filter_drh');
3344
        } else {
3345
            $table->set_header(9, get_lang('Modify'), false, 'width="150"');
3346
            $table->set_column_filter(9, 'modify_filter_drh');
3347
        }
3348
3349
        $table->set_column_filter(8, 'anonymous_filter');
3350
        $table->display();
3351
    }
3352
3353
    /**
3354
     * This function displays the sortable table with all the surveys.
3355
     *
3356
     * @author Patrick Cool <[email protected]>, Ghent University
3357
     *
3358
     * @version January 2007
3359
     */
3360
    public static function display_survey_list()
3361
    {
3362
        $parameters = [];
3363
        $parameters['cidReq'] = api_get_course_id();
3364
        if (isset($_GET['do_search']) && $_GET['do_search']) {
3365
            $message = get_lang('DisplaySearchResults').'<br />';
3366
            $message .= '<a href="'.api_get_self().'?'.api_get_cidreq().'">'.get_lang('DisplayAll').'</a>';
3367
            echo Display::return_message($message, 'normal', false);
3368
        }
3369
3370
        // Create a sortable table with survey-data
3371
        $table = new SortableTable(
3372
            'surveys',
3373
            'get_number_of_surveys',
3374
            'get_survey_data',
3375
            2
3376
        );
3377
        $table->set_additional_parameters($parameters);
3378
        $table->set_header(0, '', false);
3379
        $table->set_header(1, get_lang('SurveyName'));
3380
        $table->set_header(2, get_lang('SurveyCode'));
3381
        $table->set_header(3, get_lang('NumberOfQuestions'));
3382
        $table->set_header(4, get_lang('Author'));
3383
        $table->set_header(5, get_lang('AvailableFrom'));
3384
        $table->set_header(6, get_lang('AvailableUntil'));
3385
        $table->set_header(7, get_lang('Invite'));
3386
        $table->set_header(8, get_lang('Anonymous'));
3387
3388
        if (api_get_configuration_value('allow_mandatory_survey')) {
3389
            $table->set_header(9, get_lang('IsMandatory'));
3390
            $table->set_header(10, get_lang('Modify'), false, 'width="150"');
3391
            $table->set_column_filter(8, 'anonymous_filter');
3392
            $table->set_column_filter(10, 'modify_filter');
3393
        } else {
3394
            $table->set_header(9, get_lang('Modify'), false, 'width="150"');
3395
            $table->set_column_filter(9, 'modify_filter');
3396
        }
3397
3398
        $table->set_column_filter(8, 'anonymous_filter');
3399
        $actions = [
3400
            'export_all' => get_lang('ExportResults'),
3401
            'export_by_class' => get_lang('ExportByClass'),
3402
            'send_to_tutors' => get_lang('SendToGroupTutors'),
3403
            'multiplicate_by_class' => get_lang('MultiplicateQuestionsByClass'),
3404
            'multiplicate_by_user' => get_lang('MultiplicateQuestionsByUser'),
3405
            'delete' => get_lang('DeleteSurvey'),
3406
        ];
3407
        $table->set_form_actions($actions);
3408
3409
        $form = new FormValidator(
3410
            'survey',
3411
            'post',
3412
            null,
3413
            null,
3414
            ['class' => 'form-vertical']
3415
        );
3416
        $form->addElement(
3417
            'radio',
3418
            'type',
3419
            null,
3420
            get_lang('MultiplicateQuestionsByClass'),
3421
            'by_class',
3422
            ['id' => 'by_class']
3423
        );
3424
        $form->addElement(
3425
            'radio',
3426
            'type',
3427
            null,
3428
            get_lang('MultiplicateQuestionsByUser'),
3429
            'by_user',
3430
            ['id' => 'by_user']
3431
        );
3432
        $form->setDefaults(['type' => 'by_class']);
3433
        $formToString = $form->returnForm();
3434
3435
        echo '<div id="dialog-confirm">'.$formToString.'</div>';
3436
        $table->display();
3437
    }
3438
3439
    /**
3440
     * Survey list for coach.
3441
     */
3442
    public static function display_survey_list_for_coach()
3443
    {
3444
        $parameters = [];
3445
        $parameters['cidReq'] = api_get_course_id();
3446
        if (isset($_GET['do_search'])) {
3447
            $message = get_lang('DisplaySearchResults').'<br />';
3448
            $message .= '<a href="'.api_get_self().'?'.api_get_cidreq().'">'.get_lang('DisplayAll').'</a>';
3449
            echo Display::return_message($message, 'normal', false);
3450
        }
3451
3452
        // Create a sortable table with survey-data
3453
        $table = new SortableTable(
3454
            'surveys_coach',
3455
            'get_number_of_surveys_for_coach',
3456
            'get_survey_data_for_coach',
3457
            2
3458
        );
3459
        $table->set_additional_parameters($parameters);
3460
        $table->set_header(0, '', false);
3461
        $table->set_header(1, get_lang('SurveyName'));
3462
        $table->set_header(2, get_lang('SurveyCode'));
3463
        $table->set_header(3, get_lang('NumberOfQuestions'));
3464
        $table->set_header(4, get_lang('Author'));
3465
        $table->set_header(5, get_lang('AvailableFrom'));
3466
        $table->set_header(6, get_lang('AvailableUntil'));
3467
        $table->set_header(7, get_lang('Invite'));
3468
        $table->set_header(8, get_lang('Anonymous'));
3469
3470
        if (api_get_configuration_value('allow_mandatory_survey')) {
3471
            $table->set_header(9, get_lang('Modify'), false, 'width="130"');
3472
            $table->set_header(10, get_lang('Modify'), false, 'width="130"');
3473
            $table->set_column_filter(8, 'anonymous_filter');
3474
            $table->set_column_filter(10, 'modify_filter_for_coach');
3475
        } else {
3476
            $table->set_header(9, get_lang('Modify'), false, 'width="130"');
3477
            $table->set_column_filter(9, 'modify_filter_for_coach');
3478
        }
3479
3480
        $table->set_column_filter(8, 'anonymous_filter');
3481
        $table->display();
3482
    }
3483
3484
    /**
3485
     * Check if the hide_survey_edition configurations setting is enabled.
3486
     *
3487
     * @param string $surveyCode
3488
     *
3489
     * @return bool
3490
     */
3491
    public static function checkHideEditionToolsByCode($surveyCode)
3492
    {
3493
        $hideSurveyEdition = api_get_configuration_value('hide_survey_edition');
3494
3495
        if (false === $hideSurveyEdition) {
3496
            return false;
3497
        }
3498
3499
        if ('*' === $hideSurveyEdition['codes']) {
3500
            return true;
3501
        }
3502
3503
        if (in_array($surveyCode, $hideSurveyEdition['codes'])) {
3504
            return true;
3505
        }
3506
3507
        return false;
3508
    }
3509
3510
    /**
3511
     * This function changes the modify column of the sortable table.
3512
     *
3513
     * @param int  $survey_id the id of the survey
3514
     * @param bool $drh
3515
     *
3516
     * @return string html code that are the actions that can be performed on any survey
3517
     *
3518
     * @author Patrick Cool <[email protected]>, Ghent University
3519
     *
3520
     * @version January 2007
3521
     */
3522
    public static function modify_filter($survey_id, $drh = false)
3523
    {
3524
        /** @var CSurvey $survey */
3525
        $survey = Database::getManager()->find('ChamiloCourseBundle:CSurvey', $survey_id);
3526
        $hideSurveyEdition = self::checkHideEditionToolsByCode($survey->getCode());
3527
3528
        if ($hideSurveyEdition) {
3529
            return '';
3530
        }
3531
3532
        if (empty($survey)) {
3533
            return '';
3534
        }
3535
3536
        $survey_id = $survey->getSurveyId();
3537
        $actions = [];
3538
        $hideReportingButton = api_get_configuration_value('hide_survey_reporting_button');
3539
        $codePath = api_get_path(WEB_CODE_PATH);
3540
        $params = [];
3541
        parse_str(api_get_cidreq(), $params);
3542
3543
        $reportingLink = Display::url(
3544
            Display::return_icon('statistics.png', get_lang('Reporting')),
3545
            $codePath.'survey/reporting.php?'.http_build_query($params + ['survey_id' => $survey_id])
3546
        );
3547
3548
        if ($drh) {
3549
            return $hideReportingButton ? '-' : $reportingLink;
3550
        }
3551
3552
        $type = $survey->getSurveyType();
3553
3554
        // Coach can see that only if the survey is in his session
3555
        if (api_is_allowed_to_edit() || api_is_element_in_the_session(TOOL_SURVEY, $survey_id)) {
3556
            $configUrl = $codePath.'survey/create_new_survey.php?'.
3557
                http_build_query($params + ['action' => 'edit', 'survey_id' => $survey_id]);
3558
            $editUrl = $codePath.'survey/survey.php?'.
3559
                http_build_query($params + ['survey_id' => $survey_id]);
3560
            if (3 == $survey->getSurveyType()) {
3561
                $configUrl = $codePath.'survey/edit_meeting.php?'.
3562
                    http_build_query($params + ['action' => 'edit', 'survey_id' => $survey_id]);
3563
            }
3564
3565
            $actions[] = Display::url(
3566
                Display::return_icon('edit.png', get_lang('EditQuestions')),
3567
                $editUrl
3568
            );
3569
            $actions[] = Display::url(
3570
                Display::return_icon('settings.png', get_lang('Configure')),
3571
                $configUrl
3572
            );
3573
3574
            if (SurveyManager::survey_generation_hash_available()) {
3575
                $actions[] = Display::url(
3576
                    Display::return_icon('new_link.png', get_lang('GenerateSurveyAccessLink')),
3577
                    $codePath.'survey/generate_link.php?'.http_build_query($params + ['survey_id' => $survey_id])
3578
                );
3579
            }
3580
3581
            if ($type != 3) {
3582
                $actions[] = Display::url(
3583
                    Display::return_icon('backup.png', get_lang('CopySurvey')),
3584
                    $codePath.'survey/copy_survey.php?'.http_build_query($params + ['survey_id' => $survey_id])
3585
                );
3586
3587
                $actions[] = Display::url(
3588
                    Display::return_icon('copy.png', get_lang('DuplicateSurvey')),
3589
                    $codePath.'survey/survey_list.php?'
3590
                    .http_build_query($params + ['action' => 'copy_survey', 'survey_id' => $survey_id])
3591
                );
3592
3593
                $actions[] = Display::url(
3594
                    Display::return_icon('multiplicate_survey.png', get_lang('MultiplicateQuestions')),
3595
                    $codePath.'survey/survey_list.php?'
3596
                    .http_build_query($params + ['action' => 'multiplicate', 'survey_id' => $survey_id]),
3597
                    ['survey_id' => $survey_id, 'class' => 'multiplicate_popup']
3598
                );
3599
3600
                $actions[] = Display::url(
3601
                    Display::return_icon('multiplicate_survey_na.png', get_lang('RemoveMultiplicateQuestions')),
3602
                    $codePath.'survey/survey_list.php?'
3603
                    .http_build_query($params + ['action' => 'remove_multiplicate', 'survey_id' => $survey_id])
3604
                );
3605
3606
                $warning = addslashes(api_htmlentities(get_lang('EmptySurvey').'?', ENT_QUOTES));
3607
                $actions[] = Display::url(
3608
                    Display::return_icon('clean.png', get_lang('EmptySurvey')),
3609
                    $codePath.'survey/survey_list.php?'
3610
                    .http_build_query($params + ['action' => 'empty', 'survey_id' => $survey_id]),
3611
                    [
3612
                        'onclick' => "javascript: if (!confirm('".$warning."')) return false;",
3613
                    ]
3614
                );
3615
            }
3616
        }
3617
3618
        if (3 != $type) {
3619
            $actions[] = Display::url(
3620
                Display::return_icon('preview_view.png', get_lang('Preview')),
3621
                $codePath.'survey/preview.php?'.http_build_query($params + ['survey_id' => $survey_id])
3622
            );
3623
        }
3624
3625
        $actions[] = Display::url(
3626
            Display::return_icon('mail_send.png', get_lang('Publish')),
3627
            $codePath.'survey/survey_invite.php?'.http_build_query($params + ['survey_id' => $survey_id])
3628
        );
3629
3630
        $extraFieldValue = new ExtraFieldValue('survey');
3631
        $groupData = $extraFieldValue->get_values_by_handler_and_field_variable($survey_id, 'group_id');
3632
        if ($groupData && !empty($groupData['value'])) {
3633
            $actions[] = Display::url(
3634
                Display::return_icon('teacher.png', get_lang('SendToGroupTutors')),
3635
                $codePath.'survey/survey_list.php?action=send_to_tutors&'.http_build_query($params + ['survey_id' => $survey_id])
3636
            );
3637
        }
3638
3639
        if (3 != $type) {
3640
            $actions[] = $hideReportingButton ? null : $reportingLink;
3641
        }
3642
3643
        if (api_is_allowed_to_edit() ||
3644
            api_is_element_in_the_session(TOOL_SURVEY, $survey_id)
3645
        ) {
3646
            $actions[] = self::getAdditionalTeacherActions($survey_id);
3647
            $warning = addslashes(api_htmlentities(get_lang('DeleteSurvey').'?', ENT_QUOTES));
3648
            $actions[] = Display::url(
3649
                Display::return_icon('delete.png', get_lang('Delete')),
3650
                $codePath.'survey/survey_list.php?'
3651
                .http_build_query($params + ['action' => 'delete', 'survey_id' => $survey_id]),
3652
                [
3653
                    'onclick' => "javascript: if (!confirm('".$warning."')) return false;",
3654
                ]
3655
            );
3656
        }
3657
3658
        return implode(PHP_EOL, $actions);
3659
    }
3660
3661
    /**
3662
     * Get the additional actions added in survey_additional_teacher_modify_actions configuration.
3663
     *
3664
     * @param int $surveyId
3665
     * @param int $iconSize
3666
     *
3667
     * @return string
3668
     */
3669
    public static function getAdditionalTeacherActions($surveyId, $iconSize = ICON_SIZE_SMALL)
3670
    {
3671
        $additionalActions = api_get_configuration_value('survey_additional_teacher_modify_actions') ?: [];
3672
3673
        if (empty($additionalActions)) {
3674
            return '';
3675
        }
3676
3677
        $actions = [];
3678
        foreach ($additionalActions as $additionalAction) {
3679
            $actions[] = call_user_func(
3680
                $additionalAction,
3681
                ['survey_id' => $surveyId, 'icon_size' => $iconSize]
3682
            );
3683
        }
3684
3685
        return implode(PHP_EOL, $actions);
3686
    }
3687
3688
    /**
3689
     * @param int $survey_id
3690
     *
3691
     * @return string
3692
     */
3693
    public static function modify_filter_for_coach($survey_id)
3694
    {
3695
        $survey_id = (int) $survey_id;
3696
        $actions = [];
3697
        $codePath = api_get_path(WEB_CODE_PATH);
3698
        $params = [];
3699
        parse_str(api_get_cidreq(), $params);
3700
        $actions[] = Display::url(
3701
            Display::return_icon('preview_view.png', get_lang('Preview')),
3702
            $codePath.'survey/preview.php?'.http_build_query($params + ['survey_id' => $survey_id])
3703
        );
3704
        $actions[] = Display::url(
3705
            Display::return_icon('mail_send.png', get_lang('Publish')),
3706
            $codePath.'survey/survey_invite.php?'.http_build_query($params + ['survey_id' => $survey_id])
3707
        );
3708
        $warning = addslashes(api_htmlentities(get_lang('EmptySurvey').'?', ENT_QUOTES));
3709
        $actions[] = Display::url(
3710
            Display::return_icon('clean.png', get_lang('EmptySurvey')),
3711
            $codePath.'survey/survey_list.php?'
3712
                .http_build_query($params + ['action' => 'empty', 'survey_id' => $survey_id]),
3713
            [
3714
                'onclick' => "javascript: if(!confirm('".$warning."')) return false;",
3715
            ]
3716
        );
3717
3718
        return implode(PHP_EOL, $actions);
3719
    }
3720
3721
    /**
3722
     * Returns "yes" when given parameter is one, "no" for any other value.
3723
     *
3724
     * @param int Whether anonymous or not
3725
     *
3726
     * @return string "Yes" or "No" in the current language
3727
     */
3728
    public static function anonymous_filter($anonymous)
3729
    {
3730
        if (1 == $anonymous) {
3731
            return get_lang('Yes');
3732
        } else {
3733
            return get_lang('No');
3734
        }
3735
    }
3736
3737
    /**
3738
     * This function handles the search restriction for the SQL statements.
3739
     *
3740
     * @return string Part of a SQL statement or false on error
3741
     *
3742
     * @author Patrick Cool <[email protected]>, Ghent University
3743
     *
3744
     * @version January 2007
3745
     */
3746
    public static function survey_search_restriction()
3747
    {
3748
        if (isset($_GET['do_search'])) {
3749
            if ($_GET['keyword_title'] != '') {
3750
                $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...
3751
            }
3752
            if ($_GET['keyword_code'] != '') {
3753
                $search_term[] = 'code =\''.Database::escape_string($_GET['keyword_code']).'\'';
3754
            }
3755
            if ($_GET['keyword_language'] != '%') {
3756
                $search_term[] = 'lang =\''.Database::escape_string($_GET['keyword_language']).'\'';
3757
            }
3758
            $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...
3759
            $search_restriction = implode(' AND ', $my_search_term);
3760
3761
            return $search_restriction;
3762
        } else {
3763
            return false;
3764
        }
3765
    }
3766
3767
    /**
3768
     * This function calculates the total number of surveys.
3769
     *
3770
     * @return int Total number of surveys
3771
     *
3772
     * @author Patrick Cool <[email protected]>, Ghent University
3773
     *
3774
     * @version January 2007
3775
     */
3776
    public static function get_number_of_surveys()
3777
    {
3778
        $table_survey = Database::get_course_table(TABLE_SURVEY);
3779
        $course_id = api_get_course_int_id();
3780
3781
        $search_restriction = self::survey_search_restriction();
3782
        if ($search_restriction) {
3783
            $search_restriction = 'WHERE c_id = '.$course_id.' AND '.$search_restriction;
3784
        } else {
3785
            $search_restriction = "WHERE c_id = $course_id";
3786
        }
3787
        // To list the surveys base too
3788
        $showSurveysBase = api_get_configuration_value('show_surveys_base_in_sessions');
3789
        $sessionCondition = api_get_session_condition(api_get_session_id(), true, $showSurveysBase);
3790
3791
        $sql = "SELECT count(survey_id) AS total_number_of_items
3792
		        FROM $table_survey $search_restriction $sessionCondition";
3793
        $res = Database::query($sql);
3794
        $obj = Database::fetch_object($res);
3795
3796
        return $obj->total_number_of_items;
3797
    }
3798
3799
    /**
3800
     * @return int
3801
     */
3802
    public static function get_number_of_surveys_for_coach()
3803
    {
3804
        $survey_tree = new SurveyTree();
3805
3806
        return count($survey_tree->surveylist);
3807
    }
3808
3809
    /**
3810
     * This function gets all the survey data that is to be displayed in the sortable table.
3811
     *
3812
     * @param int    $from
3813
     * @param int    $number_of_items
3814
     * @param int    $column
3815
     * @param string $direction
3816
     * @param bool   $isDrh
3817
     *
3818
     * @return array
3819
     *
3820
     * @author Patrick Cool <[email protected]>, Ghent University
3821
     * @author Julio Montoya <[email protected]>, Beeznest - Adding intvals
3822
     *
3823
     * @version January 2007
3824
     */
3825
    public static function get_survey_data(
3826
        $from,
3827
        $number_of_items,
3828
        $column,
3829
        $direction,
3830
        $isDrh = false
3831
    ) {
3832
        $table_survey = Database::get_course_table(TABLE_SURVEY);
3833
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
3834
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
3835
        $mandatoryAllowed = api_get_configuration_value('allow_mandatory_survey');
3836
        $_user = api_get_user_info();
3837
        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
3838
3839
        // Searching
3840
        $search_restriction = self::survey_search_restriction();
3841
        if ($search_restriction) {
3842
            $search_restriction = ' AND '.$search_restriction;
3843
        }
3844
        $from = (int) $from;
3845
        $number_of_items = (int) $number_of_items;
3846
        $column = (int) $column;
3847
        if (!in_array(strtolower($direction), ['asc', 'desc'])) {
3848
            $direction = 'asc';
3849
        }
3850
3851
        // To list the surveys base too
3852
        $showSurveysBase = api_get_configuration_value('show_surveys_base_in_sessions');
3853
        $sessionId = api_get_session_id();
3854
        $sessionCondition = api_get_session_condition($sessionId, true, $showSurveysBase);
3855
        $course_id = api_get_course_int_id();
3856
3857
        $sql = "
3858
            SELECT
3859
                survey.survey_id AS col0,
3860
                survey.title AS col1,
3861
                survey.code AS col2,
3862
                count(survey_question.question_id) AS col3, "
3863
                .(api_is_western_name_order()
3864
                ? "CONCAT(user.firstname, ' ', user.lastname)"
3865
                : "CONCAT(user.lastname, ' ', user.firstname)")
3866
                ."	AS col4,
3867
                survey.avail_from AS col5,
3868
                survey.avail_till AS col6,
3869
                survey.invited AS col7,
3870
                survey.anonymous AS col8,
3871
                survey.iid AS col9,
3872
                survey.session_id AS session_id,
3873
                survey.answered,
3874
                survey.invited,
3875
                survey.survey_type
3876
            FROM $table_survey survey
3877
            LEFT JOIN $table_survey_question survey_question
3878
            ON (survey.survey_id = survey_question.survey_id AND survey_question.c_id = $course_id)
3879
            LEFT JOIN $table_user user
3880
            ON (survey.author = user.id)
3881
            WHERE survey.c_id = $course_id
3882
            $search_restriction
3883
            $sessionCondition
3884
            GROUP BY survey.survey_id
3885
            ORDER BY col$column $direction
3886
            LIMIT $from,$number_of_items
3887
        ";
3888
        $res = Database::query($sql);
3889
        $surveys = [];
3890
        $array = [];
3891
        $efv = new ExtraFieldValue('survey');
3892
        while ($survey = Database::fetch_array($res)) {
3893
            $array[0] = $survey[0];
3894
            $survey[1] = Security::remove_XSS($survey[1]);
3895
3896
            if (self::checkHideEditionToolsByCode($survey['col2'])) {
3897
                $array[1] = $survey[1];
3898
            } else {
3899
                // Doodle
3900
                if (3 == $survey['survey_type']) {
3901
                    $array[1] = Display::url(
3902
                        $survey[1],
3903
                        api_get_path(WEB_CODE_PATH).'survey/meeting.php?survey_id='.$survey[0].'&'.api_get_cidreq()
3904
                    );
3905
                } else {
3906
                    $array[1] = Display::url(
3907
                        $survey[1],
3908
                        api_get_path(WEB_CODE_PATH).'survey/survey.php?survey_id='.$survey[0].'&'.api_get_cidreq()
3909
                    );
3910
                }
3911
            }
3912
3913
            // Validation when belonging to a session
3914
            $session_img = api_get_session_image($survey['session_id'], $_user['status']);
3915
            $array[2] = $survey[2].$session_img;
3916
            $array[3] = $survey[3];
3917
            $array[4] = $survey[4];
3918
3919
            // Dates
3920
            $array[5] = '';
3921
3922
            if (!empty($survey[5]) && $survey[5] !== '0000-00-00' && $survey[5] !== '0000-00-00 00:00:00') {
3923
                $array[5] = api_convert_and_format_date(
3924
                    $survey[5],
3925
                    $allowSurveyAvailabilityDatetime ? DATE_TIME_FORMAT_LONG : DATE_FORMAT_LONG
3926
                );
3927
            }
3928
3929
            $array[6] = '';
3930
            if (!empty($survey[6]) && $survey[6] !== '0000-00-00' && $survey[6] !== '0000-00-00 00:00:00') {
3931
                $array[6] = api_convert_and_format_date(
3932
                    $survey[6],
3933
                    $allowSurveyAvailabilityDatetime ? DATE_TIME_FORMAT_LONG : DATE_FORMAT_LONG
3934
                );
3935
            }
3936
3937
            $array[7] =
3938
                Display::url(
3939
                    $survey['answered'],
3940
                    api_get_path(WEB_CODE_PATH).'survey/survey_invitation.php?view=answered&survey_id='.$survey[0].'&'
3941
                        .api_get_cidreq()
3942
                ).' / '.
3943
                Display::url(
3944
                    $survey['invited'],
3945
                    api_get_path(WEB_CODE_PATH).'survey/survey_invitation.php?view=invited&survey_id='.$survey[0].'&'
3946
                        .api_get_cidreq()
3947
                );
3948
            // Anon
3949
            $array[8] = $survey['col8'];
3950
            if ($mandatoryAllowed) {
3951
                $efvMandatory = $efv->get_values_by_handler_and_field_variable(
3952
                    $survey[9],
3953
                    'is_mandatory'
3954
                );
3955
3956
                $array[9] = $efvMandatory ? $efvMandatory['value'] : 0;
3957
                // Survey id
3958
                $array[10] = $survey['col9'];
3959
            } else {
3960
                // Survey id
3961
                $array[9] = $survey['col9'];
3962
            }
3963
3964
            if ($isDrh) {
3965
                $array[1] = $survey[1];
3966
                $array[7] = strip_tags($array[7]);
3967
            }
3968
3969
            $surveys[] = $array;
3970
        }
3971
3972
        return $surveys;
3973
    }
3974
3975
    /**
3976
     * @param $from
3977
     * @param $number_of_items
3978
     * @param $column
3979
     * @param $direction
3980
     *
3981
     * @return array
3982
     */
3983
    public static function get_survey_data_for_coach($from, $number_of_items, $column, $direction)
3984
    {
3985
        $mandatoryAllowed = api_get_configuration_value('allow_mandatory_survey');
3986
        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
3987
        $survey_tree = new SurveyTree();
3988
        $last_version_surveys = $survey_tree->surveylist;
3989
        $list = [];
3990
        foreach ($last_version_surveys as &$survey) {
3991
            $list[] = $survey['id'];
3992
        }
3993
        if (count($list) > 0) {
3994
            $list_condition = " AND survey.survey_id IN (".implode(',', $list).") ";
3995
        } else {
3996
            $list_condition = '';
3997
        }
3998
3999
        $from = (int) $from;
4000
        $number_of_items = (int) $number_of_items;
4001
        $column = (int) $column;
4002
        if (!in_array(strtolower($direction), ['asc', 'desc'])) {
4003
            $direction = 'asc';
4004
        }
4005
4006
        $table_survey = Database::get_course_table(TABLE_SURVEY);
4007
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
4008
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
4009
        $course_id = api_get_course_int_id();
4010
        $efv = new ExtraFieldValue('survey');
4011
4012
        $sql = "
4013
            SELECT
4014
            survey.survey_id AS col0,
4015
                survey.title AS col1,
4016
                survey.code AS col2,
4017
                count(survey_question.question_id) AS col3,
4018
        "
4019
            .(api_is_western_name_order()
4020
                ? "CONCAT(user.firstname, ' ', user.lastname)"
4021
                : "CONCAT(user.lastname, ' ', user.firstname)")
4022
            ."	AS col4,
4023
                survey.avail_from AS col5,
4024
                survey.avail_till AS col6,
4025
                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,
4026
                survey.anonymous AS col8,
4027
                survey.survey_id AS col9
4028
            FROM $table_survey survey
4029
            LEFT JOIN $table_survey_question survey_question
4030
            ON (survey.survey_id = survey_question.survey_id AND survey.c_id = survey_question.c_id),
4031
            $table_user user
4032
            WHERE survey.author = user.id AND survey.c_id = $course_id $list_condition
4033
        ";
4034
        $sql .= ' GROUP BY survey.survey_id';
4035
        $sql .= " ORDER BY col$column $direction ";
4036
        $sql .= " LIMIT $from,$number_of_items";
4037
4038
        $res = Database::query($sql);
4039
        $surveys = [];
4040
        while ($survey = Database::fetch_array($res)) {
4041
            $survey['col5'] = api_convert_and_format_date(
4042
                $survey['col5'],
4043
                $allowSurveyAvailabilityDatetime ? DATE_TIME_FORMAT_LONG : DATE_FORMAT_LONG
4044
            );
4045
            $survey['col6'] = api_convert_and_format_date(
4046
                $survey['col6'],
4047
                $allowSurveyAvailabilityDatetime ? DATE_TIME_FORMAT_LONG : DATE_FORMAT_LONG
4048
            );
4049
4050
            if ($mandatoryAllowed) {
4051
                $survey['col10'] = $survey['col9'];
4052
                $efvMandatory = $efv->get_values_by_handler_and_field_variable(
4053
                    $survey['col9'],
4054
                    'is_mandatory'
4055
                );
4056
                $survey['col9'] = $efvMandatory['value'];
4057
            }
4058
            $surveys[] = $survey;
4059
        }
4060
4061
        return $surveys;
4062
    }
4063
4064
    /**
4065
     * Display all the active surveys for the given course user.
4066
     *
4067
     * @param int $user_id
4068
     *
4069
     * @author Patrick Cool <[email protected]>, Ghent University
4070
     *
4071
     * @version April 2007
4072
     */
4073
    public static function getSurveyList($user_id)
4074
    {
4075
        $_course = api_get_course_info();
4076
        $course_id = $_course['real_id'];
4077
        $user_id = (int) $user_id;
4078
        $sessionId = api_get_session_id();
4079
        $mandatoryAllowed = api_get_configuration_value('allow_mandatory_survey');
4080
        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
4081
4082
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
4083
        $table_survey = Database::get_course_table(TABLE_SURVEY);
4084
4085
        echo '<table id="list-survey" class="table ">';
4086
        echo '<thead>';
4087
        echo '<tr>';
4088
        echo '	<th>'.get_lang('SurveyName').'</th>';
4089
        echo '	<th class="text-center">'.get_lang('Anonymous').'</th>';
4090
        if ($mandatoryAllowed) {
4091
            echo '<th class="text-center">'.get_lang('IsMandatory').'</th>';
4092
        }
4093
        echo '</tr>';
4094
        echo '</thead>';
4095
        echo '<tbody>';
4096
4097
        /** @var \DateTime $now */
4098
        $now = api_get_utc_datetime(null, false, true);
4099
        $filterDate = $allowSurveyAvailabilityDatetime ? $now->format('Y-m-d H:i') : $now->format('Y-m-d');
4100
4101
        // To list the surveys base too
4102
        $showSurveysBase = api_get_configuration_value('show_surveys_base_in_sessions');
4103
        $sessionCondition = api_get_session_condition($sessionId, true, $showSurveysBase, 'survey.session_id');
4104
4105
        $sql = "SELECT survey_invitation.answered,
4106
                    survey_invitation.invitation_code,
4107
                    survey_invitation.session_id,
4108
                    survey.title,
4109
                    survey.visible_results,
4110
                    survey.survey_id,
4111
                    survey.anonymous
4112
                FROM $table_survey survey
4113
                INNER JOIN
4114
                $table_survey_invitation survey_invitation
4115
                ON (
4116
                    survey.code = survey_invitation.survey_code AND
4117
                    survey.c_id = survey_invitation.c_id AND
4118
                    survey_invitation.session_id = $sessionId
4119
                )
4120
				WHERE
4121
                    survey_invitation.user = $user_id AND
4122
                    survey.avail_from <= '$filterDate' AND
4123
                    (survey.avail_till >= '$filterDate' OR
4124
                    survey.avail_till IS NULL) AND
4125
                    survey.c_id = $course_id AND
4126
                    survey_invitation.c_id = $course_id $sessionCondition
4127
				";
4128
        $result = Database::query($sql);
4129
4130
        $efv = new ExtraFieldValue('survey');
4131
4132
        $surveyIds = [];
4133
4134
        while ($row = Database::fetch_array($result, 'ASSOC')) {
4135
            if (in_array($row['survey_id'], $surveyIds)) {
4136
                continue;
4137
            }
4138
4139
            $title = Security::remove_XSS($row['title']);
4140
4141
            echo '<tr>';
4142
            if ($row['answered'] == 0) {
4143
                echo '<td>';
4144
                $url = self::generateFillSurveyLink($row['invitation_code'], $_course, $row['session_id']);
4145
                $icon = Display::return_icon(
4146
                    'survey.png',
4147
                    get_lang('ClickHereToAnswerTheSurvey'),
4148
                    ['style' => 'margin-top: -4px'],
4149
                    ICON_SIZE_TINY
4150
                );
4151
                echo '<a href="'.$url.'">
4152
                    '.$icon
4153
                    .$title
4154
                    .'</a></td>';
4155
            } else {
4156
                $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
4157
                    $user_id,
4158
                    $_course
4159
                );
4160
                $icon = Display::return_icon(
4161
                    'survey_na.png',
4162
                    get_lang('SurveysDone'),
4163
                    [],
4164
                    ICON_SIZE_TINY
4165
                );
4166
                $showLink = (!api_is_allowed_to_edit(false, true) || $isDrhOfCourse)
4167
                    && $row['visible_results'] != SURVEY_VISIBLE_TUTOR;
4168
4169
                echo '<td>';
4170
                echo $showLink
4171
                    ? Display::url(
4172
                        $icon.PHP_EOL.$row['title'],
4173
                        api_get_path(WEB_CODE_PATH).'survey/reporting.php?'.api_get_cidreq().'&'.http_build_query([
4174
                            'action' => 'questionreport',
4175
                            'survey_id' => $row['survey_id'],
4176
                        ])
4177
                    )
4178
                    : $icon.PHP_EOL.$title;
4179
                echo '</td>';
4180
            }
4181
            echo '<td class="text-center">';
4182
            echo ($row['anonymous'] == 1) ? get_lang('Yes') : get_lang('No');
4183
            echo '</td>';
4184
            if ($mandatoryAllowed) {
4185
                $efvMandatory = $efv->get_values_by_handler_and_field_variable(
4186
                    $row['survey_id'],
4187
                    'is_mandatory'
4188
                );
4189
                echo '<td class="text-center">'.($efvMandatory['value'] ? get_lang('Yes') : get_lang('No')).'</td>';
4190
            }
4191
            echo '</tr>';
4192
            $surveyIds[] = $row['survey_id'];
4193
        }
4194
        echo '</tbody>';
4195
        echo '</table>';
4196
    }
4197
4198
    /**
4199
     * Creates a multi array with the user fields that we can show.
4200
     * We look the visibility with the api_get_setting function
4201
     * The username is always NOT able to change it.
4202
     *
4203
     * @author Julio Montoya Armas <[email protected]>, Chamilo: Personality Test modification
4204
     *
4205
     * @return array array[value_name][name], array[value_name][visibilty]
4206
     */
4207
    public static function make_field_list()
4208
    {
4209
        //	LAST NAME and FIRST NAME
4210
        $field_list_array = [];
4211
        $field_list_array['lastname']['name'] = get_lang('LastName');
4212
        $field_list_array['firstname']['name'] = get_lang('FirstName');
4213
4214
        if (api_get_setting('profile', 'name') != 'true') {
4215
            $field_list_array['firstname']['visibility'] = 0;
4216
            $field_list_array['lastname']['visibility'] = 0;
4217
        } else {
4218
            $field_list_array['firstname']['visibility'] = 1;
4219
            $field_list_array['lastname']['visibility'] = 1;
4220
        }
4221
4222
        $field_list_array['username']['name'] = get_lang('Username');
4223
        $field_list_array['username']['visibility'] = 0;
4224
4225
        //	OFFICIAL CODE
4226
        $field_list_array['official_code']['name'] = get_lang('OfficialCode');
4227
4228
        if (api_get_setting('profile', 'officialcode') != 'true') {
4229
            $field_list_array['official_code']['visibility'] = 1;
4230
        } else {
4231
            $field_list_array['official_code']['visibility'] = 0;
4232
        }
4233
4234
        // EMAIL
4235
        $field_list_array['email']['name'] = get_lang('Email');
4236
        if (api_get_setting('profile', 'email') != 'true') {
4237
            $field_list_array['email']['visibility'] = 1;
4238
        } else {
4239
            $field_list_array['email']['visibility'] = 0;
4240
        }
4241
4242
        // PHONE
4243
        $field_list_array['phone']['name'] = get_lang('Phone');
4244
        if (api_get_setting('profile', 'phone') != 'true') {
4245
            $field_list_array['phone']['visibility'] = 0;
4246
        } else {
4247
            $field_list_array['phone']['visibility'] = 1;
4248
        }
4249
        //	LANGUAGE
4250
        $field_list_array['language']['name'] = get_lang('Language');
4251
        if (api_get_setting('profile', 'language') != 'true') {
4252
            $field_list_array['language']['visibility'] = 0;
4253
        } else {
4254
            $field_list_array['language']['visibility'] = 1;
4255
        }
4256
4257
        // EXTRA FIELDS
4258
        $extra = UserManager::get_extra_fields(0, 50, 5, 'ASC');
4259
4260
        foreach ($extra as $id => $field_details) {
4261
            if (0 == $field_details[6]) {
4262
                continue;
4263
            }
4264
            switch ($field_details[2]) {
4265
                case UserManager::USER_FIELD_TYPE_TEXT:
4266
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
4267
                    if (0 == $field_details[7]) {
4268
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
4269
                    } else {
4270
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
4271
                    }
4272
                    break;
4273
                case UserManager::USER_FIELD_TYPE_TEXTAREA:
4274
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
4275
                    if (0 == $field_details[7]) {
4276
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
4277
                    } else {
4278
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
4279
                    }
4280
                    break;
4281
                case UserManager::USER_FIELD_TYPE_RADIO:
4282
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
4283
                    if (0 == $field_details[7]) {
4284
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
4285
                    } else {
4286
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
4287
                    }
4288
                    break;
4289
                case UserManager::USER_FIELD_TYPE_SELECT:
4290
                    $get_lang_variables = false;
4291
                    if (in_array(
4292
                        $field_details[1],
4293
                        ['mail_notify_message', 'mail_notify_invitation', 'mail_notify_group_message']
4294
                    )
4295
                    ) {
4296
                        $get_lang_variables = true;
4297
                    }
4298
4299
                    if ($get_lang_variables) {
4300
                        $field_list_array['extra_'.$field_details[1]]['name'] = get_lang($field_details[3]);
4301
                    } else {
4302
                        $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
4303
                    }
4304
4305
                    if (0 == $field_details[7]) {
4306
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
4307
                    } else {
4308
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
4309
                    }
4310
                    break;
4311
                case UserManager::USER_FIELD_TYPE_SELECT_MULTIPLE:
4312
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
4313
                    if (0 == $field_details[7]) {
4314
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
4315
                    } else {
4316
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
4317
                    }
4318
                    break;
4319
                case UserManager::USER_FIELD_TYPE_DATE:
4320
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
4321
                    if (0 == $field_details[7]) {
4322
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
4323
                    } else {
4324
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
4325
                    }
4326
                    break;
4327
                case UserManager::USER_FIELD_TYPE_DATETIME:
4328
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
4329
                    if (0 == $field_details[7]) {
4330
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
4331
                    } else {
4332
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
4333
                    }
4334
                    break;
4335
                case UserManager::USER_FIELD_TYPE_DOUBLE_SELECT:
4336
                    $field_list_array['extra_'.$field_details[1]]['name'] = $field_details[3];
4337
                    if (0 == $field_details[7]) {
4338
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 0;
4339
                    } else {
4340
                        $field_list_array['extra_'.$field_details[1]]['visibility'] = 1;
4341
                    }
4342
                    break;
4343
                case UserManager::USER_FIELD_TYPE_DIVIDER:
4344
                    //$form->addElement('static',$field_details[1], '<br /><strong>'.$field_details[3].'</strong>');
4345
                    break;
4346
            }
4347
        }
4348
4349
        return $field_list_array;
4350
    }
4351
4352
    /**
4353
     * Display survey question chart.
4354
     *
4355
     * @param array  $chartData
4356
     * @param bool   $hasSerie         Tells if the chart has a serie. False by default
4357
     * @param string $chartContainerId
4358
     *
4359
     * @return string (direct output)
4360
     */
4361
    public static function drawChart($chartData, $hasSerie = false, $chartContainerId = 'chartContainer', $loadLibs = true)
4362
    {
4363
        $htmlChart = '';
4364
        if (api_browser_support('svg')) {
4365
            $serie = [];
4366
            $order = [];
4367
            $data = '';
4368
            foreach ($chartData as $chartDataElement) {
4369
                $data .= '{"';
4370
                $option = str_replace(["\n", "\r"], '', $chartDataElement['option']);
4371
                $serieValue = isset($chartDataElement['serie']) ? $chartDataElement['serie'] : null;
4372
4373
                if (!$hasSerie) {
4374
                    $data .= get_lang('Option').'":"'.$option.'", "';
4375
                    array_push($order, $option);
4376
                } else {
4377
                    if (!is_array($serieValue)) {
4378
                        $data .=
4379
                            get_lang('Option').'":"'.$serieValue.'", "'.
4380
                            get_lang('Score').'":"'.$option.'", "';
4381
                        array_push($serie, $serieValue);
4382
                    } else {
4383
                        $data .=
4384
                            get_lang('Serie').'":"'.$serieValue[0].'", "'.
4385
                            get_lang('Option').'":"'.$serieValue[1].'", "'.
4386
                            get_lang('Score').'":"'.$option.'", "';
4387
                    }
4388
                }
4389
                $data .= get_lang('Votes').'":"'.$chartDataElement['votes'].'"},';
4390
                rtrim($data, ',');
4391
            }
4392
4393
            if ($loadLibs) {
4394
                $htmlChart .= api_get_js('d3/d3.v3.5.4.min.js');
4395
                $htmlChart .= api_get_js('dimple.v2.1.2.min.js');
4396
            }
4397
4398
            $htmlChart .= '
4399
            <script>
4400
                var svg = dimple.newSvg("#'.$chartContainerId.'", 600, 400);
4401
                var data = ['.$data.'];
4402
                var myChart = new dimple.chart(svg, data);
4403
                myChart.setBounds(50, 30, 550, 300);
4404
                var yAxis = myChart.addMeasureAxis("y", "'.get_lang('Votes').'");
4405
                yAxis.fontSize = "14px";
4406
            ';
4407
4408
            if (!$hasSerie) {
4409
                $htmlChart .= '
4410
                    var xAxisCategory = myChart.addCategoryAxis("x", "'.get_lang("Option").'");
4411
                    xAxisCategory.fontSize = "14px";
4412
                    xAxisCategory.addOrderRule('.json_encode($order).');
4413
                    myChart.addSeries("'.get_lang("Option").'", dimple.plot.bar);';
4414
            } else {
4415
                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 4368. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
4416
                    $serie = array_values(array_unique($serie));
4417
                    $htmlChart .= '
4418
                        var xAxisCategory =
4419
                        myChart.addCategoryAxis("x", ["'.get_lang('Option').'","'.get_lang("Score").'"]);
4420
                        xAxisCategory.addOrderRule('.json_encode($serie).');
4421
                        xAxisCategory.addGroupOrderRule("'.get_lang('Score').'");
4422
4423
                        myChart.addSeries("'.get_lang('Option').'", dimple.plot.bar);';
4424
                } else {
4425
                    $htmlChart .= '
4426
                        myChart.addCategoryAxis("x", ["'.get_lang('Option').'","'.get_lang("Score").'"]);
4427
                        myChart.addSeries("'.get_lang('Serie').'", dimple.plot.bar);';
4428
                }
4429
            }
4430
4431
            $htmlChart .= 'myChart.draw();';
4432
            $htmlChart .= '</script>';
4433
        }
4434
4435
        return $htmlChart;
4436
    }
4437
4438
    /**
4439
     * Set a flag to the current survey as answered by the current user.
4440
     *
4441
     * @param string $surveyCode The survey code
4442
     * @param int    $courseId   The course ID
4443
     */
4444
    public static function flagSurveyAsAnswered($surveyCode, $courseId)
4445
    {
4446
        $currentUserId = api_get_user_id();
4447
        $flag = sprintf('%s-%s-%d', $courseId, $surveyCode, $currentUserId);
4448
4449
        if (!isset($_SESSION['filled_surveys'])) {
4450
            $_SESSION['filled_surveys'] = [];
4451
        }
4452
4453
        $_SESSION['filled_surveys'][] = $flag;
4454
    }
4455
4456
    /**
4457
     * Check whether a survey was answered by the current user.
4458
     *
4459
     * @param string $surveyCode The survey code
4460
     * @param int    $courseId   The course ID
4461
     *
4462
     * @return bool
4463
     */
4464
    public static function isSurveyAnsweredFlagged($surveyCode, $courseId)
4465
    {
4466
        $currentUserId = api_get_user_id();
4467
        $flagToCheck = sprintf('%s-%s-%d', $courseId, $surveyCode, $currentUserId);
4468
4469
        if (!isset($_SESSION['filled_surveys'])) {
4470
            return false;
4471
        }
4472
4473
        if (!is_array($_SESSION['filled_surveys'])) {
4474
            return false;
4475
        }
4476
4477
        foreach ($_SESSION['filled_surveys'] as $flag) {
4478
            if ($flagToCheck != $flag) {
4479
                continue;
4480
            }
4481
4482
            return true;
4483
        }
4484
4485
        return false;
4486
    }
4487
4488
    /**
4489
     * Check if the current survey has answers.
4490
     *
4491
     * @param int $surveyId
4492
     *
4493
     * @return bool return true if the survey has answers, false otherwise
4494
     */
4495
    public static function checkIfSurveyHasAnswers($surveyId)
4496
    {
4497
        $tableSurveyAnswer = Database::get_course_table(TABLE_SURVEY_ANSWER);
4498
        $courseId = api_get_course_int_id();
4499
        $surveyId = (int) $surveyId;
4500
4501
        if (empty($courseId) || empty($surveyId)) {
4502
            return false;
4503
        }
4504
4505
        // To select the answers by session
4506
        $sessionId = api_get_session_id();
4507
        $sessionCondition = '';
4508
        if (true === api_get_configuration_value('show_surveys_base_in_sessions')) {
4509
            $sessionCondition = api_get_session_condition($sessionId);
4510
        }
4511
4512
        $sql = "SELECT * FROM $tableSurveyAnswer
4513
                WHERE
4514
                    c_id = $courseId AND
4515
                    survey_id = '".$surveyId."'
4516
                    $sessionCondition
4517
                ORDER BY answer_id, user ASC";
4518
        $result = Database::query($sql);
4519
        $response = Database::affected_rows($result);
4520
4521
        return $response > 0;
4522
    }
4523
4524
    /**
4525
     * Get the pending surveys for a user.
4526
     *
4527
     * @param int $userId
4528
     *
4529
     * @return array
4530
     */
4531
    public static function getUserPendingInvitations($userId)
4532
    {
4533
        $now = api_get_utc_datetime(null, false, true);
4534
4535
        $dql = "
4536
            SELECT s, si FROM ChamiloCourseBundle:CSurvey s
4537
            INNER JOIN ChamiloCourseBundle:CSurveyInvitation si
4538
                WITH (s.code = si.surveyCode AND s.cId = si.cId AND s.sessionId = si.sessionId )
4539
            WHERE
4540
                si.user = :user_id AND
4541
                s.availFrom <= :now AND
4542
                s.availTill >= :now AND
4543
                si.answered = 0
4544
            ORDER BY s.availTill ASC
4545
        ";
4546
4547
        $pendingSurveys = Database::getManager()
4548
            ->createQuery($dql)
4549
            ->setParameters(['user_id' => $userId, 'now' => $now->format('Y-m-d')])
4550
            ->getResult();
4551
4552
        return $pendingSurveys;
4553
    }
4554
4555
    /**
4556
     * @param string $surveyCode
4557
     * @param int    $courseId
4558
     * @param int    $sessionId
4559
     *
4560
     * @return array
4561
     */
4562
    public static function getSentInvitations($surveyCode, $courseId, $sessionId = 0)
4563
    {
4564
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
4565
        $tblSurveyInvitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
4566
4567
        $sessionCondition = api_get_session_condition($sessionId);
4568
        $surveyCode = Database::escape_string($surveyCode);
4569
        $courseId = (int) $courseId;
4570
4571
        $sql = "SELECT survey_invitation.*, user.firstname, user.lastname, user.email
4572
                FROM $tblSurveyInvitation survey_invitation
4573
                LEFT JOIN $tblUser user
4574
                ON (survey_invitation.user = user.id AND survey_invitation.c_id = $courseId)
4575
                WHERE
4576
                    survey_invitation.survey_code = '$surveyCode'
4577
                    AND survey_invitation.c_id = $courseId
4578
                    $sessionCondition";
4579
4580
        $query = Database::query($sql);
4581
4582
        return Database::store_result($query);
4583
    }
4584
4585
    /**
4586
     * @param string $code       invitation code
4587
     * @param array  $courseInfo
4588
     * @param int    $sessionId
4589
     * @param string $surveyCode
4590
     *
4591
     * @return string
4592
     */
4593
    public static function generateFillSurveyLink($code, $courseInfo, $sessionId, $surveyCode = '')
4594
    {
4595
        $code = Security::remove_XSS($code);
4596
        $sessionId = (int) $sessionId;
4597
4598
        if (empty($courseInfo)) {
4599
            return '';
4600
        }
4601
4602
        $params = [
4603
            'invitationcode' => $code,
4604
            'cidReq' => $courseInfo['code'],
4605
            'course' => $courseInfo['code'],
4606
            'id_session' => $sessionId,
4607
        ];
4608
4609
        if (!empty($surveyCode)) {
4610
            $params['scode'] = Security::remove_XSS($surveyCode);
4611
        }
4612
        if (!empty($courseInfo['language'])) {
4613
            $params['language'] = $courseInfo['language'];
4614
        }
4615
4616
        return api_get_path(WEB_CODE_PATH).'survey/fillsurvey.php?'.http_build_query($params);
4617
    }
4618
}
4619