Passed
Push — master ( eba669...1a8a38 )
by Julito
10:56
created

SurveyUtil::get_invitations()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 12
nc 2
nop 1
dl 0
loc 19
rs 9.8666
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CSurvey;
5
use Chamilo\CourseBundle\Entity\CSurveyAnswer;
6
use ChamiloSession as Session;
7
8
/**
9
 * This class offers a series of general utility functions for survey querying and display.
10
 *
11
 * @package chamilo.survey
12
 */
13
class SurveyUtil
14
{
15
    /**
16
     * Checks whether the given survey has a pagebreak question as the first
17
     * or the last question.
18
     * If so, break the current process, displaying an error message.
19
     *
20
     * @param int  $survey_id Survey ID (database ID)
21
     * @param bool $continue  Optional. Whether to continue the current
22
     *                        process or exit when breaking condition found. Defaults to true (do not break).
23
     */
24
    public static function check_first_last_question($survey_id, $continue = true)
25
    {
26
        // Table definitions
27
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
28
        $course_id = api_get_course_int_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='".Database::escape_string($survey_id)."'
33
                ORDER BY sort ASC";
34
        $result = Database::query($sql);
35
        $total = Database::num_rows($result);
36
        $counter = 1;
37
        $error = false;
38
        while ($row = Database::fetch_array($result, 'ASSOC')) {
39
            if ($counter == 1 && $row['type'] == 'pagebreak') {
40
                echo Display::return_message(get_lang('PagebreakNotFirst'), 'error', false);
41
                $error = true;
42
            }
43
            if ($counter == $total && $row['type'] == 'pagebreak') {
44
                echo Display::return_message(get_lang('PagebreakNotLast'), 'error', false);
45
                $error = true;
46
            }
47
            $counter++;
48
        }
49
50
        if (!$continue && $error) {
51
            Display::display_footer();
52
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
53
        }
54
    }
55
56
    /**
57
     * This function removes an (or multiple) answer(s) of a user on a question of a survey.
58
     *
59
     * @param mixed   The user id or email of the person who fills the survey
60
     * @param int The survey id
61
     * @param int The question id
62
     * @param int The option id
63
     *
64
     * @author Patrick Cool <[email protected]>, Ghent University
65
     *
66
     * @version January 2007
67
     */
68
    public static function remove_answer($user, $survey_id, $question_id, $course_id)
69
    {
70
        $course_id = intval($course_id);
71
        // table definition
72
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
73
        $sql = "DELETE FROM $table
74
				WHERE
75
				    c_id = $course_id AND
76
                    user = '".Database::escape_string($user)."' AND
77
                    survey_id = '".intval($survey_id)."' AND
78
                    question_id = '".intval($question_id)."'";
79
        Database::query($sql);
80
    }
81
82
    /**
83
     * This function stores an answer of a user on a question of a survey.
84
     *
85
     * @param mixed   The user id or email of the person who fills the survey
86
     * @param int Survey id
87
     * @param int Question id
88
     * @param int Option id
89
     * @param string  Option value
90
     * @param array $survey_data Survey data settings
91
     *
92
     * @return bool False if insufficient data, true otherwise
93
     *
94
     * @author Patrick Cool <[email protected]>, Ghent University
95
     *
96
     * @version January 2007
97
     */
98
    public static function store_answer(
99
        $user,
100
        $survey_id,
101
        $question_id,
102
        $option_id,
103
        $option_value,
104
        $survey_data
105
    ) {
106
        // If the question_id is empty, don't store an answer
107
        if (empty($question_id)) {
108
            return false;
109
        }
110
111
        // Table definition
112
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
113
114
        // Make the survey anonymous
115
        if ($survey_data['anonymous'] == 1) {
116
            $surveyUser = Session::read('surveyuser');
117
            if (empty($surveyUser)) {
118
                $user = md5($user.time());
119
                Session::write('surveyuser', $user);
120
            } else {
121
                $user = Session::read('surveyuser');
122
            }
123
        }
124
125
        $answer = new CSurveyAnswer();
126
        $answer
127
            ->setCId($survey_data['c_id'])
128
            ->setUser($user)
129
            ->setSurveyId($survey_id)
130
            ->setQuestionId($question_id)
131
            ->setOptionId($option_id)
132
            ->setValue($option_value)
133
        ;
134
135
        $em = Database::getManager();
136
        $em->persist($answer);
137
        $em->flush();
138
139
        $insertId = $answer->getIid();
140
        if ($insertId) {
141
            $sql = "UPDATE $table_survey_answer SET answer_id = $insertId 
142
                WHERE iid = $insertId";
143
            Database::query($sql);
144
        }
145
146
        return true;
147
    }
148
149
    /**
150
     * This function checks the parameters that are used in this page.
151
     *
152
     * @return string $people_filled The header, an error and the footer if any parameter fails, else it returns true
153
     *
154
     * @author Patrick Cool <[email protected]>, Ghent University
155
     *
156
     * @version February 2007
157
     */
158
    public static function check_parameters($people_filled)
159
    {
160
        $error = false;
161
162
        // Getting the survey data
163
        $survey_data = SurveyManager::get_survey($_GET['survey_id']);
164
165
        // $_GET['survey_id'] has to be numeric
166
        if (!is_numeric($_GET['survey_id'])) {
167
            $error = get_lang('IllegalSurveyId');
168
        }
169
170
        // $_GET['action']
171
        $allowed_actions = [
172
            'overview',
173
            'questionreport',
174
            'userreport',
175
            'comparativereport',
176
            'completereport',
177
            'deleteuserreport',
178
        ];
179
        if (isset($_GET['action']) && !in_array($_GET['action'], $allowed_actions)) {
180
            $error = get_lang('ActionNotAllowed');
181
        }
182
183
        // User report
184
        if (isset($_GET['action']) && $_GET['action'] == 'userreport') {
185
            if ($survey_data['anonymous'] == 0) {
186
                foreach ($people_filled as $key => &$value) {
187
                    $people_filled_userids[] = $value['invited_user'];
188
                }
189
            } else {
190
                $people_filled_userids = $people_filled;
191
            }
192
193
            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...
194
                $error = get_lang('UnknowUser');
195
            }
196
        }
197
198
        // Question report
199
        if (isset($_GET['action']) && $_GET['action'] == 'questionreport') {
200
            if (isset($_GET['question']) && !is_numeric($_GET['question'])) {
201
                $error = get_lang('UnknowQuestion');
202
            }
203
        }
204
205
        if ($error) {
206
            $tool_name = get_lang('Reporting');
207
            Display::addFlash(
208
                Display::return_message(
209
                    get_lang('Error').': '.$error,
210
                    'error',
211
                    false
212
                )
213
            );
214
            Display::display_header($tool_name);
215
            Display::display_footer();
216
            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...
217
        } else {
218
            return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the documented return type string.
Loading history...
219
        }
220
    }
221
222
    /**
223
     * This function deals with the action handling.
224
     *
225
     * @param array $survey_data
226
     * @param array $people_filled
227
     *
228
     * @author Patrick Cool <[email protected]>, Ghent University
229
     *
230
     * @version February 2007
231
     */
232
    public static function handle_reporting_actions($survey_data, $people_filled)
233
    {
234
        $action = isset($_GET['action']) ? $_GET['action'] : '';
235
236
        // Getting the number of question
237
        $temp_questions_data = SurveyManager::get_questions($_GET['survey_id']);
238
239
        // Sorting like they should be displayed and removing the non-answer question types (comment and pagebreak)
240
        $my_temp_questions_data = $temp_questions_data == null ? [] : $temp_questions_data;
241
        $questions_data = [];
242
243
        foreach ($my_temp_questions_data as $key => &$value) {
244
            if ($value['type'] != 'pagebreak') {
245
                $questions_data[$value['sort']] = $value;
246
            }
247
        }
248
249
        // Counting the number of questions that are relevant for the reporting
250
        $survey_data['number_of_questions'] = count($questions_data);
251
252
        switch ($action) {
253
            case 'questionreport':
254
                self::display_question_report($survey_data);
255
                break;
256
            case 'userreport':
257
                self::display_user_report($people_filled, $survey_data);
258
                break;
259
            case 'comparativereport':
260
                self::display_comparative_report();
261
                break;
262
            case 'completereport':
263
                self::display_complete_report($survey_data);
264
                break;
265
            case 'deleteuserreport':
266
                self::delete_user_report($_GET['survey_id'], $_GET['user']);
267
                break;
268
        }
269
    }
270
271
    /**
272
     * This function deletes the report of an user who wants to retake the survey.
273
     *
274
     * @param int $survey_id
275
     * @param int $user_id
276
     *
277
     * @author Christian Fasanando Flores <[email protected]>
278
     *
279
     * @version November 2008
280
     */
281
    public static function delete_user_report($survey_id, $user_id)
282
    {
283
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
284
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
285
        $table_survey = Database::get_course_table(TABLE_SURVEY);
286
287
        $course_id = api_get_course_int_id();
288
        $survey_id = (int) $survey_id;
289
        $user_id = Database::escape_string($user_id);
290
291
        if (!empty($survey_id) && !empty($user_id)) {
292
            // delete data from survey_answer by user_id and survey_id
293
            $sql = "DELETE FROM $table_survey_answer
294
			        WHERE c_id = $course_id AND survey_id = '".$survey_id."' AND user = '".$user_id."'";
295
            Database::query($sql);
296
            // update field answered from survey_invitation by user_id and survey_id
297
            $sql = "UPDATE $table_survey_invitation SET answered = '0'
298
			        WHERE
299
			            c_id = $course_id AND
300
			            survey_code = (
301
                            SELECT code FROM $table_survey
302
                            WHERE
303
                                c_id = $course_id AND
304
                                survey_id = '".$survey_id."'
305
                        ) AND
306
			            user = '".$user_id."'";
307
            $result = Database::query($sql);
308
        }
309
310
        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...
311
            $message = get_lang('SurveyUserAnswersHaveBeenRemovedSuccessfully').'<br />
312
					<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=userreport&survey_id='
313
                .$survey_id.'">'.
314
                get_lang('GoBack').'</a>';
315
            echo Display::return_message($message, 'confirmation', false);
316
        }
317
    }
318
319
    /**
320
     * This function displays the user report which is basically nothing more
321
     * than a one-page display of all the questions
322
     * of the survey that is filled with the answers of the person who filled the survey.
323
     *
324
     * @return string html code of the one-page survey with the answers of the selected user
325
     *
326
     * @author Patrick Cool <[email protected]>, Ghent University
327
     *
328
     * @version February 2007 - Updated March 2008
329
     */
330
    public static function display_user_report($people_filled, $survey_data)
331
    {
332
        // Database table definitions
333
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
334
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
335
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
336
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
337
338
        // Actions bar
339
        echo '<div class="actions">';
340
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'.
341
            Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('ReportingOverview'), '', ICON_SIZE_MEDIUM)
342
            .'</a>';
343
        if (isset($_GET['user'])) {
344
            if (api_is_allowed_to_edit()) {
345
                // The delete link
346
                echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=deleteuserreport&survey_id='
347
                    .$surveyId.'&'.api_get_cidreq().'&user='.Security::remove_XSS($_GET['user']).'" >'.
348
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_MEDIUM).'</a>';
349
            }
350
351
            // Export the user report
352
            echo '<a href="javascript: void(0);" onclick="document.form1a.submit();">'
353
                .Display::return_icon('export_csv.png', get_lang('ExportAsCSV'), '', ICON_SIZE_MEDIUM).'</a> ';
354
            echo '<a href="javascript: void(0);" onclick="document.form1b.submit();">'
355
                .Display::return_icon('export_excel.png', get_lang('ExportAsXLS'), '', ICON_SIZE_MEDIUM).'</a> ';
356
            echo '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='
357
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
358
                .Security::remove_XSS($_GET['user']).'">';
359
            echo '<input type="hidden" name="export_report" value="export_report">';
360
            echo '<input type="hidden" name="export_format" value="csv">';
361
            echo '</form>';
362
            echo '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='
363
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
364
                .Security::remove_XSS($_GET['user']).'">';
365
            echo '<input type="hidden" name="export_report" value="export_report">';
366
            echo '<input type="hidden" name="export_format" value="xls">';
367
            echo '</form>';
368
            echo '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='
369
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
370
        }
371
        echo '</div>';
372
373
        // Step 1: selection of the user
374
        echo "<script>
375
        function jumpMenu(targ,selObj,restore) {
376
            eval(targ+\".location='\"+selObj.options[selObj.selectedIndex].value+\"'\");
377
            if (restore) selObj.selectedIndex=0;
378
        }
379
		</script>";
380
        echo get_lang('SelectUserWhoFilledSurvey').'<br />';
381
382
        echo '<select name="user" onchange="jumpMenu(\'parent\',this,0)">';
383
        echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
384
            .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">'
385
            .get_lang('SelectUser').'</option>';
386
387
        foreach ($people_filled as $key => &$person) {
388
            if ($survey_data['anonymous'] == 0) {
389
                $name = $person['user_info']['complete_name_with_username'];
390
                $id = $person['user_id'];
391
                if ($id == '') {
392
                    $id = $person['invited_user'];
393
                    $name = $person['invited_user'];
394
                }
395
            } else {
396
                $name = get_lang('Anonymous').' '.($key + 1);
397
                $id = $person;
398
            }
399
            echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
400
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&user='
401
                .Security::remove_XSS($id).'&'.api_get_cidreq().'" ';
402
            if (isset($_GET['user']) && $_GET['user'] == $id) {
403
                echo 'selected="selected"';
404
            }
405
            echo '>'.$name.'</option>';
406
        }
407
        echo '</select>';
408
409
        $course_id = api_get_course_int_id();
410
        // Step 2: displaying the survey and the answer of the selected users
411
        if (isset($_GET['user'])) {
412
            echo Display::return_message(
413
                get_lang('AllQuestionsOnOnePage'),
414
                'normal',
415
                false
416
            );
417
418
            // Getting all the questions and options
419
            $sql = "SELECT
420
			            survey_question.question_id,
421
			            survey_question.survey_id,
422
			            survey_question.survey_question,
423
			            survey_question.display,
424
			            survey_question.max_value,
425
			            survey_question.sort,
426
			            survey_question.type,
427
                        survey_question_option.question_option_id,
428
                        survey_question_option.option_text,
429
                        survey_question_option.sort as option_sort
430
					FROM $table_survey_question survey_question
431
					LEFT JOIN $table_survey_question_option survey_question_option
432
					ON
433
					    survey_question.question_id = survey_question_option.question_id AND
434
					    survey_question_option.c_id = $course_id
435
					WHERE
436
					    survey_question NOT LIKE '%{{%' AND
437
					    survey_question.survey_id = '".$surveyId."' AND
438
                        survey_question.c_id = $course_id
439
					ORDER BY survey_question.sort, survey_question_option.sort ASC";
440
            $result = Database::query($sql);
441
            while ($row = Database::fetch_array($result, 'ASSOC')) {
442
                if ($row['type'] != 'pagebreak') {
443
                    $questions[$row['sort']]['question_id'] = $row['question_id'];
444
                    $questions[$row['sort']]['survey_id'] = $row['survey_id'];
445
                    $questions[$row['sort']]['survey_question'] = $row['survey_question'];
446
                    $questions[$row['sort']]['display'] = $row['display'];
447
                    $questions[$row['sort']]['type'] = $row['type'];
448
                    $questions[$row['sort']]['maximum_score'] = $row['max_value'];
449
                    $questions[$row['sort']]['options'][$row['question_option_id']] = $row['option_text'];
450
                }
451
            }
452
453
            // Getting all the answers of the user
454
            $sql = "SELECT * FROM $table_survey_answer
455
			        WHERE
456
                        c_id = $course_id AND
457
                        survey_id = '".$surveyId."' AND
458
                        user = '".Database::escape_string($_GET['user'])."'";
459
            $result = Database::query($sql);
460
            while ($row = Database::fetch_array($result, 'ASSOC')) {
461
                $answers[$row['question_id']][] = $row['option_id'];
462
                $all_answers[$row['question_id']][] = $row;
463
            }
464
465
            // Displaying all the questions
466
467
            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...
468
                // If the question type is a scoring then we have to format the answers differently
469
                switch ($question['type']) {
470
                    case 'score':
471
                        $finalAnswer = [];
472
                        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...
473
                            foreach ($all_answers[$question['question_id']] as $key => &$answer_array) {
474
                                $finalAnswer[$answer_array['option_id']] = $answer_array['value'];
475
                            }
476
                        }
477
                        break;
478
                    case 'multipleresponse':
479
                        $finalAnswer = isset($answers[$question['question_id']])
480
                            ? $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...
481
                            : '';
482
                        break;
483
                    default:
484
                        $finalAnswer = '';
485
                        if (isset($all_answers[$question['question_id']])) {
486
                            $finalAnswer = $all_answers[$question['question_id']][0]['option_id'];
487
                        }
488
                        break;
489
                }
490
491
                $ch_type = 'ch_'.$question['type'];
492
                if (class_exists($ch_type)) {
493
                    /** @var survey_question $display */
494
                    $display = new $ch_type();
495
496
                    $url = api_get_self();
497
                    $form = new FormValidator('question', 'post', $url);
498
                    $form->addHtml('<div class="survey_question_wrapper"><div class="survey_question">');
499
                    $form->addHtml($question['survey_question']);
500
                    $display->render($form, $question, $finalAnswer);
501
                    $form->addHtml('</div></div>');
502
                    $form->display();
503
                }
504
            }
505
        }
506
    }
507
508
    /**
509
     * This function displays the report by question.
510
     *
511
     * It displays a table with all the options of the question and the number of users who have answered positively on
512
     * the option. The number of users who answered positive on a given option is expressed in an absolute number, in a
513
     * percentage of the total and graphically using bars By clicking on the absolute number you get a list with the
514
     * persons who have answered this. You can then click on the name of the person and you will then go to the report
515
     * by user where you see all the answers of that user.
516
     *
517
     * @param    array    All the survey data
518
     *
519
     * @return string html code that displays the report by question
520
     *
521
     * @todo allow switching between horizontal and vertical.
522
     * @todo multiple response: percentage are probably not OK
523
     * @todo the question and option text have to be shortened and should expand when the user clicks on it.
524
     * @todo the pagebreak and comment question types should not be shown => removed from $survey_data before
525
     *
526
     * @author Patrick Cool <[email protected]>, Ghent University
527
     *
528
     * @version February 2007 - Updated March 2008
529
     */
530
    public static function display_question_report($survey_data)
531
    {
532
        $singlePage = isset($_GET['single_page']) ? (int) $_GET['single_page'] : 0;
533
        // Determining the offset of the sql statement (the n-th question of the survey)
534
        $offset = !isset($_GET['question']) ? 0 : (int) $_GET['question'];
535
        $currentQuestion = isset($_GET['question']) ? (int) $_GET['question'] : 0;
536
        $surveyId = (int) $_GET['survey_id'];
537
        $action = Security::remove_XSS($_GET['action']);
538
        $course_id = api_get_course_int_id();
539
540
        // Database table definitions
541
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
542
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
543
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
544
        $questions = [];
545
546
        echo '<div class="actions">';
547
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'.
548
            Display::return_icon(
549
                'back.png',
550
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
551
                '',
552
                ICON_SIZE_MEDIUM
553
            ).'</a>';
554
        echo '</div>';
555
556
        if ($survey_data['number_of_questions'] > 0) {
557
            $limitStatement = null;
558
            if (!$singlePage) {
559
                echo '<div id="question_report_questionnumbers" class="pagination">';
560
                if ($currentQuestion != 0) {
561
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
562
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset - 1).'">'
563
                        .get_lang('PreviousQuestion').'</a></li>';
564
                }
565
566
                for ($i = 1; $i <= $survey_data['number_of_questions']; $i++) {
567
                    if ($offset != $i - 1) {
568
                        echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
569
                            .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($i - 1).'">'.$i.'</a></li>';
570
                    } else {
571
                        echo '<li class="disabled"s><a href="#">'.$i.'</a></li>';
572
                    }
573
                }
574
                if ($currentQuestion < ($survey_data['number_of_questions'] - 1)) {
575
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
576
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset + 1).'">'
577
                        .get_lang('NextQuestion').'</li></a>';
578
                }
579
                echo '</ul>';
580
                echo '</div>';
581
                $limitStatement = " LIMIT $offset, 1";
582
            }
583
584
            // Getting the question information
585
            $sql = "SELECT * FROM $table_survey_question
586
			        WHERE
587
			            c_id = $course_id AND
588
                        survey_id='".$surveyId."' AND
589
                        survey_question NOT LIKE '%{{%' AND
590
                        type <>'pagebreak'                        
591
                    ORDER BY sort ASC
592
                    $limitStatement";
593
            $result = Database::query($sql);
594
            while ($row = Database::fetch_array($result)) {
595
                $questions[$row['question_id']] = $row;
596
            }
597
        }
598
        foreach ($questions as $question) {
599
            $chartData = [];
600
            $options = [];
601
            $questionId = (int) $question['question_id'];
602
            echo '<div class="title-question">';
603
            echo strip_tags(isset($question['survey_question']) ? $question['survey_question'] : null);
604
            echo '</div>';
605
606
            if ($question['type'] == 'score') {
607
                /** @todo This function should return the options as this is needed further in the code */
608
                $options = self::display_question_report_score($survey_data, $question, $offset);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $options is correct as self::display_question_r...ta, $question, $offset) targeting SurveyUtil::display_question_report_score() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
609
            } elseif ($question['type'] == 'open' || $question['type'] == 'comment') {
610
                /** @todo Also get the user who has answered this */
611
                $sql = "SELECT * FROM $table_survey_answer
612
                        WHERE
613
                            c_id = $course_id AND
614
                            survey_id='".$surveyId."' AND
615
                            question_id = '".$questionId."'";
616
                $result = Database::query($sql);
617
                while ($row = Database::fetch_array($result, 'ASSOC')) {
618
                    echo $row['option_id'].'<hr noshade="noshade" size="1" />';
619
                }
620
            } else {
621
                // Getting the options ORDER BY sort ASC
622
                $sql = "SELECT * FROM $table_survey_question_option
623
                        WHERE
624
                            c_id = $course_id AND
625
                            survey_id='".$surveyId."'
626
                            AND question_id = '".$questionId."'
627
                        ORDER BY sort ASC";
628
                $result = Database::query($sql);
629
                while ($row = Database::fetch_array($result, 'ASSOC')) {
630
                    $options[$row['question_option_id']] = $row;
631
                }
632
                // Getting the answers
633
                $sql = "SELECT *, count(answer_id) as total FROM $table_survey_answer
634
                        WHERE
635
                            c_id = $course_id AND
636
                            survey_id='".$surveyId."'
637
                            AND question_id = '".$questionId."'
638
                        GROUP BY option_id, value";
639
                $result = Database::query($sql);
640
                $number_of_answers = [];
641
                $data = [];
642
                while ($row = Database::fetch_array($result, 'ASSOC')) {
643
                    if (!isset($number_of_answers[$row['question_id']])) {
644
                        $number_of_answers[$row['question_id']] = 0;
645
                    }
646
                    $number_of_answers[$row['question_id']] += $row['total'];
647
                    $data[$row['option_id']] = $row;
648
                }
649
650
                foreach ($options as $option) {
651
                    $optionText = strip_tags($option['option_text']);
652
                    $optionText = html_entity_decode($optionText);
653
                    $votes = isset($data[$option['question_option_id']]['total']) ?
654
                        $data[$option['question_option_id']]['total'] : '0';
655
                    array_push($chartData, ['option' => $optionText, 'votes' => $votes]);
656
                }
657
                $chartContainerId = 'chartContainer'.$question['question_id'];
658
                echo '<div id="'.$chartContainerId.'" class="col-md-12">';
659
                echo self::drawChart($chartData, false, $chartContainerId);
660
661
                // displaying the table: headers
662
                echo '<table class="display-survey table">';
663
                echo '	<tr>';
664
                echo '		<th>&nbsp;</th>';
665
                echo '		<th>'.get_lang('AbsoluteTotal').'</th>';
666
                echo '		<th>'.get_lang('Percentage').'</th>';
667
                echo '		<th>'.get_lang('VisualRepresentation').'</th>';
668
                echo '	<tr>';
669
670
                // Displaying the table: the content
671
                if (is_array($options)) {
672
                    foreach ($options as $key => &$value) {
673
                        $absolute_number = null;
674
                        if (isset($data[$value['question_option_id']])) {
675
                            $absolute_number = $data[$value['question_option_id']]['total'];
676
                        }
677
                        if ($question['type'] == 'percentage' && empty($absolute_number)) {
678
                            continue;
679
                        }
680
                        $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...
681
                            ? $number_of_answers[$option['question_id']]
682
                            : 0;
683
                        if ($number_of_answers[$option['question_id']] == 0) {
684
                            $answers_number = 0;
685
                        } else {
686
                            $answers_number = $absolute_number / $number_of_answers[$option['question_id']] * 100;
687
                        }
688
                        echo '	<tr>';
689
                        echo '		<td class="center">'.$value['option_text'].'</td>';
690
                        echo '		<td class="center">';
691
                        if ($absolute_number != 0) {
692
                            echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action
693
                                .'&survey_id='.$surveyId.'&question='.$offset.'&viewoption='
694
                                .$value['question_option_id'].'">'.$absolute_number.'</a>';
695
                        } else {
696
                            echo '0';
697
                        }
698
699
                        echo '      </td>';
700
                        echo '		<td class="center">'.round($answers_number, 2).' %</td>';
701
                        echo '		<td class="center">';
702
                        $size = $answers_number * 2;
703
                        if ($size > 0) {
704
                            echo '<div style="border:1px solid #264269; background-color:#aecaf4; height:10px; width:'
705
                                .$size.'px">&nbsp;</div>';
706
                        } else {
707
                            echo '<div style="text-align: left;">'.get_lang("NoDataAvailable").'</div>';
708
                        }
709
                        echo ' </td>';
710
                        echo ' </tr>';
711
                    }
712
                }
713
                // displaying the table: footer (totals)
714
                $optionResult = '';
715
                if (isset($option['question_id']) && isset($number_of_answers[$option['question_id']])) {
716
                    if ($number_of_answers[$option['question_id']] == 0) {
717
                        $optionResult = '0';
718
                    } else {
719
                        $optionResult = $number_of_answers[$option['question_id']];
720
                    }
721
                }
722
723
                // displaying the table: footer (totals)
724
                echo '	<tr>';
725
                echo '		<td class="total"><b>'.get_lang('Total').'</b></td>';
726
                echo '		<td class="total"><b>'.$optionResult.'</b></td>';
727
                echo '		<td class="total">&nbsp;</td>';
728
                echo '		<td class="total">&nbsp;</td>';
729
                echo '	</tr>';
730
                echo '</table>';
731
                echo '</div>';
732
            }
733
        }
734
735
        if (isset($_GET['viewoption'])) {
736
            echo '<div class="answered-people">';
737
            echo '<h4>'.get_lang('PeopleWhoAnswered').': '
738
                .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 598. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
739
740
            if (is_numeric($_GET['value'])) {
741
                $sql_restriction = "AND value='".Database::escape_string($_GET['value'])."'";
742
            }
743
744
            $sql = "SELECT user FROM $table_survey_answer
745
                    WHERE
746
                        c_id = $course_id AND
747
                        option_id = '".Database::escape_string($_GET['viewoption'])."'
748
                        $sql_restriction";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sql_restriction does not seem to be defined for all execution paths leading up to this point.
Loading history...
749
            $result = Database::query($sql);
750
            echo '<ul>';
751
            while ($row = Database::fetch_array($result, 'ASSOC')) {
752
                $user_info = api_get_user_info($row['user']);
753
                echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=userreport&survey_id='
754
                    .$surveyId.'&user='.$row['user'].'">'
755
                    .$user_info['complete_name_with_username']
756
                    .'</a></li>';
757
            }
758
            echo '</ul>';
759
            echo '</div>';
760
        }
761
    }
762
763
    /**
764
     * Display score data about a survey question.
765
     *
766
     * @param    array    Question info
767
     * @param    int    The offset of results shown
768
     */
769
    public static function display_question_report_score($survey_data, $question, $offset)
770
    {
771
        // Database table definitions
772
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
773
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
774
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
775
        $course_id = api_get_course_int_id();
776
777
        // Getting the options
778
        $sql = "SELECT * FROM $table_survey_question_option
779
                WHERE
780
                    c_id = $course_id AND
781
                    survey_id='".intval($_GET['survey_id'])."' AND
782
                    question_id = '".intval($question['question_id'])."'
783
                ORDER BY sort ASC";
784
        $result = Database::query($sql);
785
        while ($row = Database::fetch_array($result)) {
786
            $options[$row['question_option_id']] = $row;
787
        }
788
789
        // Getting the answers
790
        $sql = "SELECT *, count(answer_id) as total 
791
                FROM $table_survey_answer
792
                WHERE
793
                   c_id = $course_id AND
794
                   survey_id='".intval($_GET['survey_id'])."' AND
795
                   question_id = '".Database::escape_string($question['question_id'])."'
796
                GROUP BY option_id, value";
797
        $result = Database::query($sql);
798
        $number_of_answers = 0;
799
        while ($row = Database::fetch_array($result)) {
800
            $number_of_answers += $row['total'];
801
            $data[$row['option_id']][$row['value']] = $row;
802
        }
803
804
        $chartData = [];
805
        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...
806
            $optionText = strip_tags($option['option_text']);
807
            $optionText = html_entity_decode($optionText);
808
            for ($i = 1; $i <= $question['max_value']; $i++) {
809
                $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...
810
                if (empty($votes)) {
811
                    $votes = '0';
812
                }
813
                array_push(
814
                    $chartData,
815
                    [
816
                        'serie' => $optionText,
817
                        'option' => $i,
818
                        'votes' => $votes,
819
                    ]
820
                );
821
            }
822
        }
823
        echo '<div id="chartContainer" class="col-md-12">';
824
        echo self::drawChart($chartData, true);
825
        echo '</div>';
826
827
        // Displaying the table: headers
828
        echo '<table class="data_table">';
829
        echo '	<tr>';
830
        echo '		<th>&nbsp;</th>';
831
        echo '		<th>'.get_lang('Score').'</th>';
832
        echo '		<th>'.get_lang('AbsoluteTotal').'</th>';
833
        echo '		<th>'.get_lang('Percentage').'</th>';
834
        echo '		<th>'.get_lang('VisualRepresentation').'</th>';
835
        echo '	<tr>';
836
        // Displaying the table: the content
837
        foreach ($options as $key => &$value) {
838
            for ($i = 1; $i <= $question['max_value']; $i++) {
839
                $absolute_number = $data[$value['question_option_id']][$i]['total'];
840
                echo '	<tr>';
841
                echo '		<td>'.$value['option_text'].'</td>';
842
                echo '		<td>'.$i.'</td>';
843
                echo '		<td><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action
844
                    .'&survey_id='.intval($_GET['survey_id']).'&question='.Security::remove_XSS($offset)
845
                    .'&viewoption='.$value['question_option_id'].'&value='.$i.'">'.$absolute_number.'</a></td>';
846
                echo '		<td>'.round($absolute_number / $number_of_answers * 100, 2).' %</td>';
847
                echo '		<td>';
848
                $size = ($absolute_number / $number_of_answers * 100 * 2);
849
                if ($size > 0) {
850
                    echo '<div style="border:1px solid #264269; background-color:#aecaf4; height:10px; width:'.$size.'px">&nbsp;</div>';
851
                }
852
                echo '		</td>';
853
                echo '	</tr>';
854
            }
855
        }
856
        // Displaying the table: footer (totals)
857
        echo '	<tr>';
858
        echo '		<td style="border-top:1px solid black"><b>'.get_lang('Total').'</b></td>';
859
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
860
        echo '		<td style="border-top:1px solid black"><b>'.$number_of_answers.'</b></td>';
861
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
862
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
863
        echo '	</tr>';
864
865
        echo '</table>';
866
    }
867
868
    /**
869
     * This functions displays the complete reporting.
870
     *
871
     * @return string HTML code
872
     *
873
     * @todo open questions are not in the complete report yet.
874
     *
875
     * @author Patrick Cool <[email protected]>, Ghent University
876
     *
877
     * @version February 2007
878
     */
879
    public static function display_complete_report($survey_data)
880
    {
881
        // Database table definitions
882
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
883
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
884
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
885
886
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
887
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
888
889
        // Actions bar
890
        echo '<div class="actions">';
891
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'
892
            .Display::return_icon(
893
                'back.png',
894
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
895
                [],
896
                ICON_SIZE_MEDIUM
897
            )
898
            .'</a>';
899
        echo '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1a.submit();">'
900
            .Display::return_icon('export_csv.png', get_lang('ExportAsCSV'), '', ICON_SIZE_MEDIUM).'</a>';
901
        echo '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1b.submit();">'
902
            .Display::return_icon('export_excel.png', get_lang('ExportAsXLS'), '', ICON_SIZE_MEDIUM).'</a>';
903
        echo '</div>';
904
905
        // The form
906
        echo '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
907
            .$surveyId.'&'.api_get_cidreq().'">';
908
        echo '<input type="hidden" name="export_report" value="export_report">';
909
        echo '<input type="hidden" name="export_format" value="csv">';
910
        echo '</form>';
911
        echo '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
912
            .$surveyId.'&'.api_get_cidreq().'">';
913
        echo '<input type="hidden" name="export_report" value="export_report">';
914
        echo '<input type="hidden" name="export_format" value="xls">';
915
        echo '</form>';
916
917
        echo '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
918
            .$surveyId.'&'.api_get_cidreq().'">';
919
920
        // The table
921
        echo '<br /><table class="data_table" border="1">';
922
        // Getting the number of options per question
923
        echo '	<tr>';
924
        echo '		<th>';
925
        if ((isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
926
            (isset($_POST['export_report']) && $_POST['export_report'])
927
        ) {
928
            echo '<button class="cancel" type="submit" name="reset_question_filter" value="'
929
                .get_lang('ResetQuestionFilter').'">'.get_lang('ResetQuestionFilter').'</button>';
930
        }
931
        echo '<button class="save" type="submit" name="submit_question_filter" value="'.get_lang('SubmitQuestionFilter')
932
            .'">'.get_lang('SubmitQuestionFilter').'</button>';
933
        echo '</th>';
934
935
        $display_extra_user_fields = false;
936
        if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
937
            isset($_POST['export_report']) && $_POST['export_report']) ||
938
            !empty($_POST['fields_filter'])
939
        ) {
940
            // Show user fields section with a big th colspan that spans over all fields
941
            $extra_user_fields = UserManager::get_extra_fields(
942
                0,
943
                0,
944
                5,
945
                'ASC',
946
                false,
947
                true
948
            );
949
            $num = count($extra_user_fields);
950
            if ($num > 0) {
951
                echo '<th '.($num > 0 ? ' colspan="'.$num.'"' : '').'>';
952
                echo '<label><input type="checkbox" name="fields_filter" value="1" checked="checked"/> ';
953
                echo get_lang('UserFields');
954
                echo '</label>';
955
                echo '</th>';
956
                $display_extra_user_fields = true;
957
            }
958
        }
959
960
        $course_id = api_get_course_int_id();
961
        $sql = "SELECT 
962
                  q.question_id, 
963
                  q.type, 
964
                  q.survey_question, 
965
                  count(o.question_option_id) as number_of_options
966
				FROM $table_survey_question q 
967
				LEFT JOIN $table_survey_question_option o
968
				ON q.question_id = o.question_id AND q.c_id = o.c_id
969
				WHERE 
970
				    survey_question NOT LIKE '%{{%' AND
971
				    q.survey_id = '".$surveyId."' AND
972
				    q.c_id = $course_id
973
				GROUP BY q.question_id
974
				ORDER BY q.sort ASC";
975
        $result = Database::query($sql);
976
        $questions = [];
977
        while ($row = Database::fetch_array($result)) {
978
            // We show the questions if
979
            // 1. there is no question filter and the export button has not been clicked
980
            // 2. there is a quesiton filter but the question is selected for display
981
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
982
                (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))
983
            ) {
984
                // We do not show comment and pagebreak question types
985
                if ($row['type'] != 'pagebreak') {
986
                    echo ' <th';
987
                    if ($row['number_of_options'] > 0 && $row['type'] != 'percentage') {
988
                        echo ' colspan="'.$row['number_of_options'].'"';
989
                    }
990
                    echo '>';
991
                    echo '<label><input type="checkbox" name="questions_filter[]" value="'.$row['question_id']
992
                        .'" checked="checked"/> ';
993
                    echo $row['survey_question'];
994
                    echo '</label>';
995
                    echo '</th>';
996
                }
997
                // No column at all if it's not a question
998
            }
999
            $questions[$row['question_id']] = $row;
1000
        }
1001
        echo '	</tr>';
1002
        // Getting all the questions and options
1003
        echo '	<tr>';
1004
        echo '		<th>&nbsp;</th>'; // the user column
1005
1006
        if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
1007
            isset($_POST['export_report']) && $_POST['export_report']) || !empty($_POST['fields_filter'])
1008
        ) {
1009
            //show the fields names for user fields
1010
            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...
1011
                echo '<th>'.$field[3].'</th>';
1012
            }
1013
        }
1014
1015
        // cells with option (none for open question)
1016
        $sql = "SELECT 	
1017
                    sq.question_id, 
1018
                    sq.survey_id,
1019
                    sq.survey_question, 
1020
                    sq.display,
1021
                    sq.sort, 
1022
                    sq.type, 
1023
                    sqo.question_option_id,
1024
                    sqo.option_text, 
1025
                    sqo.sort as option_sort
1026
				FROM $table_survey_question sq
1027
				LEFT JOIN $table_survey_question_option sqo
1028
				ON sq.question_id = sqo.question_id AND sq.c_id = sqo.c_id
1029
				WHERE
1030
				    survey_question NOT LIKE '%{{%' AND
1031
				    sq.survey_id = '".$surveyId."' AND
1032
                    sq.c_id = $course_id
1033
				ORDER BY sq.sort ASC, sqo.sort ASC";
1034
        $result = Database::query($sql);
1035
1036
        $display_percentage_header = 1;
1037
        $possible_answers = [];
1038
        // in order to display only once the cell option (and not 100 times)
1039
        while ($row = Database::fetch_array($result)) {
1040
            // We show the options if
1041
            // 1. there is no question filter and the export button has not been clicked
1042
            // 2. there is a question filter but the question is selected for display
1043
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
1044
                (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))
1045
            ) {
1046
                // <hub> modif 05-05-2010
1047
                if ($row['type'] == 'open' || $row['type'] == 'comment') {
1048
                    echo '<th>&nbsp;-&nbsp;</th>';
1049
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1050
                    $display_percentage_header = 1;
1051
                } elseif ($row['type'] == 'percentage' && $display_percentage_header) {
1052
                    echo '<th>&nbsp;%&nbsp;</th>';
1053
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1054
                    $display_percentage_header = 0;
1055
                } elseif ($row['type'] == 'percentage') {
1056
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1057
                } elseif ($row['type'] != 'pagebreak' && $row['type'] != 'percentage') {
1058
                    echo '<th>';
1059
                    echo $row['option_text'];
1060
                    echo '</th>';
1061
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1062
                    $display_percentage_header = 1;
1063
                }
1064
            }
1065
        }
1066
1067
        echo '	</tr>';
1068
1069
        // Getting all the answers of the users
1070
        $old_user = '';
1071
        $answers_of_user = [];
1072
        $sql = "SELECT * FROM $table_survey_answer
1073
                WHERE
1074
                    c_id = $course_id AND
1075
                    survey_id='".$surveyId."'
1076
                ORDER BY answer_id, user ASC";
1077
        $result = Database::query($sql);
1078
        $i = 1;
1079
        while ($row = Database::fetch_array($result)) {
1080
            if ($old_user != $row['user'] && $old_user != '') {
1081
                $userParam = $old_user;
1082
                if ($survey_data['anonymous'] != 0) {
1083
                    $userParam = $i;
1084
                    $i++;
1085
                }
1086
                self::display_complete_report_row(
1087
                    $survey_data,
1088
                    $possible_answers,
1089
                    $answers_of_user,
1090
                    $userParam,
1091
                    $questions,
1092
                    $display_extra_user_fields
1093
                );
1094
                $answers_of_user = [];
1095
            }
1096
            if (isset($questions[$row['question_id']]) &&
1097
                $questions[$row['question_id']]['type'] != 'open' &&
1098
                $questions[$row['question_id']]['type'] != 'comment'
1099
            ) {
1100
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1101
            } else {
1102
                $answers_of_user[$row['question_id']][0] = $row;
1103
            }
1104
            $old_user = $row['user'];
1105
        }
1106
        $userParam = $old_user;
1107
        if ($survey_data['anonymous'] != 0) {
1108
            $userParam = $i;
1109
            $i++;
1110
        }
1111
        self::display_complete_report_row(
1112
            $survey_data,
1113
            $possible_answers,
1114
            $answers_of_user,
1115
            $userParam,
1116
            $questions,
1117
            $display_extra_user_fields
1118
        );
1119
        // This is to display the last user
1120
        echo '</table>';
1121
        echo '</form>';
1122
    }
1123
1124
    /**
1125
     * This function displays a row (= a user and his/her answers) in the table of the complete report.
1126
     *
1127
     * @param array $survey_data
1128
     * @param array    Possible options
1129
     * @param array    User answers
1130
     * @param mixed    User ID or user details string
1131
     * @param bool  Whether to show extra user fields or not
1132
     *
1133
     * @author Patrick Cool <[email protected]>, Ghent University
1134
     *
1135
     * @version February 2007 - Updated March 2008
1136
     */
1137
    public static function display_complete_report_row(
1138
        $survey_data,
1139
        $possible_options,
1140
        $answers_of_user,
1141
        $user,
1142
        $questions,
1143
        $display_extra_user_fields = false
1144
    ) {
1145
        $user = Security::remove_XSS($user);
1146
        echo '<tr>';
1147
        if ($survey_data['anonymous'] == 0) {
1148
            if (intval($user) !== 0) {
1149
                $userInfo = api_get_user_info($user);
1150
                if (!empty($userInfo)) {
1151
                    $user_displayed = $userInfo['complete_name_with_username'];
1152
                } else {
1153
                    $user_displayed = '-';
1154
                }
1155
                echo '<th>
1156
                    <a href="'.api_get_self().'?action=userreport&survey_id='.intval($_GET['survey_id']).'&user='.$user.'">'
1157
                    .$user_displayed.'</a>
1158
                    </th>'; // the user column
1159
            } else {
1160
                echo '<th>'.$user.'</th>'; // the user column
1161
            }
1162
        } else {
1163
            echo '<th>'.get_lang('Anonymous').' '.$user.'</th>';
1164
        }
1165
1166
        if ($display_extra_user_fields) {
1167
            // Show user fields data, if any, for this user
1168
            $user_fields_values = UserManager::get_extra_user_data(
1169
                $user,
1170
                false,
1171
                false,
1172
                false,
1173
                true
1174
            );
1175
            foreach ($user_fields_values as &$value) {
1176
                echo '<td align="center">'.$value.'</td>';
1177
            }
1178
        }
1179
1180
        if (is_array($possible_options)) {
1181
            foreach ($possible_options as $question_id => &$possible_option) {
1182
                if ($questions[$question_id]['type'] == 'open' || $questions[$question_id]['type'] == 'comment') {
1183
                    echo '<td align="center">';
1184
                    if (isset($answers_of_user[$question_id]) && isset($answers_of_user[$question_id]['0'])) {
1185
                        echo $answers_of_user[$question_id]['0']['option_id'];
1186
                    }
1187
                    echo '</td>';
1188
                } else {
1189
                    foreach ($possible_option as $option_id => &$value) {
1190
                        if ($questions[$question_id]['type'] == 'percentage') {
1191
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1192
                                echo "<td align='center'>";
1193
                                echo $answers_of_user[$question_id][$option_id]['value'];
1194
                                echo "</td>";
1195
                            }
1196
                        } else {
1197
                            echo '<td align="center">';
1198
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1199
                                if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1200
                                    echo $answers_of_user[$question_id][$option_id]['value'];
1201
                                } else {
1202
                                    echo 'v';
1203
                                }
1204
                            }
1205
                        }
1206
                    }
1207
                }
1208
            }
1209
        }
1210
        echo '</tr>';
1211
    }
1212
1213
    /**
1214
     * Quite similar to display_complete_report(), returns an HTML string
1215
     * that can be used in a csv file.
1216
     *
1217
     * @todo consider merging this function with display_complete_report
1218
     *
1219
     * @return string The contents of a csv file
1220
     *
1221
     * @author Patrick Cool <[email protected]>, Ghent University
1222
     *
1223
     * @version February 2007
1224
     */
1225
    public static function export_complete_report($survey_data, $user_id = 0)
1226
    {
1227
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1228
1229
        if (empty($surveyId)) {
1230
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
1231
        }
1232
1233
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1234
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1235
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1236
1237
        // The first column
1238
        $return = ';';
1239
1240
        // Show extra fields blank space (enough for extra fields on next line)
1241
        $extra_user_fields = UserManager::get_extra_fields(
1242
            0,
1243
            0,
1244
            5,
1245
            'ASC',
1246
            false,
1247
            true
1248
        );
1249
1250
        $num = count($extra_user_fields);
1251
        $return .= str_repeat(';', $num);
1252
        $course_id = api_get_course_int_id();
1253
1254
        $sql = "SELECT
1255
                    questions.question_id,
1256
                    questions.type,
1257
                    questions.survey_question,
1258
                    count(options.question_option_id) as number_of_options
1259
				FROM $table_survey_question questions
1260
                LEFT JOIN $table_survey_question_option options
1261
				ON 
1262
				  questions.question_id = options.question_id AND 
1263
				  options.c_id = questions.c_id
1264
				WHERE
1265
				    survey_question NOT LIKE '%{{%' AND
1266
				    questions.type <> 'pagebreak' AND
1267
				    questions.survey_id = $surveyId AND
1268
                    questions.c_id = $course_id
1269
				GROUP BY questions.question_id
1270
				ORDER BY questions.sort ASC";
1271
1272
        $result = Database::query($sql);
1273
        while ($row = Database::fetch_array($result)) {
1274
            // We show the questions if
1275
            // 1. there is no question filter and the export button has not been clicked
1276
            // 2. there is a quesiton filter but the question is selected for display
1277
            if (!(isset($_POST['submit_question_filter'])) ||
1278
                (isset($_POST['submit_question_filter']) &&
1279
                    is_array($_POST['questions_filter']) &&
1280
                    in_array($row['question_id'], $_POST['questions_filter']))
1281
            ) {
1282
                if ($row['number_of_options'] == 0) {
1283
                    $return .= str_replace(
1284
                        "\r\n",
1285
                        '  ',
1286
                        api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1287
                    )
1288
                    .';';
1289
                } else {
1290
                    for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1291
                        $return .= str_replace(
1292
                            "\r\n",
1293
                            '  ',
1294
                            api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1295
                        )
1296
                        .';';
1297
                    }
1298
                }
1299
            }
1300
        }
1301
1302
        $return .= "\n";
1303
        // Getting all the questions and options
1304
        $return .= ';';
1305
        // Show the fields names for user fields
1306
        if (!empty($extra_user_fields)) {
1307
            foreach ($extra_user_fields as &$field) {
1308
                $return .= '"'
1309
                    .str_replace(
1310
                        "\r\n",
1311
                        '  ',
1312
                        api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1313
                    )
1314
                    .'";';
1315
            }
1316
        }
1317
1318
        $sql = "SELECT DISTINCT
1319
		            survey_question.question_id,
1320
		            survey_question.survey_id,
1321
		            survey_question.survey_question,
1322
		            survey_question.display,
1323
		            survey_question.sort,
1324
		            survey_question.type,
1325
                    survey_question_option.question_option_id,
1326
                    survey_question_option.option_text,
1327
                    survey_question_option.sort as option_sort
1328
				FROM $table_survey_question survey_question
1329
				LEFT JOIN $table_survey_question_option survey_question_option
1330
				ON
1331
				    survey_question.question_id = survey_question_option.question_id AND
1332
				    survey_question_option.c_id = survey_question.c_id
1333
				WHERE
1334
				    survey_question NOT LIKE '%{{%' AND			
1335
				    survey_question.type <> 'pagebreak' AND				    
1336
				    survey_question.survey_id = $surveyId AND
1337
				    survey_question.c_id = $course_id
1338
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1339
        $result = Database::query($sql);
1340
        $possible_answers = [];
1341
        $possible_answers_type = [];
1342
        while ($row = Database::fetch_array($result)) {
1343
            // We show the options if
1344
            // 1. there is no question filter and the export button has not been clicked
1345
            // 2. there is a question filter but the question is selected for display
1346
            if (!(isset($_POST['submit_question_filter'])) || (
1347
                is_array($_POST['questions_filter']) &&
1348
                in_array($row['question_id'], $_POST['questions_filter'])
1349
            )
1350
            ) {
1351
                $row['option_text'] = str_replace(["\r", "\n"], ['', ''], $row['option_text']);
1352
                $return .= api_html_entity_decode(strip_tags($row['option_text']), ENT_QUOTES).';';
1353
                $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1354
                $possible_answers_type[$row['question_id']] = $row['type'];
1355
            }
1356
        }
1357
1358
        $return .= "\n";
1359
1360
        // Getting all the answers of the users
1361
        $old_user = '';
1362
        $answers_of_user = [];
1363
        $sql = "SELECT * FROM $table_survey_answer
1364
		        WHERE 
1365
		          c_id = $course_id AND 
1366
		          survey_id='".$surveyId."'		           
1367
		          ";
1368
        if ($user_id != 0) {
1369
            $sql .= "AND user='".Database::escape_string($user_id)."' ";
1370
        }
1371
        $sql .= ' ORDER BY user ASC ';
1372
1373
        $questionIdList = array_keys($possible_answers_type);
1374
        $open_question_iterator = 1;
1375
        $result = Database::query($sql);
1376
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1377
            if (!in_array($row['question_id'], $questionIdList)) {
1378
                continue;
1379
            }
1380
            if ($old_user != $row['user'] && $old_user != '') {
1381
                $return .= self::export_complete_report_row(
1382
                    $survey_data,
1383
                    $possible_answers,
1384
                    $answers_of_user,
1385
                    $old_user,
1386
                    true
1387
                );
1388
                $answers_of_user = [];
1389
            }
1390
1391
            if ($possible_answers_type[$row['question_id']] == 'open' ||
1392
                $possible_answers_type[$row['question_id']] == 'comment'
1393
            ) {
1394
                $temp_id = 'open'.$open_question_iterator;
1395
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1396
                $open_question_iterator++;
1397
            } else {
1398
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1399
            }
1400
            $old_user = $row['user'];
1401
        }
1402
1403
        // This is to display the last user
1404
        $return .= self::export_complete_report_row(
1405
            $survey_data,
1406
            $possible_answers,
1407
            $answers_of_user,
1408
            $old_user,
1409
            true
1410
        );
1411
1412
        return $return;
1413
    }
1414
1415
    /**
1416
     * Add a line to the csv file.
1417
     *
1418
     * @param array Possible answers
1419
     * @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...
1420
     * @param mixed User ID or user details as string - Used as a string in the result string
1421
     * @param bool Whether to display user fields or not
1422
     *
1423
     * @return string One line of the csv file
1424
     *
1425
     * @author Patrick Cool <[email protected]>, Ghent University
1426
     *
1427
     * @version February 2007
1428
     */
1429
    public static function export_complete_report_row(
1430
        $survey_data,
1431
        $possible_options,
1432
        $answers_of_user,
1433
        $user,
1434
        $display_extra_user_fields = false
1435
    ) {
1436
        $return = '';
1437
        if ($survey_data['anonymous'] == 0) {
1438
            if (intval($user) !== 0) {
1439
                $userInfo = api_get_user_info($user);
1440
                if (!empty($userInfo)) {
1441
                    $user_displayed = $userInfo['complete_name_with_username'];
1442
                } else {
1443
                    $user_displayed = '-';
1444
                }
1445
                $return .= $user_displayed.';';
1446
            } else {
1447
                $return .= $user.';';
1448
            }
1449
        } else {
1450
            $return .= '-;'; // The user column
1451
        }
1452
1453
        if ($display_extra_user_fields) {
1454
            // Show user fields data, if any, for this user
1455
            $user_fields_values = UserManager::get_extra_user_data(
1456
                $user,
1457
                false,
1458
                false,
1459
                false,
1460
                true
1461
            );
1462
            foreach ($user_fields_values as &$value) {
1463
                $return .= '"'.str_replace('"', '""', api_html_entity_decode(strip_tags($value), ENT_QUOTES)).'";';
1464
            }
1465
        }
1466
1467
        if (is_array($possible_options)) {
1468
            foreach ($possible_options as $question_id => $possible_option) {
1469
                if (is_array($possible_option) && count($possible_option) > 0) {
1470
                    foreach ($possible_option as $option_id => &$value) {
1471
                        $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];
1472
                        $key = array_keys($my_answer_of_user);
1473
                        if (isset($key[0]) && substr($key[0], 0, 4) == 'open') {
1474
                            $return .= '"'.
1475
                                str_replace(
1476
                                    '"',
1477
                                    '""',
1478
                                    api_html_entity_decode(
1479
                                        strip_tags(
1480
                                            $answers_of_user[$question_id][$key[0]]['option_id']
1481
                                        ),
1482
                                        ENT_QUOTES
1483
                                    )
1484
                                ).
1485
                                '"';
1486
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
1487
                            //$return .= 'v';
1488
                            if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1489
                                $return .= $answers_of_user[$question_id][$option_id]['value'];
1490
                            } else {
1491
                                $return .= 'v';
1492
                            }
1493
                        }
1494
                        $return .= ';';
1495
                    }
1496
                }
1497
            }
1498
        }
1499
        $return .= "\n";
1500
1501
        return $return;
1502
    }
1503
1504
    /**
1505
     * Quite similar to display_complete_report(), returns an HTML string
1506
     * that can be used in a csv file.
1507
     *
1508
     * @todo consider merging this function with display_complete_report
1509
     *
1510
     * @return string The contents of a csv file
1511
     *
1512
     * @author Patrick Cool <[email protected]>, Ghent University
1513
     *
1514
     * @version February 2007
1515
     */
1516
    public static function export_complete_report_xls($survey_data, $filename, $user_id = 0)
1517
    {
1518
        $course_id = api_get_course_int_id();
1519
        $user_id = (int) $user_id;
1520
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1521
1522
        if (empty($course_id) || empty($surveyId)) {
1523
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
1524
        }
1525
1526
        // Show extra fields blank space (enough for extra fields on next line)
1527
        // Show user fields section with a big th colspan that spans over all fields
1528
        $extra_user_fields = UserManager::get_extra_fields(
1529
            0,
1530
            0,
1531
            5,
1532
            'ASC',
1533
            false,
1534
            true
1535
        );
1536
        $list = [];
1537
        $num = count($extra_user_fields);
1538
        for ($i = 0; $i < $num; $i++) {
1539
            $list[0][] = '';
1540
        }
1541
1542
        $display_extra_user_fields = true;
1543
1544
        // Database table definitions
1545
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1546
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1547
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1548
1549
        // First line (questions)
1550
        $sql = "SELECT
1551
                    questions.question_id,
1552
                    questions.type,
1553
                    questions.survey_question,
1554
                    count(options.question_option_id) as number_of_options
1555
				FROM $table_survey_question questions
1556
				LEFT JOIN $table_survey_question_option options
1557
                ON questions.question_id = options.question_id AND options.c_id = questions.c_id
1558
				WHERE
1559
				    questions.survey_id = $surveyId AND
1560
				    questions.c_id = $course_id
1561
				GROUP BY questions.question_id
1562
				ORDER BY questions.sort ASC";
1563
        $result = Database::query($sql);
1564
        $line = 1;
1565
        $column = 1;
1566
        while ($row = Database::fetch_array($result)) {
1567
            // We show the questions if
1568
            // 1. there is no question filter and the export button has not been clicked
1569
            // 2. there is a quesiton filter but the question is selected for display
1570
            if (!(isset($_POST['submit_question_filter'])) ||
1571
                (isset($_POST['submit_question_filter']) && is_array($_POST['questions_filter']) &&
1572
                in_array($row['question_id'], $_POST['questions_filter']))
1573
            ) {
1574
                // We do not show comment and pagebreak question types
1575
                if ($row['type'] != 'pagebreak') {
1576
                    if ($row['number_of_options'] == 0 && ($row['type'] == 'open' || $row['type'] == 'comment')) {
1577
                        $list[$line][$column] = api_html_entity_decode(
1578
                            strip_tags($row['survey_question']),
1579
                            ENT_QUOTES
1580
                        );
1581
                        $column++;
1582
                    } else {
1583
                        for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1584
                            $list[$line][$column] = api_html_entity_decode(
1585
                                strip_tags($row['survey_question']),
1586
                                ENT_QUOTES
1587
                            );
1588
                            $column++;
1589
                        }
1590
                    }
1591
                }
1592
            }
1593
        }
1594
1595
        $line++;
1596
        $column = 1;
1597
        // Show extra field values
1598
        if ($display_extra_user_fields) {
1599
            // Show the fields names for user fields
1600
            foreach ($extra_user_fields as &$field) {
1601
                $list[$line][$column] = api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES);
1602
                $column++;
1603
            }
1604
        }
1605
1606
        // Getting all the questions and options (second line)
1607
        $sql = "SELECT
1608
                    survey_question.question_id, 
1609
                    survey_question.survey_id, 
1610
                    survey_question.survey_question, 
1611
                    survey_question.display, 
1612
                    survey_question.sort, 
1613
                    survey_question.type,
1614
                    survey_question_option.question_option_id, 
1615
                    survey_question_option.option_text, 
1616
                    survey_question_option.sort as option_sort
1617
				FROM $table_survey_question survey_question
1618
				LEFT JOIN $table_survey_question_option survey_question_option
1619
				ON 
1620
				    survey_question.question_id = survey_question_option.question_id AND 
1621
				    survey_question_option.c_id = survey_question.c_id
1622
				WHERE 
1623
				    survey_question.survey_id = $surveyId AND
1624
				    survey_question.c_id = $course_id
1625
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1626
        $result = Database::query($sql);
1627
        $possible_answers = [];
1628
        $possible_answers_type = [];
1629
        while ($row = Database::fetch_array($result)) {
1630
            // We show the options if
1631
            // 1. there is no question filter and the export button has not been clicked
1632
            // 2. there is a quesiton filter but the question is selected for display
1633
            if (!isset($_POST['submit_question_filter']) ||
1634
                (isset($_POST['questions_filter']) && is_array($_POST['questions_filter']) &&
1635
                in_array($row['question_id'], $_POST['questions_filter']))
1636
            ) {
1637
                // We do not show comment and pagebreak question types
1638
                if ($row['type'] != 'pagebreak') {
1639
                    $list[$line][$column] = api_html_entity_decode(
1640
                        strip_tags($row['option_text']),
1641
                        ENT_QUOTES
1642
                    );
1643
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1644
                    $possible_answers_type[$row['question_id']] = $row['type'];
1645
                    $column++;
1646
                }
1647
            }
1648
        }
1649
1650
        // Getting all the answers of the users
1651
        $line++;
1652
        $column = 0;
1653
        $old_user = '';
1654
        $answers_of_user = [];
1655
        $sql = "SELECT * FROM $table_survey_answer
1656
                WHERE c_id = $course_id AND survey_id = $surveyId";
1657
        if ($user_id != 0) {
1658
            $sql .= " AND user='".$user_id."' ";
1659
        }
1660
        $sql .= ' ORDER BY user ASC';
1661
1662
        $open_question_iterator = 1;
1663
        $result = Database::query($sql);
1664
        while ($row = Database::fetch_array($result)) {
1665
            if ($old_user != $row['user'] && $old_user != '') {
1666
                $return = self::export_complete_report_row_xls(
1667
                    $survey_data,
1668
                    $possible_answers,
1669
                    $answers_of_user,
1670
                    $old_user,
1671
                    true
1672
                );
1673
                foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
1674
                    $list[$line][$column] = $elem;
1675
                    $column++;
1676
                }
1677
                $answers_of_user = [];
1678
                $line++;
1679
                $column = 0;
1680
            }
1681
            if ($possible_answers_type[$row['question_id']] == 'open' || $possible_answers_type[$row['question_id']] == 'comment') {
1682
                $temp_id = 'open'.$open_question_iterator;
1683
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1684
                $open_question_iterator++;
1685
            } else {
1686
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1687
            }
1688
            $old_user = $row['user'];
1689
        }
1690
1691
        $return = self::export_complete_report_row_xls(
1692
            $survey_data,
1693
            $possible_answers,
1694
            $answers_of_user,
1695
            $old_user,
1696
            true
1697
        );
1698
1699
        // this is to display the last user
1700
        foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
1701
            $list[$line][$column] = $elem;
1702
            $column++;
1703
        }
1704
1705
        Export::arrayToXls($list, $filename);
1706
1707
        return null;
1708
    }
1709
1710
    /**
1711
     * Add a line to the csv file.
1712
     *
1713
     * @param array Possible answers
1714
     * @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...
1715
     * @param mixed User ID or user details as string - Used as a string in the result string
1716
     * @param bool Whether to display user fields or not
1717
     *
1718
     * @return string One line of the csv file
1719
     */
1720
    public static function export_complete_report_row_xls(
1721
        $survey_data,
1722
        $possible_options,
1723
        $answers_of_user,
1724
        $user,
1725
        $display_extra_user_fields = false
1726
    ) {
1727
        $return = [];
1728
        if ($survey_data['anonymous'] == 0) {
1729
            if (intval($user) !== 0) {
1730
                $userInfo = api_get_user_info($user);
1731
                if ($userInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1732
                    $user_displayed = $userInfo['complete_name_with_username'];
1733
                } else {
1734
                    $user_displayed = '-';
1735
                }
1736
                $return[] = $user_displayed;
1737
            } else {
1738
                $return[] = $user;
1739
            }
1740
        } else {
1741
            $return[] = '-'; // The user column
1742
        }
1743
1744
        if ($display_extra_user_fields) {
1745
            //show user fields data, if any, for this user
1746
            $user_fields_values = UserManager::get_extra_user_data(
1747
                intval($user),
1748
                false,
1749
                false,
1750
                false,
1751
                true
1752
            );
1753
            foreach ($user_fields_values as $value) {
1754
                $return[] = api_html_entity_decode(strip_tags($value), ENT_QUOTES);
1755
            }
1756
        }
1757
1758
        if (is_array($possible_options)) {
1759
            foreach ($possible_options as $question_id => &$possible_option) {
1760
                if (is_array($possible_option) && count($possible_option) > 0) {
1761
                    foreach ($possible_option as $option_id => &$value) {
1762
                        $my_answers_of_user = isset($answers_of_user[$question_id])
1763
                            ? $answers_of_user[$question_id]
1764
                            : [];
1765
                        $key = array_keys($my_answers_of_user);
1766
                        if (isset($key[0]) && substr($key[0], 0, 4) == 'open') {
1767
                            $return[] = api_html_entity_decode(
1768
                                strip_tags($answers_of_user[$question_id][$key[0]]['option_id']),
1769
                                ENT_QUOTES
1770
                            );
1771
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
1772
                            if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1773
                                $return[] = $answers_of_user[$question_id][$option_id]['value'];
1774
                            } else {
1775
                                $return[] = 'v';
1776
                            }
1777
                        } else {
1778
                            $return[] = '';
1779
                        }
1780
                    }
1781
                }
1782
            }
1783
        }
1784
1785
        return $return;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $return returns the type array|string[] which is incompatible with the documented return type string.
Loading history...
1786
    }
1787
1788
    /**
1789
     * This function displays the comparative report which
1790
     * allows you to compare two questions
1791
     * A comparative report creates a table where one question
1792
     * is on the x axis and a second question is on the y axis.
1793
     * In the intersection is the number of people who have
1794
     * answered positive on both options.
1795
     *
1796
     * @return string HTML code
1797
     *
1798
     * @author Patrick Cool <[email protected]>, Ghent University
1799
     *
1800
     * @version February 2007
1801
     */
1802
    public static function display_comparative_report()
1803
    {
1804
        // Allowed question types for comparative report
1805
        $allowed_question_types = [
1806
            'yesno',
1807
            'multiplechoice',
1808
            'multipleresponse',
1809
            'dropdown',
1810
            'percentage',
1811
            'score',
1812
        ];
1813
1814
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1815
1816
        // Getting all the questions
1817
        $questions = SurveyManager::get_questions($surveyId);
1818
1819
        // Actions bar
1820
        echo '<div class="actions">';
1821
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq()
1822
            .'">'
1823
            .Display::return_icon(
1824
                'back.png',
1825
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
1826
                [],
1827
                ICON_SIZE_MEDIUM
1828
            )
1829
            .'</a>';
1830
        echo '</div>';
1831
1832
        // Displaying an information message that only the questions with predefined answers can be used in a comparative report
1833
        echo Display::return_message(get_lang('OnlyQuestionsWithPredefinedAnswers'), 'normal', false);
1834
1835
        $xAxis = isset($_GET['xaxis']) ? Security::remove_XSS($_GET['xaxis']) : '';
1836
        $yAxis = isset($_GET['yaxis']) ? Security::remove_XSS($_GET['yaxis']) : '';
1837
1838
        $url = api_get_self().'?'.api_get_cidreq().'&action='.Security::remove_XSS($_GET['action'])
1839
            .'&survey_id='.$surveyId.'&xaxis='.$xAxis.'&y='.$yAxis;
1840
1841
        $form = new FormValidator('compare', 'get', $url);
1842
        $form->addHidden('action', Security::remove_XSS($_GET['action']));
1843
        $form->addHidden('survey_id', $surveyId);
1844
        $optionsX = ['----'];
1845
        $optionsY = ['----'];
1846
        $defaults = [];
1847
        foreach ($questions as $key => &$question) {
1848
            // Ignored tagged questions
1849
            if ($question) {
1850
                if (strpos($question['question'], '{{') !== false) {
1851
                    $question = null;
1852
                    continue;
1853
                }
1854
            }
1855
            if (is_array($allowed_question_types)) {
1856
                if (in_array($question['type'], $allowed_question_types)) {
1857
                    if (isset($_GET['xaxis']) && $_GET['xaxis'] == $question['question_id']) {
1858
                        $defaults['xaxis'] = $question['question_id'];
1859
                    }
1860
1861
                    if (isset($_GET['yaxis']) && $_GET['yaxis'] == $question['question_id']) {
1862
                        $defaults['yaxis'] = $question['question_id'];
1863
                    }
1864
1865
                    $optionsX[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
1866
                    $optionsY[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 90);
1867
                }
1868
            }
1869
        }
1870
1871
        $form->addSelect('xaxis', get_lang('SelectXAxis'), $optionsX);
1872
        $form->addSelect('yaxis', get_lang('SelectYAxis'), $optionsY);
1873
1874
        $form->addButtonSearch(get_lang('CompareQuestions'));
1875
        $form->setDefaults($defaults);
1876
        $form->display();
1877
1878
        // Getting all the information of the x axis
1879
        if (is_numeric($xAxis)) {
1880
            $question_x = SurveyManager::get_question($xAxis);
1881
        }
1882
1883
        // Getting all the information of the y axis
1884
        if (is_numeric($yAxis)) {
1885
            $question_y = SurveyManager::get_question($yAxis);
1886
        }
1887
1888
        if (is_numeric($xAxis) && is_numeric($yAxis)) {
1889
            // Getting the answers of the two questions
1890
            $answers_x = self::get_answers_of_question_by_user($surveyId, $xAxis);
1891
            $answers_y = self::get_answers_of_question_by_user($surveyId, $yAxis);
1892
1893
            // Displaying the table
1894
            $tableHtml = '<table border="1" class="data_table">';
1895
            $xOptions = [];
1896
            // The header
1897
            $tableHtml .= '<tr>';
1898
            for ($ii = 0; $ii <= count($question_x['answers']); $ii++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

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

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

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
Comprehensibility Best Practice introduced by
The variable $question_x does not seem to be defined for all execution paths leading up to this point.
Loading history...
1899
                if ($ii == 0) {
1900
                    $tableHtml .= '<th>&nbsp;</th>';
1901
                } else {
1902
                    if ($question_x['type'] == 'score') {
1903
                        for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
1904
                            $tableHtml .= '<th>'.$question_x['answers'][($ii - 1)].'<br />'.$x.'</th>';
1905
                        }
1906
                        $x = '';
1907
                    } else {
1908
                        $tableHtml .= '<th>'.$question_x['answers'][($ii - 1)].'</th>';
1909
                    }
1910
                    $optionText = strip_tags($question_x['answers'][$ii - 1]);
1911
                    $optionText = html_entity_decode($optionText);
1912
                    array_push($xOptions, trim($optionText));
1913
                }
1914
            }
1915
            $tableHtml .= '</tr>';
1916
            $chartData = [];
1917
            // The main part
1918
            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...
1919
                $currentYQuestion = strip_tags($question_y['answers'][$ij]);
1920
                $currentYQuestion = html_entity_decode($currentYQuestion);
1921
                // The Y axis is a scoring question type so we have more rows than the options (actually options * maximum score)
1922
                if ($question_y['type'] == 'score') {
1923
                    for ($y = 1; $y <= $question_y['maximum_score']; $y++) {
1924
                        $tableHtml .= '<tr>';
1925
                        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...
1926
                            if ($question_x['type'] == 'score') {
1927
                                for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
1928
                                    if ($ii == 0) {
1929
                                        $tableHtml .= '<th>'.$question_y['answers'][($ij)].' '.$y.'</th>';
1930
                                        break;
1931
                                    } else {
1932
                                        $tableHtml .= '<td align="center">';
1933
                                        $votes = self::comparative_check(
1934
                                            $answers_x,
1935
                                            $answers_y,
1936
                                            $question_x['answersid'][($ii - 1)],
1937
                                            $question_y['answersid'][($ij)],
1938
                                            $x,
1939
                                            $y
1940
                                        );
1941
                                        $tableHtml .= $votes;
1942
                                        array_push(
1943
                                            $chartData,
1944
                                            [
1945
                                                'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
1946
                                                'option' => $x,
1947
                                                'votes' => $votes,
1948
                                            ]
1949
                                        );
1950
                                        $tableHtml .= '</td>';
1951
                                    }
1952
                                }
1953
                            } else {
1954
                                if ($ii == 0) {
1955
                                    $tableHtml .= '<th>'.$question_y['answers'][$ij].' '.$y.'</th>';
1956
                                } else {
1957
                                    $tableHtml .= '<td align="center">';
1958
                                    $votes = self::comparative_check(
1959
                                        $answers_x,
1960
                                        $answers_y,
1961
                                        $question_x['answersid'][($ii - 1)],
1962
                                        $question_y['answersid'][($ij)],
1963
                                        0,
1964
                                        $y
1965
                                    );
1966
                                    $tableHtml .= $votes;
1967
                                    array_push(
1968
                                        $chartData,
1969
                                        [
1970
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
1971
                                            'option' => $y,
1972
                                            'votes' => $votes,
1973
                                        ]
1974
                                    );
1975
                                    $tableHtml .= '</td>';
1976
                                }
1977
                            }
1978
                        }
1979
                        $tableHtml .= '</tr>';
1980
                    }
1981
                } else {
1982
                    // The Y axis is NOT a score question type so the number of rows = the number of options
1983
                    $tableHtml .= '<tr>';
1984
                    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...
1985
                        if ($question_x['type'] == 'score') {
1986
                            for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
1987
                                if ($ii == 0) {
1988
                                    $tableHtml .= '<th>'.$question_y['answers'][$ij].'</th>';
1989
                                    break;
1990
                                } else {
1991
                                    $tableHtml .= '<td align="center">';
1992
                                    $votes = self::comparative_check(
1993
                                        $answers_x,
1994
                                        $answers_y,
1995
                                        $question_x['answersid'][($ii - 1)],
1996
                                        $question_y['answersid'][($ij)],
1997
                                        $x,
1998
                                        0
1999
                                    );
2000
                                    $tableHtml .= $votes;
2001
                                    array_push(
2002
                                        $chartData,
2003
                                        [
2004
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
2005
                                            'option' => $x,
2006
                                            'votes' => $votes,
2007
                                        ]
2008
                                    );
2009
                                    $tableHtml .= '</td>';
2010
                                }
2011
                            }
2012
                        } else {
2013
                            if ($ii == 0) {
2014
                                $tableHtml .= '<th>'.$question_y['answers'][($ij)].'</th>';
2015
                            } else {
2016
                                $tableHtml .= '<td align="center">';
2017
                                $votes = self::comparative_check(
2018
                                    $answers_x,
2019
                                    $answers_y,
2020
                                    $question_x['answersid'][($ii - 1)],
2021
                                    $question_y['answersid'][($ij)]
2022
                                );
2023
                                $tableHtml .= $votes;
2024
                                array_push(
2025
                                    $chartData,
2026
                                    [
2027
                                        'serie' => $xOptions[$ii - 1],
2028
                                        'option' => $currentYQuestion,
2029
                                        'votes' => $votes,
2030
                                    ]
2031
                                );
2032
                                $tableHtml .= '</td>';
2033
                            }
2034
                        }
2035
                    }
2036
                    $tableHtml .= '</tr>';
2037
                }
2038
            }
2039
            $tableHtml .= '</table>';
2040
            echo '<div id="chartContainer" class="col-md-12">';
2041
            echo self::drawChart($chartData, true);
2042
            echo '</div>';
2043
            echo $tableHtml;
2044
        }
2045
    }
2046
2047
    /**
2048
     * Get all the answers of a question grouped by user.
2049
     *
2050
     * @param int $survey_id   Survey ID
2051
     * @param int $question_id Question ID
2052
     *
2053
     * @return array Array containing all answers of all users, grouped by user
2054
     *
2055
     * @author Patrick Cool <[email protected]>, Ghent University
2056
     *
2057
     * @version February 2007 - Updated March 2008
2058
     */
2059
    public static function get_answers_of_question_by_user($survey_id, $question_id)
2060
    {
2061
        $course_id = api_get_course_int_id();
2062
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
2063
2064
        $sql = "SELECT * FROM $table_survey_answer
2065
                WHERE 
2066
                  c_id = $course_id AND 
2067
                  survey_id='".intval($survey_id)."' AND 
2068
                  question_id='".intval($question_id)."'
2069
                ORDER BY USER ASC";
2070
        $result = Database::query($sql);
2071
        $return = [];
2072
        while ($row = Database::fetch_array($result)) {
2073
            if ($row['value'] == 0) {
2074
                $return[$row['user']][] = $row['option_id'];
2075
            } else {
2076
                $return[$row['user']][] = $row['option_id'].'*'.$row['value'];
2077
            }
2078
        }
2079
2080
        return $return;
2081
    }
2082
2083
    /**
2084
     * Count the number of users who answer positively on both options.
2085
     *
2086
     * @param array All answers of the x axis
2087
     * @param array All answers of the y axis
2088
     * @param int x axis value (= the option_id of the first question)
2089
     * @param int y axis value (= the option_id of the second question)
2090
     *
2091
     * @return int Number of users who have answered positively to both options
2092
     *
2093
     * @author Patrick Cool <[email protected]>, Ghent University
2094
     *
2095
     * @version February 2007
2096
     */
2097
    public static function comparative_check(
2098
        $answers_x,
2099
        $answers_y,
2100
        $option_x,
2101
        $option_y,
2102
        $value_x = 0,
2103
        $value_y = 0
2104
    ) {
2105
        if ($value_x == 0) {
2106
            $check_x = $option_x;
2107
        } else {
2108
            $check_x = $option_x.'*'.$value_x;
2109
        }
2110
        if ($value_y == 0) {
2111
            $check_y = $option_y;
2112
        } else {
2113
            $check_y = $option_y.'*'.$value_y;
2114
        }
2115
2116
        $counter = 0;
2117
        if (is_array($answers_x)) {
2118
            foreach ($answers_x as $user => &$answers) {
2119
                // Check if the user has given $option_x as answer
2120
                if (in_array($check_x, $answers)) {
2121
                    // Check if the user has given $option_y as an answer
2122
                    if (!is_null($answers_y[$user]) &&
2123
                        in_array($check_y, $answers_y[$user])
2124
                    ) {
2125
                        $counter++;
2126
                    }
2127
                }
2128
            }
2129
        }
2130
2131
        return $counter;
2132
    }
2133
2134
    /**
2135
     * Save the invitation mail.
2136
     *
2137
     * @param string Text of the e-mail
2138
     * @param int Whether the mail contents are for invite mail (0, default) or reminder mail (1)
2139
     *
2140
     * @author Patrick Cool <[email protected]>, Ghent University
2141
     *
2142
     * @version January 2007
2143
     */
2144
    public static function save_invite_mail($mailtext, $mail_subject, $reminder = 0)
2145
    {
2146
        $course_id = api_get_course_int_id();
2147
        // Database table definition
2148
        $table_survey = Database::get_course_table(TABLE_SURVEY);
2149
2150
        // Reminder or not
2151
        if ($reminder == 0) {
2152
            $mail_field = 'invite_mail';
2153
        } else {
2154
            $mail_field = 'reminder_mail';
2155
        }
2156
2157
        $sql = "UPDATE $table_survey SET
2158
		        mail_subject='".Database::escape_string($mail_subject)."',
2159
		        $mail_field = '".Database::escape_string($mailtext)."'
2160
		        WHERE c_id = $course_id AND survey_id = '".intval($_GET['survey_id'])."'";
2161
        Database::query($sql);
2162
    }
2163
2164
    /**
2165
     * This function saves all the invitations of course users
2166
     * and additional users in the database
2167
     * and sends the invitations by email.
2168
     *
2169
     * @param $users_array Users $array array can be both a list of course uids AND a list of additional emailaddresses
2170
     * @param $invitation_title Title $string of the invitation, used as the title of the mail
2171
     * @param $invitation_text Text $string of the invitation, used as the text of the mail.
2172
     *                         The text has to contain a **link** string or this will automatically be added to the end
2173
     * @param int  $reminder
2174
     * @param bool $sendmail
2175
     * @param int  $remindUnAnswered
2176
     *
2177
     * @return bool $isAdditionalEmail
2178
     *
2179
     * @author Patrick Cool <[email protected]>, Ghent University
2180
     * @author Julio Montoya - Adding auto-generated link support
2181
     *
2182
     * @version January 2007
2183
     */
2184
    public static function saveInvitations(
2185
        $users_array,
2186
        $invitation_title,
2187
        $invitation_text,
2188
        $reminder = 0,
2189
        $sendmail = false,
2190
        $remindUnAnswered = 0,
2191
        $isAdditionalEmail = false
2192
    ) {
2193
        if (!is_array($users_array)) {
2194
            // Should not happen
2195
2196
            return 0;
0 ignored issues
show
Bug Best Practice introduced by
The expression return 0 returns the type integer which is incompatible with the documented return type boolean.
Loading history...
2197
        }
2198
2199
        // Getting the survey information
2200
        $survey_data = SurveyManager::get_survey($_GET['survey_id']);
2201
        $survey_invitations = self::get_invitations($survey_data['survey_code']);
2202
        $already_invited = self::get_invited_users($survey_data['code']);
2203
2204
        // Remind unanswered is a special version of remind all reminder
2205
        $exclude_users = [];
2206
        if ($remindUnAnswered == 1) { // Remind only unanswered users
2207
            $reminder = 1;
2208
            $exclude_users = SurveyManager::get_people_who_filled_survey($_GET['survey_id']);
2209
        }
2210
2211
        $counter = 0; // Nr of invitations "sent" (if sendmail option)
2212
        $course_id = api_get_course_int_id();
2213
        $session_id = api_get_session_id();
2214
2215
        if ($isAdditionalEmail == false) {
2216
            $result = CourseManager::separateUsersGroups($users_array);
2217
            $groupList = $result['groups'];
2218
            $users_array = $result['users'];
2219
2220
            foreach ($groupList as $groupId) {
2221
                $userGroupList = GroupManager::getStudents($groupId);
2222
                $userGroupIdList = array_column($userGroupList, 'user_id');
2223
                $users_array = array_merge($users_array, $userGroupIdList);
2224
2225
                $params = [
2226
                    'c_id' => $course_id,
2227
                    'session_id' => $session_id,
2228
                    'group_id' => $groupId,
2229
                    'survey_code' => $survey_data['code'],
2230
                ];
2231
2232
                $invitationExists = self::invitationExists(
2233
                    $course_id,
2234
                    $session_id,
2235
                    $groupId,
2236
                    $survey_data['code']
2237
                );
2238
                if (empty($invitationExists)) {
2239
                    self::save_invitation($params);
2240
                }
2241
            }
2242
        }
2243
2244
        $users_array = array_unique($users_array);
2245
        foreach ($users_array as $key => $value) {
2246
            if (!isset($value) || $value == '') {
2247
                continue;
2248
            }
2249
2250
            // Skip user if reminding only unanswered people
2251
            if (in_array($value, $exclude_users)) {
2252
                continue;
2253
            }
2254
2255
            // Get the unique invitation code if we already have it
2256
            if ($reminder == 1 && array_key_exists($value, $survey_invitations)) {
2257
                $invitation_code = $survey_invitations[$value]['invitation_code'];
2258
            } else {
2259
                $invitation_code = md5($value.microtime());
2260
            }
2261
            $new_user = false; // User not already invited
2262
            // Store the invitation if user_id not in $already_invited['course_users'] OR email is not in $already_invited['additional_users']
2263
            $addit_users_array = isset($already_invited['additional_users']) && !empty($already_invited['additional_users'])
2264
                    ? explode(';', $already_invited['additional_users'])
2265
                    : [];
2266
            $my_alredy_invited = $already_invited['course_users'] == null ? [] : $already_invited['course_users'];
2267
            if ((is_numeric($value) && !in_array($value, $my_alredy_invited)) ||
2268
                (!is_numeric($value) && !in_array($value, $addit_users_array))
2269
            ) {
2270
                $new_user = true;
2271
                if (!array_key_exists($value, $survey_invitations)) {
2272
                    $params = [
2273
                        'c_id' => $course_id,
2274
                        'session_id' => $session_id,
2275
                        'user' => $value,
2276
                        'survey_code' => $survey_data['code'],
2277
                        'invitation_code' => $invitation_code,
2278
                        'invitation_date' => api_get_utc_datetime(),
2279
                    ];
2280
                    self::save_invitation($params);
2281
                }
2282
            }
2283
2284
            // Send the email if checkboxed
2285
            if (($new_user || $reminder == 1) && $sendmail) {
2286
                // Make a change for absolute url
2287
                if (isset($invitation_text)) {
2288
                    $invitation_text = api_html_entity_decode($invitation_text, ENT_QUOTES);
2289
                    $invitation_text = str_replace('src="../../', 'src="'.api_get_path(WEB_PATH), $invitation_text);
2290
                    $invitation_text = trim(stripslashes($invitation_text));
2291
                }
2292
                self::send_invitation_mail(
2293
                    $value,
2294
                    $invitation_code,
2295
                    $invitation_title,
2296
                    $invitation_text
2297
                );
2298
                $counter++;
2299
            }
2300
        }
2301
2302
        return $counter; // Number of invitations sent
0 ignored issues
show
Bug Best Practice introduced by
The expression return $counter returns the type integer which is incompatible with the documented return type boolean.
Loading history...
2303
    }
2304
2305
    /**
2306
     * @param $params
2307
     *
2308
     * @return bool|int
2309
     */
2310
    public static function save_invitation($params)
2311
    {
2312
        // Database table to store the invitations data
2313
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2314
        if (!empty($params['c_id']) &&
2315
            (!empty($params['user']) || !empty($params['group_id'])) &&
2316
            !empty($params['survey_code'])
2317
        ) {
2318
            $params['survey_invitation_id'] = $params['survey_invitation_id'] ?? 0;
2319
            $params['reminder_date'] = $params['reminder_date'] ?? null;
2320
            $params['answered'] = $params['answered'] ?? 0;
2321
            $params['group_id'] = $params['group_id'] ?? 0;
2322
2323
            $insertId = Database::insert($table, $params);
2324
            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...
2325
                $sql = "UPDATE $table 
2326
                        SET survey_invitation_id = $insertId
2327
                        WHERE iid = $insertId";
2328
                Database::query($sql);
2329
            }
2330
2331
            return $insertId;
2332
        }
2333
2334
        return false;
2335
    }
2336
2337
    /**
2338
     * @param int    $courseId
2339
     * @param int    $sessionId
2340
     * @param int    $groupId
2341
     * @param string $surveyCode
2342
     *
2343
     * @return int
2344
     */
2345
    public static function invitationExists($courseId, $sessionId, $groupId, $surveyCode)
2346
    {
2347
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2348
        $courseId = intval($courseId);
2349
        $sessionId = intval($sessionId);
2350
        $groupId = intval($groupId);
2351
        $surveyCode = Database::escape_string($surveyCode);
2352
2353
        $sql = "SELECT survey_invitation_id FROM $table
2354
                WHERE
2355
                    c_id = $courseId AND
2356
                    session_id = $sessionId AND
2357
                    group_id = $groupId AND
2358
                    survey_code = '$surveyCode'
2359
                ";
2360
        $result = Database::query($sql);
2361
2362
        return Database::num_rows($result);
2363
    }
2364
2365
    /**
2366
     * Send the invitation by mail.
2367
     *
2368
     * @param int invitedUser - the userId (course user) or emailaddress of additional user
2369
     * $param string $invitation_code - the unique invitation code for the URL
2370
     */
2371
    public static function send_invitation_mail(
2372
        $invitedUser,
2373
        $invitation_code,
2374
        $invitation_title,
2375
        $invitation_text
2376
    ) {
2377
        $_user = api_get_user_info();
2378
        $_course = api_get_course_info();
2379
        $sessionId = api_get_session_id();
2380
2381
        // Replacing the **link** part with a valid link for the user
2382
        $link = api_get_path(WEB_CODE_PATH).'survey/fillsurvey.php?';
2383
        $link .= 'id_session='.$sessionId.'&course='.$_course['code'].'&invitationcode='.$invitation_code;
2384
2385
        $text_link = '<a href="'.$link.'">'.get_lang('ClickHereToAnswerTheSurvey')."</a><br />\r\n<br />\r\n"
2386
            .get_lang('OrCopyPasteTheFollowingUrl')." <br />\r\n ".$link;
2387
2388
        $replace_count = 0;
2389
        $full_invitation_text = api_str_ireplace('**link**', $text_link, $invitation_text, $replace_count);
2390
        if ($replace_count < 1) {
2391
            $full_invitation_text = $full_invitation_text."<br />\r\n<br />\r\n".$text_link;
2392
        }
2393
2394
        // Sending the mail
2395
        $sender_name = api_get_person_name($_user['firstName'], $_user['lastName'], null, PERSON_NAME_EMAIL_ADDRESS);
2396
        $sender_email = $_user['mail'];
2397
        $sender_user_id = api_get_user_id();
2398
2399
        $replyto = [];
2400
        if (api_get_setting('survey_email_sender_noreply') == 'noreply') {
2401
            $noreply = api_get_setting('noreply_email_address');
2402
            if (!empty($noreply)) {
2403
                $replyto['Reply-to'] = $noreply;
2404
                $sender_name = $noreply;
2405
                $sender_email = $noreply;
2406
                $sender_user_id = null;
2407
            }
2408
        }
2409
2410
        // Optionally: finding the e-mail of the course user
2411
        if (is_numeric($invitedUser)) {
2412
            MessageManager::send_message(
2413
                $invitedUser,
2414
                $invitation_title,
2415
                $full_invitation_text,
2416
                [],
2417
                [],
2418
                null,
2419
                null,
2420
                null,
2421
                null,
2422
                $sender_user_id
2423
            );
2424
        } else {
2425
            /** @todo check if the address is a valid email */
2426
            $recipient_email = $invitedUser;
2427
            @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

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