SurveyUtil   F
last analyzed

Complexity

Total Complexity 629

Size/Duplication

Total Lines 4607
Duplicated Lines 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
wmc 629
eloc 2574
c 3
b 2
f 0
dl 0
loc 4607
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
F display_question_report() 0 319 49
F display_question_report_score() 0 122 15
F displayCompleteReport() 0 342 62
D display_complete_report_row() 0 99 23
D export_complete_report_row() 0 124 30
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
A generateFillSurveyLink() 0 24 4
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
A flagSurveyAsAnswered() 0 10 2
A get_number_of_surveys_for_coach() 0 5 1
A get_invitations() 0 19 2
A survey_search_restriction() 0 18 6
F modify_filter() 0 137 17
D export_complete_report_row_xls() 0 85 23
A getUserPendingInvitations() 0 22 1
A update_count_invited() 0 38 3
F export_complete_report_xls() 0 274 39
F export_complete_report() 0 252 39

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') {
1749
                        $numberOfOptions++;
1750
                    }
1751
                    for ($ii = 0; $ii < $numberOfOptions; $ii++) {
1752
                        $return .= str_replace(
1753
                            "\r\n",
1754
                            '  ',
1755
                            api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1756
                        )
1757
                        .';';
1758
                    }
1759
                }
1760
            }
1761
        }
1762
1763
        $return .= "\n";
1764
        // Getting all the questions and options
1765
        $return .= ';';
1766
        // Show the fields names for user fields
1767
        if (!empty($extra_user_fields) && !$survey_data['anonymous']) {
1768
            foreach ($extra_user_fields as &$field) {
1769
                if ($translate) {
1770
                    $field[3] = api_get_filtered_multilingual_HTML_string($field[3], $course['language']);
1771
                }
1772
                $return .= '"'
1773
                    .str_replace(
1774
                        "\r\n",
1775
                        '  ',
1776
                        api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1777
                    )
1778
                    .'";';
1779
            }
1780
        }
1781
1782
        $sql = "SELECT DISTINCT
1783
		            survey_question.question_id,
1784
		            survey_question.survey_id,
1785
		            survey_question.survey_question,
1786
		            survey_question.display,
1787
		            survey_question.sort,
1788
		            survey_question.type,
1789
                    survey_question_option.question_option_id,
1790
                    survey_question_option.option_text,
1791
                    survey_question_option.sort as option_sort
1792
				FROM $table_survey_question survey_question
1793
				LEFT JOIN $table_survey_question_option survey_question_option
1794
				ON
1795
				    survey_question.question_id = survey_question_option.question_id AND
1796
				    survey_question_option.c_id = survey_question.c_id
1797
				WHERE
1798
				    survey_question NOT LIKE '%{{%' AND
1799
				    survey_question.type <> 'pagebreak' AND
1800
				    survey_question.survey_id = $surveyId AND
1801
				    survey_question.c_id = $course_id
1802
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1803
        $result = Database::query($sql);
1804
        $possible_answers = [];
1805
        $possible_answers_type = [];
1806
        $current_question_type = '';
1807
        $current_question_id = null;
1808
        while ($row = Database::fetch_array($result)) {
1809
            // We show the options if
1810
            // 1. there is no question filter and the export button has not been clicked
1811
            // 2. there is a question filter but the question is selected for display
1812
            if ($translate) {
1813
                $row['option_text'] = api_get_filtered_multilingual_HTML_string($row['option_text'], $course['language']);
1814
            }
1815
            if (!(isset($_POST['submit_question_filter'.$suffixLpItem])) || (
1816
                is_array($_POST['questions_filter'.$suffixLpItem]) &&
1817
                in_array($row['question_id'], $_POST['questions_filter'.$suffixLpItem])
1818
            )
1819
            ) {
1820
                if ($current_question_id != $row['question_id']) {
1821
                    if ($current_question_type == 'multiplechoiceother') {
1822
                        $return .= api_html_entity_decode(strip_tags(get_lang('Comment')), ENT_QUOTES).';';
1823
                    }
1824
                }
1825
1826
                $current_question_type = $row['type'];
1827
                $current_question_id = $row['question_id'];
1828
1829
                $row['option_text'] = str_replace(["\r", "\n"], ['', ''], $row['option_text']);
1830
                if (!$compact) {
1831
                    $return .= api_html_entity_decode(strip_tags($row['option_text']), ENT_QUOTES).';';
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') {
2158
                        $numberOfOptions++;
2159
                    }
2160
                    for ($ii = 0; $ii < $numberOfOptions; $ii++) {
2161
                        $worksheet->setCellValueByColumnAndRow(
2162
                            $column,
2163
                            $line,
2164
                            api_html_entity_decode(
2165
                                strip_tags($row['survey_question']),
2166
                                ENT_QUOTES
2167
                            )
2168
                        );
2169
                        $column++;
2170
                    }
2171
                }
2172
            }
2173
        }
2174
2175
        $line++;
2176
        $column = 1;
2177
        // Show extra field values
2178
        if ($display_extra_user_fields && !$survey_data['anonymous']) {
2179
            // Show the fields names for user fields
2180
            foreach ($extra_user_fields as &$field) {
2181
                $worksheet->setCellValueByColumnAndRow(
2182
                    $column,
2183
                    $line,
2184
                    api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
2185
                );
2186
                $column++;
2187
            }
2188
        }
2189
2190
        // Getting all the questions and options (second line)
2191
        $sql = "SELECT
2192
                    survey_question.question_id,
2193
                    survey_question.survey_id,
2194
                    survey_question.survey_question,
2195
                    survey_question.display,
2196
                    survey_question.sort,
2197
                    survey_question.type,
2198
                    survey_question_option.question_option_id,
2199
                    survey_question_option.option_text,
2200
                    survey_question_option.sort as option_sort
2201
				FROM $table_survey_question survey_question
2202
				LEFT JOIN $table_survey_question_option survey_question_option
2203
				ON
2204
				    survey_question.question_id = survey_question_option.question_id AND
2205
				    survey_question_option.c_id = survey_question.c_id
2206
				WHERE
2207
				    survey_question NOT LIKE '%{{%' AND
2208
				    survey_question.type <> 'pagebreak' AND
2209
				    survey_question.survey_id = $surveyId AND
2210
				    survey_question.c_id = $course_id
2211
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
2212
        $result = Database::query($sql);
2213
        $possible_answers = [];
2214
        $possible_answers_type = [];
2215
        $current_question_type = '';
2216
        $current_question_id = null;
2217
        while ($row = Database::fetch_array($result)) {
2218
            // We show the options if
2219
            // 1. there is no question filter and the export button has not been clicked
2220
            // 2. there is a quesiton filter but the question is selected for display
2221
            if (!isset($_POST['submit_question_filter'.$suffixLpItem]) ||
2222
                (isset($_POST['questions_filter'.$suffixLpItem]) && is_array($_POST['questions_filter'.$suffixLpItem]) &&
2223
                in_array($row['question_id'], $_POST['questions_filter'.$suffixLpItem]))
2224
            ) {
2225
                if ($current_question_id != $row['question_id']) {
2226
                    if ($current_question_type == 'multiplechoiceother') {
2227
                        $worksheet->setCellValueByColumnAndRow(
2228
                            $column,
2229
                            $line,
2230
                            api_html_entity_decode(
2231
                                strip_tags(get_lang('Comment')),
2232
                                ENT_QUOTES
2233
                            )
2234
                        );
2235
                        $column++;
2236
                    }
2237
                }
2238
2239
                $current_question_type = $row['type'];
2240
                $current_question_id = $row['question_id'];
2241
2242
                $worksheet->setCellValueByColumnAndRow(
2243
                    $column,
2244
                    $line,
2245
                    api_html_entity_decode(
2246
                        strip_tags($row['option_text']),
2247
                        ENT_QUOTES
2248
                    )
2249
                );
2250
                $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
2251
                $possible_answers_type[$row['question_id']] = $row['type'];
2252
                $column++;
2253
            }
2254
        }
2255
2256
        if ($current_question_type == 'multiplechoiceother') {
2257
            $worksheet->setCellValueByColumnAndRow(
2258
                $column,
2259
                $line,
2260
                api_html_entity_decode(
2261
                    strip_tags(get_lang('Comment')),
2262
                    ENT_QUOTES
2263
                )
2264
            );
2265
        }
2266
2267
        // To select the answers by Lp item
2268
        $lpItemCondition = '';
2269
        if (api_get_configuration_value('allow_survey_tool_in_lp')) {
2270
            $lpItemCondition = " AND c_lp_item_id = $lpItemId";
2271
        }
2272
2273
        // Getting all the answers of the users
2274
        $line++;
2275
        $column = 0;
2276
        $old_user = '';
2277
        $answers_of_user = [];
2278
        $sql = "SELECT * FROM $table_survey_answer
2279
                WHERE c_id = $course_id AND survey_id = $surveyId $sessionCondition $lpItemCondition";
2280
        if ($user_id != 0) {
2281
            $sql .= " AND user='".$user_id."' ";
2282
        }
2283
        $sql .= ' ORDER BY user ASC';
2284
2285
        $open_question_iterator = 1;
2286
        $result = Database::query($sql);
2287
        while ($row = Database::fetch_array($result)) {
2288
            if ($old_user != $row['user'] && $old_user != '') {
2289
                $return = self::export_complete_report_row_xls(
2290
                    $survey_data,
2291
                    $possible_answers,
2292
                    $answers_of_user,
2293
                    $old_user,
2294
                    !$survey_data['anonymous'],
2295
                    $possible_answers_type
2296
                );
2297
                foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
2298
                    $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
2299
                    $column++;
2300
                }
2301
                $answers_of_user = [];
2302
                $line++;
2303
                $column = 0;
2304
            }
2305
            if ($possible_answers_type[$row['question_id']] === 'open' ||
2306
                $possible_answers_type[$row['question_id']] === 'comment'
2307
            ) {
2308
                $temp_id = 'open'.$open_question_iterator;
2309
                $answers_of_user[$row['question_id']][$temp_id] = $row;
2310
                $open_question_iterator++;
2311
            } else {
2312
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
2313
            }
2314
            $old_user = $row['user'];
2315
        }
2316
2317
        $return = self::export_complete_report_row_xls(
2318
            $survey_data,
2319
            $possible_answers,
2320
            $answers_of_user,
2321
            $old_user,
2322
            true,
2323
            $possible_answers_type
2324
        );
2325
2326
        // this is to display the last user
2327
        foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
2328
            $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
2329
            $column++;
2330
        }
2331
2332
        $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
2333
        $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
2334
        $writer->save($file);
2335
2336
        if ($returnFile) {
2337
            return $file;
2338
        }
2339
2340
        DocumentManager::file_send_for_download($file, true, $filename);
2341
2342
        return null;
2343
    }
2344
2345
    /**
2346
     * Add a line to the csv file.
2347
     *
2348
     * @param array Possible answers
2349
     * @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...
2350
     * @param mixed User ID or user details as string - Used as a string in the result string
2351
     * @param bool Whether to display user fields or not
2352
     *
2353
     * @return string One line of the csv file
2354
     */
2355
    public static function export_complete_report_row_xls(
2356
        $survey_data,
2357
        $possible_options,
2358
        $answers_of_user,
2359
        $user,
2360
        $display_extra_user_fields = false,
2361
        $questionTypes = true
2362
    ) {
2363
        $return = [];
2364
        if ($survey_data['anonymous'] == 0) {
2365
            if (intval($user) !== 0) {
2366
                $userInfo = api_get_user_info($user);
2367
                if ($userInfo) {
2368
                    $user_displayed = $userInfo['complete_name_with_username'];
2369
                } else {
2370
                    $user_displayed = '-';
2371
                }
2372
                $return[] = $user_displayed;
2373
            } else {
2374
                $return[] = $user;
2375
            }
2376
        } else {
2377
            $return[] = '-'; // The user column
2378
        }
2379
2380
        if ($display_extra_user_fields) {
2381
            //show user fields data, if any, for this user
2382
            $user_fields_values = UserManager::get_extra_user_data(
2383
                $user,
2384
                false,
2385
                false,
2386
                false,
2387
                true
2388
            );
2389
            foreach ($user_fields_values as $fieldName => $value) {
2390
                $fieldValue = is_array($value) ? $value[$fieldName] : $value;
2391
                $return[] = api_html_entity_decode(strip_tags($fieldValue), ENT_QUOTES);
2392
            }
2393
        }
2394
2395
        if (is_array($possible_options)) {
2396
            foreach ($possible_options as $question_id => &$possible_option) {
2397
                $otherPaddingNeeded = ($questionTypes[$question_id] == 'multiplechoiceother' ? true : false);
2398
                if (is_array($possible_option) && count($possible_option) > 0) {
2399
                    foreach ($possible_option as $option_id => &$value) {
2400
                        $my_answers_of_user = isset($answers_of_user[$question_id])
2401
                            ? $answers_of_user[$question_id]
2402
                            : [];
2403
                        $key = array_keys($my_answers_of_user);
2404
                        if (isset($key[0]) && substr($key[0], 0, 4) == 'open') {
2405
                            $return[] = api_html_entity_decode(
2406
                                strip_tags($answers_of_user[$question_id][$key[0]]['option_id']),
2407
                                ENT_QUOTES
2408
                            );
2409
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
2410
                            if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
2411
                                $return[] = $answers_of_user[$question_id][$option_id]['value'];
2412
                            } else {
2413
                                $return[] = 'v';
2414
                            }
2415
                        } elseif (isset($key[0]) && strpos($key[0], '@:@') !== false) {
2416
                            list($idAnswer, $other) = explode('@:@', $key[0]);
2417
                            if ($idAnswer == $option_id) {
2418
                                if (strlen($other) > 0) {
2419
                                    $return[] = 'v';
2420
                                    $return[] = api_html_entity_decode(strip_tags($other), ENT_QUOTES);
2421
                                    $otherPaddingNeeded = false;
2422
                                } else {
2423
                                    $return[] = 'v';
2424
                                }
2425
                            } else {
2426
                                $return[] = '';
2427
                            }
2428
                        } else {
2429
                            $return[] = '';
2430
                        }
2431
                    }
2432
                    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...
2433
                        $return[] = '';
2434
                    }
2435
                }
2436
            }
2437
        }
2438
2439
        return $return;
2440
    }
2441
2442
    /**
2443
     * This function displays the comparative report which
2444
     * allows you to compare two questions
2445
     * A comparative report creates a table where one question
2446
     * is on the x axis and a second question is on the y axis.
2447
     * In the intersection is the number of people who have
2448
     * answered positive on both options.
2449
     *
2450
     * @return string HTML code
2451
     *
2452
     * @author Patrick Cool <[email protected]>, Ghent University
2453
     *
2454
     * @version February 2007
2455
     */
2456
    public static function display_comparative_report()
2457
    {
2458
        // Allowed question types for comparative report
2459
        $allowed_question_types = [
2460
            'yesno',
2461
            'multiplechoice',
2462
            'multipleresponse',
2463
            'dropdown',
2464
            'percentage',
2465
            'score',
2466
        ];
2467
2468
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
2469
2470
        // Getting all the questions
2471
        $questions = SurveyManager::get_questions($surveyId);
2472
2473
        // Actions bar
2474
        echo '<div class="actions">';
2475
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq()
2476
            .'">'
2477
            .Display::return_icon(
2478
                'back.png',
2479
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
2480
                [],
2481
                ICON_SIZE_MEDIUM
2482
            )
2483
            .'</a>';
2484
        echo '</div>';
2485
2486
        // Displaying an information message that only the questions with predefined answers can be used in a comparative report
2487
        echo Display::return_message(get_lang('OnlyQuestionsWithPredefinedAnswers'), 'normal', false);
2488
2489
        $xAxis = isset($_GET['xaxis']) ? Security::remove_XSS($_GET['xaxis']) : '';
2490
        $yAxis = isset($_GET['yaxis']) ? Security::remove_XSS($_GET['yaxis']) : '';
2491
        $course_id = api_get_course_int_id();
2492
        $lpItemId = isset($_REQUEST['lp_item']) ? (int) $_REQUEST['lp_item'] : '';
2493
        $sessionId = api_get_session_id();
2494
2495
        $url = api_get_self().'?'.api_get_cidreq().'&action='.Security::remove_XSS($_GET['action'])
2496
            .'&survey_id='.$surveyId.'&xaxis='.$xAxis.'&y='.$yAxis;
2497
2498
        $form = new FormValidator('compare', 'get', $url);
2499
        $form->addHidden('action', Security::remove_XSS($_GET['action']));
2500
        $form->addHidden('survey_id', $surveyId);
2501
        $optionsX = ['----'];
2502
        $optionsY = ['----'];
2503
        $defaults = [];
2504
        foreach ($questions as &$question) {
2505
            // Ignored tagged questions
2506
            if ($question) {
2507
                if (strpos($question['question'], '{{') !== false) {
2508
                    $question = null;
2509
                    continue;
2510
                }
2511
            }
2512
            if (is_array($allowed_question_types)) {
2513
                if (in_array($question['type'], $allowed_question_types)) {
2514
                    if (isset($_GET['xaxis']) && $_GET['xaxis'] == $question['question_id']) {
2515
                        $defaults['xaxis'] = $question['question_id'];
2516
                    }
2517
2518
                    if (isset($_GET['yaxis']) && $_GET['yaxis'] == $question['question_id']) {
2519
                        $defaults['yaxis'] = $question['question_id'];
2520
                    }
2521
                    $question['question'] = Security::remove_XSS($question['question']);
2522
2523
                    $optionsX[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
2524
                    $optionsY[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
2525
                }
2526
            }
2527
        }
2528
2529
        if (api_get_configuration_value('allow_survey_tool_in_lp')) {
2530
            self::addSelectLpItemsForm($surveyId, $course_id, $sessionId, 'comparativereport', $form);
2531
        }
2532
2533
        $form->addSelect('xaxis', get_lang('SelectXAxis'), $optionsX);
2534
        $form->addSelect('yaxis', get_lang('SelectYAxis'), $optionsY);
2535
2536
        $form->addButtonSearch(get_lang('CompareQuestions'));
2537
        $form->setDefaults($defaults);
2538
        $form->display();
2539
2540
        // Getting all the information of the x axis
2541
        if (!empty($xAxis)) {
2542
            $question_x = SurveyManager::get_question($xAxis);
2543
        }
2544
2545
        // Getting all the information of the y axis
2546
        if (!empty($yAxis)) {
2547
            $question_y = SurveyManager::get_question($yAxis);
2548
        }
2549
2550
        if (!empty($xAxis) && !empty($yAxis)) {
2551
            // Getting the answers of the two questions
2552
            $answers_x = self::get_answers_of_question_by_user($surveyId, $xAxis, $lpItemId);
2553
            $answers_y = self::get_answers_of_question_by_user($surveyId, $yAxis, $lpItemId);
2554
2555
            // Displaying the table
2556
            $tableHtml = '<table border="1" class="table table-hover table-striped data_table">';
2557
            $xOptions = [];
2558
            // The header
2559
            $tableHtml .= '<tr>';
2560
            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...
2561
                if ($ii == 0) {
2562
                    $tableHtml .= '<th>&nbsp;</th>';
2563
                } else {
2564
                    if ($question_x['type'] === 'score') {
2565
                        for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2566
                            $tableHtml .= '<th>'.Security::remove_XSS($question_x['answers'][($ii - 1)]).'<br />'.$x.'</th>';
2567
                        }
2568
                        $x = '';
2569
                    } else {
2570
                        $tableHtml .= '<th>'.Security::remove_XSS($question_x['answers'][($ii - 1)]).'</th>';
2571
                    }
2572
                    $optionText = strip_tags($question_x['answers'][$ii - 1]);
2573
                    $optionText = html_entity_decode($optionText);
2574
                    $optionText = Security::remove_XSS($optionText);
2575
                    array_push($xOptions, trim($optionText));
2576
                }
2577
            }
2578
            $tableHtml .= '</tr>';
2579
            $chartData = [];
2580
            // The main part
2581
            for ($ij = 0; $ij < count($question_y['answers']); $ij++) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_y does not seem to be defined for all execution paths leading up to this point.
Loading history...
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

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

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

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2582
                $currentYQuestion = strip_tags($question_y['answers'][$ij]);
2583
                $currentYQuestion = html_entity_decode($currentYQuestion);
2584
                // The Y axis is a scoring question type so we have more rows than the options (actually options * maximum score)
2585
                if ($question_y['type'] == 'score') {
2586
                    for ($y = 1; $y <= $question_y['maximum_score']; $y++) {
2587
                        $tableHtml .= '<tr>';
2588
                        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...
2589
                            if ($question_x['type'] == 'score') {
2590
                                for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2591
                                    if ($ii == 0) {
2592
                                        $tableHtml .= '<th>'.Security::remove_XSS($question_y['answers'][($ij)]).' '.$y.'</th>';
2593
                                        break;
2594
                                    } else {
2595
                                        $tableHtml .= '<td align="center">';
2596
                                        $votes = self::comparative_check(
2597
                                            $answers_x,
2598
                                            $answers_y,
2599
                                            $question_x['answersid'][($ii - 1)],
2600
                                            $question_y['answersid'][($ij)],
2601
                                            $x,
2602
                                            $y
2603
                                        );
2604
                                        $tableHtml .= $votes;
2605
                                        array_push(
2606
                                            $chartData,
2607
                                            [
2608
                                                'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2609
                                                'option' => $x,
2610
                                                'votes' => $votes,
2611
                                            ]
2612
                                        );
2613
                                        $tableHtml .= '</td>';
2614
                                    }
2615
                                }
2616
                            } else {
2617
                                if ($ii == 0) {
2618
                                    $tableHtml .= '<th>'.Security::remove_XSS($question_y['answers'][$ij]).' '.$y.'</th>';
2619
                                } else {
2620
                                    $tableHtml .= '<td align="center">';
2621
                                    $votes = self::comparative_check(
2622
                                        $answers_x,
2623
                                        $answers_y,
2624
                                        $question_x['answersid'][($ii - 1)],
2625
                                        $question_y['answersid'][($ij)],
2626
                                        0,
2627
                                        $y
2628
                                    );
2629
                                    $tableHtml .= $votes;
2630
                                    array_push(
2631
                                        $chartData,
2632
                                        [
2633
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2634
                                            'option' => $y,
2635
                                            'votes' => $votes,
2636
                                        ]
2637
                                    );
2638
                                    $tableHtml .= '</td>';
2639
                                }
2640
                            }
2641
                        }
2642
                        $tableHtml .= '</tr>';
2643
                    }
2644
                } else {
2645
                    // The Y axis is NOT a score question type so the number of rows = the number of options
2646
                    $tableHtml .= '<tr>';
2647
                    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...
2648
                        if ($question_x['type'] === 'score') {
2649
                            for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
2650
                                if ($ii == 0) {
2651
                                    $tableHtml .= '<th>'.Security::remove_XSS($question_y['answers'][$ij]).'</th>';
2652
                                    break;
2653
                                } else {
2654
                                    $tableHtml .= '<td align="center">';
2655
                                    $votes = self::comparative_check(
2656
                                        $answers_x,
2657
                                        $answers_y,
2658
                                        $question_x['answersid'][($ii - 1)],
2659
                                        $question_y['answersid'][($ij)],
2660
                                        $x,
2661
                                        0
2662
                                    );
2663
                                    $tableHtml .= $votes;
2664
                                    array_push(
2665
                                        $chartData,
2666
                                        [
2667
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2668
                                            'option' => $x,
2669
                                            'votes' => $votes,
2670
                                        ]
2671
                                    );
2672
                                    $tableHtml .= '</td>';
2673
                                }
2674
                            }
2675
                        } else {
2676
                            if ($ii == 0) {
2677
                                $tableHtml .= '<th>'.Security::remove_XSS($question_y['answers'][($ij)]).'</th>';
2678
                            } else {
2679
                                $tableHtml .= '<td align="center">';
2680
                                $votes = self::comparative_check(
2681
                                    $answers_x,
2682
                                    $answers_y,
2683
                                    $question_x['answersid'][($ii - 1)],
2684
                                    $question_y['answersid'][($ij)]
2685
                                );
2686
                                $tableHtml .= $votes;
2687
                                array_push(
2688
                                    $chartData,
2689
                                    [
2690
                                        'serie' => $xOptions[$ii - 1],
2691
                                        'option' => $currentYQuestion,
2692
                                        'votes' => $votes,
2693
                                    ]
2694
                                );
2695
                                $tableHtml .= '</td>';
2696
                            }
2697
                        }
2698
                    }
2699
                    $tableHtml .= '</tr>';
2700
                }
2701
            }
2702
            $tableHtml .= '</table>';
2703
            echo '<div id="chartContainer" class="col-md-12">';
2704
            echo self::drawChart($chartData, true);
2705
            echo '</div>';
2706
            echo $tableHtml;
2707
        }
2708
    }
2709
2710
    /**
2711
     * Get all the answers of a question grouped by user.
2712
     *
2713
     * @param int $survey_id   Survey ID
2714
     * @param int $question_id Question ID
2715
     *
2716
     * @return array Array containing all answers of all users, grouped by user
2717
     *
2718
     * @author Patrick Cool <[email protected]>, Ghent University
2719
     *
2720
     * @version February 2007 - Updated March 2008
2721
     */
2722
    public static function get_answers_of_question_by_user($survey_id, $question_id, $lpItemId = 0)
2723
    {
2724
        $course_id = api_get_course_int_id();
2725
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
2726
        $sessionId = api_get_session_id();
2727
2728
        // To select the answers by session
2729
        $sessionCondition = '';
2730
        if (api_get_configuration_value('show_surveys_base_in_sessions')) {
2731
            if (!empty($sessionId)) {
2732
                $sessionCondition = api_get_session_condition($sessionId);
2733
            }
2734
        }
2735
        // To select the answers by Lp item
2736
        $lpItemCondition = '';
2737
        if (api_get_configuration_value('allow_survey_tool_in_lp') && !empty($lpItemId)) {
2738
            $lpItemCondition = " AND c_lp_item_id = $lpItemId";
2739
        }
2740
2741
        $sql = "SELECT * FROM $table_survey_answer
2742
                WHERE
2743
                  c_id = $course_id AND
2744
                  survey_id='".intval($survey_id)."' AND
2745
                  question_id='".intval($question_id)."'
2746
                  $sessionCondition
2747
                  $lpItemCondition
2748
                ORDER BY USER ASC";
2749
        $result = Database::query($sql);
2750
        $return = [];
2751
        while ($row = Database::fetch_array($result)) {
2752
            if ($row['value'] == 0) {
2753
                $return[$row['user']][] = $row['option_id'];
2754
            } else {
2755
                $return[$row['user']][] = $row['option_id'].'*'.$row['value'];
2756
            }
2757
        }
2758
2759
        return $return;
2760
    }
2761
2762
    /**
2763
     * Count the number of users who answer positively on both options.
2764
     *
2765
     * @param array All answers of the x axis
2766
     * @param array All answers of the y axis
2767
     * @param int x axis value (= the option_id of the first question)
2768
     * @param int y axis value (= the option_id of the second question)
2769
     *
2770
     * @return int Number of users who have answered positively to both options
2771
     *
2772
     * @author Patrick Cool <[email protected]>, Ghent University
2773
     *
2774
     * @version February 2007
2775
     */
2776
    public static function comparative_check(
2777
        $answers_x,
2778
        $answers_y,
2779
        $option_x,
2780
        $option_y,
2781
        $value_x = 0,
2782
        $value_y = 0
2783
    ) {
2784
        if ($value_x == 0) {
2785
            $check_x = $option_x;
2786
        } else {
2787
            $check_x = $option_x.'*'.$value_x;
2788
        }
2789
        if ($value_y == 0) {
2790
            $check_y = $option_y;
2791
        } else {
2792
            $check_y = $option_y.'*'.$value_y;
2793
        }
2794
2795
        $counter = 0;
2796
        if (is_array($answers_x)) {
2797
            foreach ($answers_x as $user => &$answers) {
2798
                // Check if the user has given $option_x as answer
2799
                if (in_array($check_x, $answers)) {
2800
                    // Check if the user has given $option_y as an answer
2801
                    if (!is_null($answers_y[$user]) &&
2802
                        in_array($check_y, $answers_y[$user])
2803
                    ) {
2804
                        $counter++;
2805
                    }
2806
                }
2807
            }
2808
        }
2809
2810
        return $counter;
2811
    }
2812
2813
    public static function saveInviteMail(CSurvey $survey, $content, $subject, $remind)
2814
    {
2815
        // Reminder or not
2816
        if ($remind) {
2817
            $survey->setReminderMail($content);
2818
        } else {
2819
            $survey->setInviteMail($content);
2820
        }
2821
2822
        $survey->setMailSubject($subject);
2823
        $em = Database::getManager();
2824
        $em->persist($survey);
2825
        $em->flush();
2826
    }
2827
2828
    /**
2829
     * This function saves all the invitations of course users
2830
     * and additional users in the database
2831
     * and sends the invitations by email.
2832
     *
2833
     * @param int    $surveyId
2834
     * @param array  $users_array       Users array can be both a list of course uids AND a list of additional email addresses
2835
     * @param string $invitation_title  title of the mail
2836
     * @param string $invitation_text   text of the mail has to contain a **link** string or
2837
     *                                  this will automatically be added to the end
2838
     * @param int    $reminder
2839
     * @param bool   $sendmail
2840
     * @param int    $remindUnAnswered
2841
     * @param bool   $isAdditionalEmail
2842
     * @param bool   $hideLink
2843
     *
2844
     * @author Patrick Cool <[email protected]>, Ghent University
2845
     * @author Julio Montoya - Adding auto-generated link support
2846
     *
2847
     * @version January 2007
2848
     */
2849
    public static function saveInvitations(
2850
        $surveyId,
2851
        $users_array,
2852
        $invitation_title,
2853
        $invitation_text,
2854
        $reminder = 0,
2855
        $sendmail = false,
2856
        $remindUnAnswered = 0,
2857
        $isAdditionalEmail = false,
2858
        $hideLink = false
2859
    ) {
2860
        $surveyId = (int) $surveyId;
2861
        if (!is_array($users_array)) {
2862
            return 0;
2863
        }
2864
2865
        // Getting the survey information
2866
        $survey_data = SurveyManager::get_survey($surveyId);
2867
        $survey_invitations = self::get_invitations($survey_data['survey_code']);
2868
        $already_invited = self::get_invited_users($survey_data['code']);
2869
2870
        // Remind unanswered is a special version of remind all reminder
2871
        $exclude_users = [];
2872
        if (1 == $remindUnAnswered) {
2873
            // Remind only unanswered users
2874
            $reminder = 1;
2875
            $exclude_users = SurveyManager::get_people_who_filled_survey($surveyId);
2876
        }
2877
2878
        $counter = 0; // Nr of invitations "sent" (if sendmail option)
2879
        $course_id = api_get_course_int_id();
2880
        $session_id = api_get_session_id();
2881
2882
        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...
2883
            $result = CourseManager::separateUsersGroups($users_array);
2884
            $groupList = $result['groups'];
2885
            $users_array = $result['users'];
2886
2887
            foreach ($groupList as $groupId) {
2888
                $userGroupList = GroupManager::getStudents($groupId, true);
2889
                $userGroupIdList = array_column($userGroupList, 'user_id');
2890
                $users_array = array_merge($users_array, $userGroupIdList);
2891
2892
                $params = [
2893
                    'c_id' => $course_id,
2894
                    'session_id' => $session_id,
2895
                    'group_id' => $groupId,
2896
                    'survey_code' => $survey_data['code'],
2897
                ];
2898
2899
                $invitationExists = self::invitationExists(
2900
                    $course_id,
2901
                    $session_id,
2902
                    $groupId,
2903
                    $survey_data['code']
2904
                );
2905
                if (empty($invitationExists)) {
2906
                    self::save_invitation($params);
2907
                }
2908
            }
2909
        }
2910
2911
        $users_array = array_unique($users_array);
2912
        foreach ($users_array as $key => $value) {
2913
            if (!isset($value) || '' == $value) {
2914
                continue;
2915
            }
2916
2917
            // Skip user if reminding only unanswered people
2918
            if (in_array($value, $exclude_users)) {
2919
                continue;
2920
            }
2921
            // Get the unique invitation code if we already have it
2922
            if ($reminder == 1 && array_key_exists($value, $survey_invitations)) {
2923
                $invitation_code = $survey_invitations[$value]['invitation_code'];
2924
            } else {
2925
                $invitation_code = md5($value.microtime());
2926
            }
2927
            $new_user = false; // User not already invited
2928
            // Store the invitation if user_id not in $already_invited['course_users'] OR email is not in $already_invited['additional_users']
2929
            $addit_users_array = isset($already_invited['additional_users']) && !empty($already_invited['additional_users'])
2930
                    ? explode(';', $already_invited['additional_users'])
2931
                    : [];
2932
            $my_alredy_invited = $already_invited['course_users'] == null ? [] : $already_invited['course_users'];
2933
            if ((is_numeric($value) && !in_array($value, $my_alredy_invited)) ||
2934
                (!is_numeric($value) && !in_array($value, $addit_users_array))
2935
            ) {
2936
                $new_user = true;
2937
                if (!array_key_exists($value, $survey_invitations)) {
2938
                    $params = [
2939
                        'c_id' => $course_id,
2940
                        'session_id' => $session_id,
2941
                        'user' => $value,
2942
                        'survey_code' => $survey_data['code'],
2943
                        'invitation_code' => $invitation_code,
2944
                        'invitation_date' => api_get_utc_datetime(),
2945
                    ];
2946
                    self::save_invitation($params);
2947
                }
2948
            }
2949
2950
            // Send the email if checkboxed
2951
            if (($new_user || $reminder == 1) && $sendmail) {
2952
                // Make a change for absolute url
2953
                if (isset($invitation_text)) {
2954
                    $invitation_text = api_html_entity_decode($invitation_text, ENT_QUOTES);
2955
                    $invitation_text = str_replace('src="../../', 'src="'.api_get_path(WEB_PATH), $invitation_text);
2956
                    $invitation_text = trim(stripslashes($invitation_text));
2957
                }
2958
                self::send_invitation_mail(
2959
                    $value,
2960
                    $invitation_code,
2961
                    $invitation_title,
2962
                    $invitation_text,
2963
                    $hideLink
2964
                );
2965
                $counter++;
2966
            }
2967
        }
2968
2969
        return $counter; // Number of invitations sent
2970
    }
2971
2972
    /**
2973
     * @param $params
2974
     *
2975
     * @return bool|int
2976
     */
2977
    public static function save_invitation($params)
2978
    {
2979
        // Database table to store the invitations data
2980
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2981
        if (!empty($params['c_id']) &&
2982
            (!empty($params['user']) || !empty($params['group_id'])) &&
2983
            !empty($params['survey_code'])
2984
        ) {
2985
            if (!isset($params['survey_invitation_id'])) {
2986
                $params['survey_invitation_id'] = 0;
2987
            }
2988
            if (!isset($params['answered'])) {
2989
                $params['answered'] = 0;
2990
            }
2991
            if (!isset($params['group_id'])) {
2992
                $params['group_id'] = 0;
2993
            }
2994
            $insertId = Database::insert($table, $params);
2995
            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...
2996
                $sql = "UPDATE $table
2997
                        SET survey_invitation_id = $insertId
2998
                        WHERE iid = $insertId";
2999
                Database::query($sql);
3000
            }
3001
3002
            return $insertId;
3003
        }
3004
3005
        return false;
3006
    }
3007
3008
    /**
3009
     * @param int    $courseId
3010
     * @param int    $sessionId
3011
     * @param int    $groupId
3012
     * @param string $surveyCode
3013
     *
3014
     * @return int
3015
     */
3016
    public static function invitationExists($courseId, $sessionId, $groupId, $surveyCode)
3017
    {
3018
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
3019
        $courseId = (int) $courseId;
3020
        $sessionId = (int) $sessionId;
3021
        $groupId = (int) $groupId;
3022
        $surveyCode = Database::escape_string($surveyCode);
3023
3024
        $sql = "SELECT survey_invitation_id FROM $table
3025
                WHERE
3026
                    c_id = $courseId AND
3027
                    session_id = $sessionId AND
3028
                    group_id = $groupId AND
3029
                    survey_code = '$surveyCode'
3030
                ";
3031
        $result = Database::query($sql);
3032
3033
        return Database::num_rows($result);
3034
    }
3035
3036
    /**
3037
     * Send the invitation by mail.
3038
     *
3039
     * @param int invitedUser - the userId (course user) or emailaddress of additional user
3040
     * $param string $invitation_code - the unique invitation code for the URL
3041
     */
3042
    public static function send_invitation_mail(
3043
        $invitedUser,
3044
        $invitation_code,
3045
        $invitation_title,
3046
        $invitation_text,
3047
        $hideLink = false
3048
    ) {
3049
        $_user = api_get_user_info();
3050
        $_course = api_get_course_info();
3051
        $sessionId = api_get_session_id();
3052
3053
        // Replacing the **link** part with a valid link for the user
3054
        $link = self::generateFillSurveyLink($invitation_code, $_course, $sessionId);
3055
        if ($hideLink) {
3056
            $full_invitation_text = str_replace('**link**', '', $invitation_text);
3057
        } else {
3058
            $text_link = '<a href="'.$link.'">'.get_lang('ClickHereToAnswerTheSurvey')."</a><br />\r\n<br />\r\n"
3059
                .get_lang('OrCopyPasteTheFollowingUrl')." <br /> \r\n <br /> \r\n ".$link;
3060
3061
            $replace_count = 0;
3062
            $full_invitation_text = api_str_ireplace('**link**', $text_link, $invitation_text, $replace_count);
3063
            if ($replace_count < 1) {
3064
                $full_invitation_text = $full_invitation_text."<br />\r\n<br />\r\n".$text_link;
3065
            }
3066
        }
3067
3068
        // Sending the mail
3069
        $sender_name = api_get_person_name($_user['firstName'], $_user['lastName'], null, PERSON_NAME_EMAIL_ADDRESS);
3070
        $sender_email = $_user['mail'];
3071
        $sender_user_id = api_get_user_id();
3072
3073
        $replyto = [];
3074
        if (api_get_setting('survey_email_sender_noreply') == 'noreply') {
3075
            $noreply = api_get_setting('noreply_email_address');
3076
            if (!empty($noreply)) {
3077
                $replyto['Reply-to'] = $noreply;
3078
                $sender_name = $noreply;
3079
                $sender_email = $noreply;
3080
                $sender_user_id = null;
3081
            }
3082
        }
3083
3084
        // Optionally: finding the e-mail of the course user
3085
        if (is_numeric($invitedUser)) {
3086
            MessageManager::send_message(
3087
                $invitedUser,
3088
                $invitation_title,
3089
                $full_invitation_text,
3090
                [],
3091
                [],
3092
                null,
3093
                null,
3094
                null,
3095
                null,
3096
                $sender_user_id,
3097
                true
3098
            );
3099
        } else {
3100
            $extraParameters = [];
3101
            if (api_get_configuration_value('mail_header_from_custom_course_logo') == true) {
3102
                $extraParameters = ['logo' => CourseManager::getCourseEmailPicture($_course)];
3103
            }
3104
3105
            @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

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