SurveyUtil::checkIfSurveyHasAnswers()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 16
c 0
b 0
f 0
dl 0
loc 27
rs 9.7333
cc 4
nc 3
nop 1
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
                            if (isset($answers_of_user[$question_id])) {
1608
                                foreach ($answers_of_user[$question_id] as $key => $newValue) {
1609
                                    $parts = ch_multiplechoiceother::decodeOptionValue($key);
1610
                                    if (isset($parts[0])) {
1611
                                        $data = $answers_of_user[$question_id][$key];
1612
                                        unset($answers_of_user[$question_id][$key]);
1613
                                        $newKey = $parts[0];
1614
                                        $answers_of_user[$question_id][$newKey] = $data;
1615
                                    }
1616
                                }
1617
                            }
1618
                        }
1619
                        if ($questions[$question_id]['type'] === 'percentage') {
1620
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1621
                                $content .= "<td align='center'>";
1622
                                $content .= $answers_of_user[$question_id][$option_id]['value'];
1623
                                $content .= "</td>";
1624
                            }
1625
                        } else {
1626
                            $content .= '<td align="center">';
1627
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1628
                                if (0 != $answers_of_user[$question_id][$option_id]['value']) {
1629
                                    $content .= $answers_of_user[$question_id][$option_id]['value'];
1630
                                } else {
1631
                                    $content .= 'v';
1632
                                }
1633
                            }
1634
                        }
1635
                    }
1636
                }
1637
            }
1638
        }
1639
1640
        $content .= '</tr>';
1641
1642
        return $content;
1643
    }
1644
1645
    /**
1646
     * Quite similar to display_complete_report(), returns an HTML string
1647
     * that can be used in a csv file.
1648
     *
1649
     * @param array $survey_data The basic survey data as initially obtained by SurveyManager::get_survey()
1650
     * @param int   $user_id     The ID of the user asking for the report
1651
     * @param bool  $compact     Whether to present the long (v marks with multiple columns per question) or compact (one column per question) answers format
1652
     *
1653
     * @todo consider merging this function with display_complete_report
1654
     *
1655
     * @throws Exception
1656
     *
1657
     * @return string The contents of a csv file
1658
     *
1659
     * @author Patrick Cool <[email protected]>, Ghent University
1660
     *
1661
     * @version February 2007
1662
     */
1663
    public static function export_complete_report($survey_data, $user_id = 0, $compact = false, $lpItemId = 0)
1664
    {
1665
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1666
1667
        if (empty($surveyId)) {
1668
            return false;
1669
        }
1670
1671
        $course = api_get_course_info();
1672
        $course_id = $course['real_id'];
1673
        $sessionId = api_get_session_id();
1674
1675
        // To select the answers by session
1676
        $sessionCondition = '';
1677
        if (api_get_configuration_value('show_surveys_base_in_sessions')) {
1678
            if (!empty($sessionId)) {
1679
                $sessionCondition = api_get_session_condition($sessionId);
1680
            }
1681
        }
1682
1683
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1684
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1685
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1686
1687
        $translate = false;
1688
        if (api_get_configuration_value('translate_html') == true) {
1689
            $translate = true;
1690
        }
1691
1692
        // The first column
1693
        $return = ';';
1694
1695
        // Show extra fields blank space (enough for extra fields on next line)
1696
        $extra_user_fields = UserManager::get_extra_fields(
1697
            0,
1698
            0,
1699
            5,
1700
            'ASC',
1701
            false,
1702
            true
1703
        );
1704
1705
        $num = count($extra_user_fields);
1706
        if (!$survey_data['anonymous']) {
1707
            $return .= str_repeat(';', $num);
1708
        }
1709
        $suffixLpItem = !empty($lpItemId) ? '-item'.$lpItemId : '';
1710
        $sql = "SELECT
1711
                    questions.question_id,
1712
                    questions.type,
1713
                    questions.survey_question,
1714
                    count(options.question_option_id) as number_of_options
1715
				FROM $table_survey_question questions
1716
                LEFT JOIN $table_survey_question_option options
1717
				ON
1718
				  questions.question_id = options.question_id AND
1719
				  options.c_id = questions.c_id
1720
				WHERE
1721
				    survey_question NOT LIKE '%{{%' AND
1722
				    questions.type <> 'pagebreak' AND
1723
				    questions.survey_id = $surveyId AND
1724
                    questions.c_id = $course_id
1725
				GROUP BY questions.question_id
1726
				ORDER BY questions.sort ASC";
1727
1728
        $result = Database::query($sql);
1729
        while ($row = Database::fetch_array($result)) {
1730
            if ($translate) {
1731
                $row['survey_question'] = api_get_filtered_multilingual_HTML_string($row['survey_question'], $course['language']);
1732
            }
1733
            // We show the questions if
1734
            // 1. there is no question filter and the export button has not been clicked
1735
            // 2. there is a question filter but the question is selected for display
1736
            if (!(isset($_POST['submit_question_filter'.$suffixLpItem])) ||
1737
                (isset($_POST['submit_question_filter'.$suffixLpItem]) &&
1738
                    is_array($_POST['questions_filter'.$suffixLpItem]) &&
1739
                    in_array($row['question_id'], $_POST['questions_filter'.$suffixLpItem]))
1740
            ) {
1741
                if ($row['number_of_options'] == 0 || $compact) {
1742
                    $return .= str_replace(
1743
                        "\r\n",
1744
                        '  ',
1745
                        api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1746
                    )
1747
                    .';';
1748
                } else {
1749
                    $numberOfOptions = $row['number_of_options'];
1750
                    if ($row['type'] == 'multiplechoiceother') {
1751
                        $numberOfOptions++;
1752
                    }
1753
                    for ($ii = 0; $ii < $numberOfOptions; $ii++) {
1754
                        $return .= str_replace(
1755
                            "\r\n",
1756
                            '  ',
1757
                            api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1758
                        )
1759
                        .';';
1760
                    }
1761
                }
1762
            }
1763
        }
1764
1765
        $return .= "\n";
1766
        // Getting all the questions and options
1767
        $return .= ';';
1768
        // Show the fields names for user fields
1769
        if (!empty($extra_user_fields) && !$survey_data['anonymous']) {
1770
            foreach ($extra_user_fields as &$field) {
1771
                if ($translate) {
1772
                    $field[3] = api_get_filtered_multilingual_HTML_string($field[3], $course['language']);
1773
                }
1774
                $return .= '"'
1775
                    .str_replace(
1776
                        "\r\n",
1777
                        '  ',
1778
                        api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1779
                    )
1780
                    .'";';
1781
            }
1782
        }
1783
1784
        $sql = "SELECT DISTINCT
1785
		            survey_question.question_id,
1786
		            survey_question.survey_id,
1787
		            survey_question.survey_question,
1788
		            survey_question.display,
1789
		            survey_question.sort,
1790
		            survey_question.type,
1791
                    survey_question_option.question_option_id,
1792
                    survey_question_option.option_text,
1793
                    survey_question_option.sort as option_sort
1794
				FROM $table_survey_question survey_question
1795
				LEFT JOIN $table_survey_question_option survey_question_option
1796
				ON
1797
				    survey_question.question_id = survey_question_option.question_id AND
1798
				    survey_question_option.c_id = survey_question.c_id
1799
				WHERE
1800
				    survey_question NOT LIKE '%{{%' AND
1801
				    survey_question.type <> 'pagebreak' AND
1802
				    survey_question.survey_id = $surveyId AND
1803
				    survey_question.c_id = $course_id
1804
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1805
        $result = Database::query($sql);
1806
        $possible_answers = [];
1807
        $possible_answers_type = [];
1808
        $current_question_type = '';
1809
        $current_question_id = null;
1810
        while ($row = Database::fetch_array($result)) {
1811
            // We show the options if
1812
            // 1. there is no question filter and the export button has not been clicked
1813
            // 2. there is a question filter but the question is selected for display
1814
            if ($translate) {
1815
                $row['option_text'] = api_get_filtered_multilingual_HTML_string($row['option_text'], $course['language']);
1816
            }
1817
            if (!(isset($_POST['submit_question_filter'.$suffixLpItem])) || (
1818
                is_array($_POST['questions_filter'.$suffixLpItem]) &&
1819
                in_array($row['question_id'], $_POST['questions_filter'.$suffixLpItem])
1820
            )
1821
            ) {
1822
                if ($current_question_id != $row['question_id']) {
1823
                    if ($current_question_type == 'multiplechoiceother') {
1824
                        $return .= api_html_entity_decode(strip_tags(get_lang('Comment')), ENT_QUOTES).';';
1825
                    }
1826
                }
1827
1828
                $current_question_type = $row['type'];
1829
                $current_question_id = $row['question_id'];
1830
1831
                $row['option_text'] = str_replace(["\r", "\n"], ['', ''], $row['option_text']);
1832
                if (!$compact) {
1833
                    $return .= api_html_entity_decode(strip_tags($row['option_text']), ENT_QUOTES).';';
1834
1835
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1836
                } else {
1837
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['option_text'];
1838
                }
1839
                $possible_answers_type[$row['question_id']] = $row['type'];
1840
            }
1841
        }
1842
1843
        if ($current_question_type == 'multiplechoiceother') {
1844
            $return .= api_html_entity_decode(strip_tags(get_lang('Comment')), ENT_QUOTES).';';
1845
        }
1846
1847
        $return .= "\n";
1848
1849
        // To select the answers by Lp item
1850
        $lpItemCondition = '';
1851
        if (api_get_configuration_value('allow_survey_tool_in_lp')) {
1852
            $lpItemCondition = " AND c_lp_item_id = $lpItemId";
1853
        }
1854
1855
        // Getting all the answers of the users
1856
        $old_user = '';
1857
        $answers_of_user = [];
1858
        $sql = "SELECT * FROM $table_survey_answer
1859
		        WHERE
1860
		          c_id = $course_id AND
1861
		          survey_id = $surveyId
1862
                  $sessionCondition
1863
                  $lpItemCondition
1864
		          ";
1865
        if ($user_id != 0) {
1866
            $user_id = (int) $user_id;
1867
            $sql .= " AND user = $user_id ";
1868
        }
1869
        $sql .= ' ORDER BY user ASC ';
1870
1871
        $questionIdList = array_keys($possible_answers_type);
1872
        $open_question_iterator = 1;
1873
        $result = Database::query($sql);
1874
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1875
            if (!in_array($row['question_id'], $questionIdList)) {
1876
                continue;
1877
            }
1878
            if ($old_user != $row['user'] && $old_user != '') {
1879
                $return .= self::export_complete_report_row(
1880
                    $survey_data,
1881
                    $possible_answers,
1882
                    $answers_of_user,
1883
                    $old_user,
1884
                    !$survey_data['anonymous'],
1885
                    $compact,
1886
                    $possible_answers_type
1887
                );
1888
                $answers_of_user = [];
1889
            }
1890
1891
            if ('open' === $possible_answers_type[$row['question_id']] ||
1892
                'comment' === $possible_answers_type[$row['question_id']]
1893
            ) {
1894
                $temp_id = 'open'.$open_question_iterator;
1895
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1896
                $open_question_iterator++;
1897
            } else {
1898
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1899
            }
1900
            $old_user = $row['user'];
1901
        }
1902
1903
        // This is to display the last user
1904
        $return .= self::export_complete_report_row(
1905
            $survey_data,
1906
            $possible_answers,
1907
            $answers_of_user,
1908
            $old_user,
1909
            true,
1910
            $compact,
1911
            $possible_answers_type
1912
        );
1913
1914
        return $return;
1915
    }
1916
1917
    /**
1918
     * Add a line to the csv file.
1919
     *
1920
     * @param array $survey_data               Basic survey data (we're mostly interested in the 'anonymous' index)
1921
     * @param array $possible_options          Possible answers
1922
     * @param array $answers_of_user           User's answers
1923
     * @param mixed $user                      User ID or user details as string - Used as a string in the result string
1924
     * @param bool  $display_extra_user_fields Whether to display user fields or not
1925
     * @param bool  $compact                   Whether to show answers as different column values (true) or one column per option (false, default)
1926
     *
1927
     * @return string One line of the csv file
1928
     *
1929
     * @author Patrick Cool <[email protected]>, Ghent University
1930
     *
1931
     * @version February 2007
1932
     */
1933
    public static function export_complete_report_row(
1934
        $survey_data,
1935
        $possible_options,
1936
        $answers_of_user,
1937
        $user,
1938
        $display_extra_user_fields = false,
1939
        $compact = false,
1940
        $questionTypes = true
1941
    ) {
1942
        $return = '';
1943
        if (0 == $survey_data['anonymous']) {
1944
            if (0 !== intval($user)) {
1945
                $userInfo = api_get_user_info($user);
1946
                if (!empty($userInfo)) {
1947
                    $user_displayed = $userInfo['complete_name_with_username'];
1948
                } else {
1949
                    $user_displayed = '-';
1950
                }
1951
                $return .= $user_displayed.';';
1952
            } else {
1953
                $return .= $user.';';
1954
            }
1955
        } else {
1956
            $return .= '-;'; // The user column
1957
        }
1958
1959
        if ($display_extra_user_fields) {
1960
            // Show user fields data, if any, for this user
1961
            $user_fields_values = UserManager::get_extra_user_data(
1962
                $user,
1963
                false,
1964
                false,
1965
                false,
1966
                true
1967
            );
1968
            foreach ($user_fields_values as $fieldName => $value) {
1969
                $fieldValue = is_array($value) ? $value[$fieldName] : $value;
1970
                $return .= '"'.str_replace('"', '""', api_html_entity_decode(strip_tags($fieldValue), ENT_QUOTES)).'";';
1971
            }
1972
        }
1973
1974
        // Run through possible options
1975
        if (is_array($possible_options)) {
1976
            foreach ($possible_options as $question_id => $possible_option) {
1977
                if (is_array($possible_option) && count($possible_option) > 0) {
1978
                    $otherPaddingNeeded = ($questionTypes[$question_id] == 'multiplechoiceother' ? true : false);
1979
                    foreach ($possible_option as $option_id => &$value) {
1980
                        // For each option of this question, look if it matches the user's answer
1981
                        $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];
1982
                        $key = array_keys($my_answer_of_user);
1983
                        if (isset($key[0]) && substr($key[0], 0, 4) === 'open') {
1984
                            // If this is an open type question (type starts by 'open'), take whatever answer is given
1985
                            $return .= '"'.
1986
                                str_replace(
1987
                                    '"',
1988
                                    '""',
1989
                                    api_html_entity_decode(
1990
                                        strip_tags(
1991
                                            $answers_of_user[$question_id][$key[0]]['option_id']
1992
                                        ),
1993
                                        ENT_QUOTES
1994
                                    )
1995
                                ).
1996
                                '";';
1997
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
1998
                            // If this is a selected option from a list...
1999
                            if ($compact) {
2000
                                // If we asked for a compact view, show only one column for the question
2001
                                // and fill it with the text of the selected option (i.e. "Yes") instead of an ID
2002
                                if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
2003
                                    $return .= $answers_of_user[$question_id][$option_id]['value'].";";
2004
                                } else {
2005
                                    $return .= '"'.
2006
                                        str_replace(
2007
                                            '"',
2008
                                            '""',
2009
                                            api_html_entity_decode(
2010
                                                strip_tags(
2011
                                                    $possible_option[$option_id]
2012
                                                ),
2013
                                                ENT_QUOTES
2014
                                            )
2015
                                        ).
2016
                                        '";';
2017
                                }
2018
                            } else {
2019
                                // If we don't want a compact view, show one column per possible option and mark a 'v'
2020
                                // or the defined value in the corresponding column if the user selected it
2021
                                if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
2022
                                    $return .= '"'.$answers_of_user[$question_id][$option_id]['value'].'";';
2023
                                } else {
2024
                                    $return .= 'v;';
2025
                                }
2026
                            }
2027
                        } elseif (isset($key[0]) && strpos($key[0], '@:@') !== false) {
2028
                            list($idAnswer, $other) = explode('@:@', $key[0]);
2029
2030
                            if ($idAnswer == $option_id) {
2031
                                $return .= (
2032
                                    strlen($other) > 0
2033
                                    ? 'v;"'.str_replace('"', '""', api_html_entity_decode(strip_tags($other), ENT_QUOTES)).'";'
2034
                                    : 'v;'
2035
                                    );
2036
                            } else {
2037
                                if (!$compact) {
2038
                                    $return .= ';';
2039
                                    $otherPaddingNeeded = false;
2040
                                }
2041
                            }
2042
                        } else {
2043
                            if (!$compact || $questionTypes[$question_id] == 'multipleresponse') {
2044
                                $return .= ';';
2045
                            }
2046
                        }
2047
                    }
2048
                    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...
2049
                        $return .= ';';
2050
                    }
2051
                }
2052
            }
2053
        }
2054
        $return .= "\n";
2055
2056
        return $return;
2057
    }
2058
2059
    /**
2060
     * Quite similar to display_complete_report(), returns an HTML string
2061
     * that can be used in a csv file.
2062
     *
2063
     * @todo consider merging this function with display_complete_report
2064
     *
2065
     * @return string The contents of a csv file
2066
     *
2067
     * @author Patrick Cool <[email protected]>, Ghent University
2068
     *
2069
     * @version February 2007
2070
     */
2071
    public static function export_complete_report_xls($survey_data, $filename, $user_id = 0, $returnFile = false, $lpItemId = 0)
2072
    {
2073
        $course_id = api_get_course_int_id();
2074
        $user_id = (int) $user_id;
2075
        $surveyId = $survey_data['survey_id'];
2076
2077
        if (empty($course_id) || empty($surveyId)) {
2078
            return false;
2079
        }
2080
2081
        $spreadsheet = new PHPExcel();
2082
        $spreadsheet->setActiveSheetIndex(0);
2083
        $worksheet = $spreadsheet->getActiveSheet();
2084
        $line = 1;
2085
        $column = 1; // Skip the first column (row titles)
2086
2087
        // Show extra fields blank space (enough for extra fields on next line)
2088
        // Show user fields section with a big th colspan that spans over all fields
2089
        $extra_user_fields = UserManager::get_extra_fields(
2090
            0,
2091
            0,
2092
            5,
2093
            'ASC',
2094
            false,
2095
            true
2096
        );
2097
        $num = count($extra_user_fields);
2098
        if (!$survey_data['anonymous']) {
2099
            for ($i = 0; $i < $num; $i++) {
2100
                $worksheet->setCellValueByColumnAndRow($column, $line, '');
2101
                $column++;
2102
            }
2103
        }
2104
        $display_extra_user_fields = true;
2105
2106
        // Database table definitions
2107
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
2108
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2109
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
2110
2111
        // To select the answers by session
2112
        $sessionId = api_get_session_id();
2113
        $sessionCondition = '';
2114
        if (api_get_configuration_value('show_surveys_base_in_sessions')) {
2115
            if (!empty($sessionId)) {
2116
                $sessionCondition = api_get_session_condition($sessionId);
2117
            }
2118
        }
2119
        $suffixLpItem = !empty($lpItemId) ? '-item'.$lpItemId : '';
2120
        // First line (questions)
2121
        $sql = "SELECT
2122
                    questions.question_id,
2123
                    questions.type,
2124
                    questions.survey_question,
2125
                    count(options.question_option_id) as number_of_options
2126
				FROM $table_survey_question questions
2127
				LEFT JOIN $table_survey_question_option options
2128
                ON
2129
                  questions.question_id = options.question_id AND
2130
                  options.c_id = questions.c_id
2131
				WHERE
2132
				    survey_question NOT LIKE '%{{%' AND
2133
				    questions.type <> 'pagebreak' AND
2134
				    questions.survey_id = $surveyId AND
2135
				    questions.c_id = $course_id
2136
				GROUP BY questions.question_id
2137
				ORDER BY questions.sort ASC";
2138
        $result = Database::query($sql);
2139
        while ($row = Database::fetch_array($result)) {
2140
            // We show the questions if
2141
            // 1. there is no question filter and the export button has not been clicked
2142
            // 2. there is a question filter but the question is selected for display
2143
            if (!(isset($_POST['submit_question_filter'.$suffixLpItem])) ||
2144
                (isset($_POST['submit_question_filter'.$suffixLpItem]) && is_array($_POST['questions_filter'.$suffixLpItem]) &&
2145
                in_array($row['question_id'], $_POST['questions_filter'.$suffixLpItem]))
2146
            ) {
2147
                if ($row['number_of_options'] == 0 && ($row['type'] === 'open' || $row['type'] === 'comment')) {
2148
                    $worksheet->setCellValueByColumnAndRow(
2149
                        $column,
2150
                        $line,
2151
                        api_html_entity_decode(
2152
                            strip_tags($row['survey_question']),
2153
                            ENT_QUOTES
2154
                        )
2155
                    );
2156
                    $column++;
2157
                } else {
2158
                    $numberOfOptions = $row['number_of_options'];
2159
                    if ($row['type'] == 'multiplechoiceother') {
2160
                        $numberOfOptions++;
2161
                    }
2162
                    for ($ii = 0; $ii < $numberOfOptions; $ii++) {
2163
                        $worksheet->setCellValueByColumnAndRow(
2164
                            $column,
2165
                            $line,
2166
                            api_html_entity_decode(
2167
                                strip_tags($row['survey_question']),
2168
                                ENT_QUOTES
2169
                            )
2170
                        );
2171
                        $column++;
2172
                    }
2173
                }
2174
            }
2175
        }
2176
2177
        $line++;
2178
        $column = 1;
2179
        // Show extra field values
2180
        if ($display_extra_user_fields && !$survey_data['anonymous']) {
2181
            // Show the fields names for user fields
2182
            foreach ($extra_user_fields as &$field) {
2183
                $worksheet->setCellValueByColumnAndRow(
2184
                    $column,
2185
                    $line,
2186
                    api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
2187
                );
2188
                $column++;
2189
            }
2190
        }
2191
2192
        // Getting all the questions and options (second line)
2193
        $sql = "SELECT
2194
                    survey_question.question_id,
2195
                    survey_question.survey_id,
2196
                    survey_question.survey_question,
2197
                    survey_question.display,
2198
                    survey_question.sort,
2199
                    survey_question.type,
2200
                    survey_question_option.question_option_id,
2201
                    survey_question_option.option_text,
2202
                    survey_question_option.sort as option_sort
2203
				FROM $table_survey_question survey_question
2204
				LEFT JOIN $table_survey_question_option survey_question_option
2205
				ON
2206
				    survey_question.question_id = survey_question_option.question_id AND
2207
				    survey_question_option.c_id = survey_question.c_id
2208
				WHERE
2209
				    survey_question NOT LIKE '%{{%' AND
2210
				    survey_question.type <> 'pagebreak' AND
2211
				    survey_question.survey_id = $surveyId AND
2212
				    survey_question.c_id = $course_id
2213
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
2214
        $result = Database::query($sql);
2215
        $possible_answers = [];
2216
        $possible_answers_type = [];
2217
        $current_question_type = '';
2218
        $current_question_id = null;
2219
        while ($row = Database::fetch_array($result)) {
2220
            // We show the options if
2221
            // 1. there is no question filter and the export button has not been clicked
2222
            // 2. there is a quesiton filter but the question is selected for display
2223
            if (!isset($_POST['submit_question_filter'.$suffixLpItem]) ||
2224
                (isset($_POST['questions_filter'.$suffixLpItem]) && is_array($_POST['questions_filter'.$suffixLpItem]) &&
2225
                in_array($row['question_id'], $_POST['questions_filter'.$suffixLpItem]))
2226
            ) {
2227
                if ($current_question_id != $row['question_id']) {
2228
                    if ($current_question_type == 'multiplechoiceother') {
2229
                        $worksheet->setCellValueByColumnAndRow(
2230
                            $column,
2231
                            $line,
2232
                            api_html_entity_decode(
2233
                                strip_tags(get_lang('Comment')),
2234
                                ENT_QUOTES
2235
                            )
2236
                        );
2237
                        $column++;
2238
                    }
2239
                }
2240
2241
                $current_question_type = $row['type'];
2242
                $current_question_id = $row['question_id'];
2243
2244
                $worksheet->setCellValueByColumnAndRow(
2245
                    $column,
2246
                    $line,
2247
                    api_html_entity_decode(
2248
                        strip_tags($row['option_text']),
2249
                        ENT_QUOTES
2250
                    )
2251
                );
2252
                $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
2253
                $possible_answers_type[$row['question_id']] = $row['type'];
2254
                $column++;
2255
            }
2256
        }
2257
2258
        if ($current_question_type == 'multiplechoiceother') {
2259
            $worksheet->setCellValueByColumnAndRow(
2260
                $column,
2261
                $line,
2262
                api_html_entity_decode(
2263
                    strip_tags(get_lang('Comment')),
2264
                    ENT_QUOTES
2265
                )
2266
            );
2267
        }
2268
2269
        // To select the answers by Lp item
2270
        $lpItemCondition = '';
2271
        if (api_get_configuration_value('allow_survey_tool_in_lp')) {
2272
            $lpItemCondition = " AND c_lp_item_id = $lpItemId";
2273
        }
2274
2275
        // Getting all the answers of the users
2276
        $line++;
2277
        $column = 0;
2278
        $old_user = '';
2279
        $answers_of_user = [];
2280
        $sql = "SELECT * FROM $table_survey_answer
2281
                WHERE c_id = $course_id AND survey_id = $surveyId $sessionCondition $lpItemCondition";
2282
        if ($user_id != 0) {
2283
            $sql .= " AND user='".$user_id."' ";
2284
        }
2285
        $sql .= ' ORDER BY user ASC';
2286
2287
        $open_question_iterator = 1;
2288
        $result = Database::query($sql);
2289
        while ($row = Database::fetch_array($result)) {
2290
            if ($old_user != $row['user'] && $old_user != '') {
2291
                $return = self::export_complete_report_row_xls(
2292
                    $survey_data,
2293
                    $possible_answers,
2294
                    $answers_of_user,
2295
                    $old_user,
2296
                    !$survey_data['anonymous'],
2297
                    $possible_answers_type
2298
                );
2299
                foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
2300
                    $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
2301
                    $column++;
2302
                }
2303
                $answers_of_user = [];
2304
                $line++;
2305
                $column = 0;
2306
            }
2307
            if ($possible_answers_type[$row['question_id']] === 'open' ||
2308
                $possible_answers_type[$row['question_id']] === 'comment'
2309
            ) {
2310
                $temp_id = 'open'.$open_question_iterator;
2311
                $answers_of_user[$row['question_id']][$temp_id] = $row;
2312
                $open_question_iterator++;
2313
            } else {
2314
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
2315
            }
2316
            $old_user = $row['user'];
2317
        }
2318
2319
        $return = self::export_complete_report_row_xls(
2320
            $survey_data,
2321
            $possible_answers,
2322
            $answers_of_user,
2323
            $old_user,
2324
            true,
2325
            $possible_answers_type
2326
        );
2327
2328
        // this is to display the last user
2329
        foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
2330
            $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
2331
            $column++;
2332
        }
2333
2334
        $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
2335
        $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
2336
        $writer->save($file);
2337
2338
        if ($returnFile) {
2339
            return $file;
2340
        }
2341
2342
        DocumentManager::file_send_for_download($file, true, $filename);
2343
2344
        return null;
2345
    }
2346
2347
    /**
2348
     * Add a line to the csv file.
2349
     *
2350
     * @param array Possible answers
2351
     * @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...
2352
     * @param mixed User ID or user details as string - Used as a string in the result string
2353
     * @param bool Whether to display user fields or not
2354
     *
2355
     * @return string One line of the csv file
2356
     */
2357
    public static function export_complete_report_row_xls(
2358
        $survey_data,
2359
        $possible_options,
2360
        $answers_of_user,
2361
        $user,
2362
        $display_extra_user_fields = false,
2363
        $questionTypes = true
2364
    ) {
2365
        $return = [];
2366
        if ($survey_data['anonymous'] == 0) {
2367
            if (intval($user) !== 0) {
2368
                $userInfo = api_get_user_info($user);
2369
                if ($userInfo) {
2370
                    $user_displayed = $userInfo['complete_name_with_username'];
2371
                } else {
2372
                    $user_displayed = '-';
2373
                }
2374
                $return[] = $user_displayed;
2375
            } else {
2376
                $return[] = $user;
2377
            }
2378
        } else {
2379
            $return[] = '-'; // The user column
2380
        }
2381
2382
        if ($display_extra_user_fields) {
2383
            //show user fields data, if any, for this user
2384
            $user_fields_values = UserManager::get_extra_user_data(
2385
                $user,
2386
                false,
2387
                false,
2388
                false,
2389
                true
2390
            );
2391
            foreach ($user_fields_values as $fieldName => $value) {
2392
                $fieldValue = is_array($value) ? $value[$fieldName] : $value;
2393
                $return[] = api_html_entity_decode(strip_tags($fieldValue), ENT_QUOTES);
2394
            }
2395
        }
2396
2397
        if (is_array($possible_options)) {
2398
            foreach ($possible_options as $question_id => &$possible_option) {
2399
                $otherPaddingNeeded = ($questionTypes[$question_id] == 'multiplechoiceother' ? true : false);
2400
                if (is_array($possible_option) && count($possible_option) > 0) {
2401
                    foreach ($possible_option as $option_id => &$value) {
2402
                        $my_answers_of_user = isset($answers_of_user[$question_id])
2403
                            ? $answers_of_user[$question_id]
2404
                            : [];
2405
                        $key = array_keys($my_answers_of_user);
2406
                        if (isset($key[0]) && substr($key[0], 0, 4) == 'open') {
2407
                            $return[] = api_html_entity_decode(
2408
                                strip_tags($answers_of_user[$question_id][$key[0]]['option_id']),
2409
                                ENT_QUOTES
2410
                            );
2411
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
2412
                            if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
2413
                                $return[] = $answers_of_user[$question_id][$option_id]['value'];
2414
                            } else {
2415
                                $return[] = 'v';
2416
                            }
2417
                        } elseif (isset($key[0]) && strpos($key[0], '@:@') !== false) {
2418
                            list($idAnswer, $other) = explode('@:@', $key[0]);
2419
                            if ($idAnswer == $option_id) {
2420
                                if (strlen($other) > 0) {
2421
                                    $return[] = 'v';
2422
                                    $return[] = api_html_entity_decode(strip_tags($other), ENT_QUOTES);
2423
                                    $otherPaddingNeeded = false;
2424
                                } else {
2425
                                    $return[] = 'v';
2426
                                }
2427
                            } else {
2428
                                $return[] = '';
2429
                            }
2430
                        } else {
2431
                            $return[] = '';
2432
                        }
2433
                    }
2434
                    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...
2435
                        $return[] = '';
2436
                    }
2437
                }
2438
            }
2439
        }
2440
2441
        return $return;
2442
    }
2443
2444
    /**
2445
     * This function displays the comparative report which
2446
     * allows you to compare two questions
2447
     * A comparative report creates a table where one question
2448
     * is on the x axis and a second question is on the y axis.
2449
     * In the intersection is the number of people who have
2450
     * answered positive on both options.
2451
     *
2452
     * @return string HTML code
2453
     *
2454
     * @author Patrick Cool <[email protected]>, Ghent University
2455
     *
2456
     * @version February 2007
2457
     */
2458
    public static function display_comparative_report()
2459
    {
2460
        // Allowed question types for comparative report
2461
        $allowed_question_types = [
2462
            'yesno',
2463
            'multiplechoice',
2464
            'multipleresponse',
2465
            'dropdown',
2466
            'percentage',
2467
            'score',
2468
        ];
2469
2470
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
2471
2472
        // Getting all the questions
2473
        $questions = SurveyManager::get_questions($surveyId);
2474
2475
        // Actions bar
2476
        echo '<div class="actions">';
2477
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq()
2478
            .'">'
2479
            .Display::return_icon(
2480
                'back.png',
2481
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
2482
                [],
2483
                ICON_SIZE_MEDIUM
2484
            )
2485
            .'</a>';
2486
        echo '</div>';
2487
2488
        // Displaying an information message that only the questions with predefined answers can be used in a comparative report
2489
        echo Display::return_message(get_lang('OnlyQuestionsWithPredefinedAnswers'), 'normal', false);
2490
2491
        $xAxis = isset($_GET['xaxis']) ? Security::remove_XSS($_GET['xaxis']) : '';
2492
        $yAxis = isset($_GET['yaxis']) ? Security::remove_XSS($_GET['yaxis']) : '';
2493
        $course_id = api_get_course_int_id();
2494
        $lpItemId = isset($_REQUEST['lp_item']) ? (int) $_REQUEST['lp_item'] : '';
2495
        $sessionId = api_get_session_id();
2496
2497
        $url = api_get_self().'?'.api_get_cidreq().'&action='.Security::remove_XSS($_GET['action'])
2498
            .'&survey_id='.$surveyId.'&xaxis='.$xAxis.'&y='.$yAxis;
2499
2500
        $form = new FormValidator('compare', 'get', $url);
2501
        $form->addHidden('action', Security::remove_XSS($_GET['action']));
2502
        $form->addHidden('survey_id', $surveyId);
2503
        $optionsX = ['----'];
2504
        $optionsY = ['----'];
2505
        $defaults = [];
2506
        foreach ($questions as &$question) {
2507
            // Ignored tagged questions
2508
            if ($question) {
2509
                if (strpos($question['question'], '{{') !== false) {
2510
                    $question = null;
2511
                    continue;
2512
                }
2513
            }
2514
            if (is_array($allowed_question_types)) {
2515
                if (in_array($question['type'], $allowed_question_types)) {
2516
                    if (isset($_GET['xaxis']) && $_GET['xaxis'] == $question['question_id']) {
2517
                        $defaults['xaxis'] = $question['question_id'];
2518
                    }
2519
2520
                    if (isset($_GET['yaxis']) && $_GET['yaxis'] == $question['question_id']) {
2521
                        $defaults['yaxis'] = $question['question_id'];
2522
                    }
2523
                    $question['question'] = Security::remove_XSS($question['question']);
2524
2525
                    $optionsX[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
2526
                    $optionsY[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
2527
                }
2528
            }
2529
        }
2530
2531
        if (api_get_configuration_value('allow_survey_tool_in_lp')) {
2532
            self::addSelectLpItemsForm($surveyId, $course_id, $sessionId, 'comparativereport', $form);
2533
        }
2534
2535
        $form->addSelect('xaxis', get_lang('SelectXAxis'), $optionsX);
2536
        $form->addSelect('yaxis', get_lang('SelectYAxis'), $optionsY);
2537
2538
        $form->addButtonSearch(get_lang('CompareQuestions'));
2539
        $form->setDefaults($defaults);
2540
        $form->display();
2541
2542
        // Getting all the information of the x axis
2543
        if (!empty($xAxis)) {
2544
            $question_x = SurveyManager::get_question($xAxis);
2545
        }
2546
2547
        // Getting all the information of the y axis
2548
        if (!empty($yAxis)) {
2549
            $question_y = SurveyManager::get_question($yAxis);
2550
        }
2551
2552
        if (!empty($xAxis) && !empty($yAxis)) {
2553
            // Getting the answers of the two questions
2554
            $answers_x = self::get_answers_of_question_by_user($surveyId, $xAxis, $lpItemId);
2555
            $answers_y = self::get_answers_of_question_by_user($surveyId, $yAxis, $lpItemId);
2556
2557
            // Displaying the table
2558
            $tableHtml = '<table border="1" class="table table-hover table-striped data_table">';
2559
            $xOptions = [];
2560
            // The header
2561
            $tableHtml .= '<tr>';
2562
            for ($ii = 0; $ii <= count($question_x['answers']); $ii++) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_x does not seem to be defined for all execution paths leading up to this point.
Loading history...
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

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

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

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

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

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

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

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