Test Failed
Push — master ( 482637...7bef58 )
by Julito
33:32
created

SurveyUtil::invitationExists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 12
nc 1
nop 4
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CSurvey;
5
use ChamiloSession as Session;
6
7
/**
8
 * This class offers a series of general utility functions for survey querying and display.
9
 *
10
 * @package chamilo.survey
11
 */
12
class SurveyUtil
13
{
14
    /**
15
     * Checks whether the given survey has a pagebreak question as the first
16
     * or the last question.
17
     * If so, break the current process, displaying an error message.
18
     *
19
     * @param int  $survey_id Survey ID (database ID)
20
     * @param bool $continue  Optional. Whether to continue the current
21
     *                        process or exit when breaking condition found. Defaults to true (do not break).
22
     */
23
    public static function check_first_last_question($survey_id, $continue = true)
24
    {
25
        // Table definitions
26
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
27
        $course_id = api_get_course_int_id();
28
29
        // Getting the information of the question
30
        $sql = "SELECT * FROM $tbl_survey_question
31
                WHERE c_id = $course_id AND survey_id='".Database::escape_string($survey_id)."'
32
                ORDER BY sort ASC";
33
        $result = Database::query($sql);
34
        $total = Database::num_rows($result);
35
        $counter = 1;
36
        $error = false;
37
        while ($row = Database::fetch_array($result, 'ASSOC')) {
38
            if ($counter == 1 && $row['type'] == 'pagebreak') {
39
                echo Display::return_message(get_lang('PagebreakNotFirst'), 'error', false);
40
                $error = true;
41
            }
42
            if ($counter == $total && $row['type'] == 'pagebreak') {
43
                echo Display::return_message(get_lang('PagebreakNotLast'), 'error', false);
44
                $error = true;
45
            }
46
            $counter++;
47
        }
48
49
        if (!$continue && $error) {
50
            Display::display_footer();
51
            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...
52
        }
53
    }
54
55
    /**
56
     * This function removes an (or multiple) answer(s) of a user on a question of a survey.
57
     *
58
     * @param mixed   The user id or email of the person who fills the survey
59
     * @param int The survey id
60
     * @param int The question id
61
     * @param int The option id
62
     *
63
     * @author Patrick Cool <[email protected]>, Ghent University
64
     *
65
     * @version January 2007
66
     */
67
    public static function remove_answer($user, $survey_id, $question_id, $course_id)
68
    {
69
        $course_id = intval($course_id);
70
        // table definition
71
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
72
        $sql = "DELETE FROM $table
73
				WHERE
74
				    c_id = $course_id AND
75
                    user = '".Database::escape_string($user)."' AND
76
                    survey_id = '".intval($survey_id)."' AND
77
                    question_id = '".intval($question_id)."'";
78
        Database::query($sql);
79
    }
80
81
    /**
82
     * This function stores an answer of a user on a question of a survey.
83
     *
84
     * @param mixed   The user id or email of the person who fills the survey
85
     * @param int Survey id
86
     * @param int Question id
87
     * @param int Option id
88
     * @param string  Option value
89
     * @param array $survey_data Survey data settings
90
     *
91
     * @return bool False if insufficient data, true otherwise
92
     *
93
     * @author Patrick Cool <[email protected]>, Ghent University
94
     *
95
     * @version January 2007
96
     */
97
    public static function store_answer(
98
        $user,
99
        $survey_id,
100
        $question_id,
101
        $option_id,
102
        $option_value,
103
        $survey_data
104
    ) {
105
        // If the question_id is empty, don't store an answer
106
        if (empty($question_id)) {
107
            return false;
108
        }
109
        // Table definition
110
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
111
112
        // Make the survey anonymous
113
        if ($survey_data['anonymous'] == 1) {
114
            $surveyUser = Session::read('surveyuser');
115
            if (empty($surveyUser)) {
116
                $user = md5($user.time());
117
                Session::write('surveyuser', $user);
118
            } else {
119
                $user = Session::read('surveyuser');
120
            }
121
        }
122
123
        $course_id = $survey_data['c_id'];
124
125
        $sql = "INSERT INTO $table_survey_answer (c_id, user, survey_id, question_id, option_id, value) VALUES (
126
				$course_id,
127
				'".Database::escape_string($user)."',
128
				'".Database::escape_string($survey_id)."',
129
				'".Database::escape_string($question_id)."',
130
				'".Database::escape_string($option_id)."',
131
				'".Database::escape_string($option_value)."'
132
				)";
133
        Database::query($sql);
134
        $insertId = Database::insert_id();
135
136
        $sql = "UPDATE $table_survey_answer SET answer_id = $insertId 
137
                WHERE iid = $insertId";
138
        Database::query($sql);
139
140
        return true;
141
    }
142
143
    /**
144
     * This function checks the parameters that are used in this page.
145
     *
146
     * @return string $people_filled The header, an error and the footer if any parameter fails, else it returns true
147
     *
148
     * @author Patrick Cool <[email protected]>, Ghent University
149
     *
150
     * @version February 2007
151
     */
152
    public static function check_parameters($people_filled)
153
    {
154
        $error = false;
155
156
        // Getting the survey data
157
        $survey_data = SurveyManager::get_survey($_GET['survey_id']);
158
159
        // $_GET['survey_id'] has to be numeric
160
        if (!is_numeric($_GET['survey_id'])) {
161
            $error = get_lang('IllegalSurveyId');
162
        }
163
164
        // $_GET['action']
165
        $allowed_actions = [
166
            'overview',
167
            'questionreport',
168
            'userreport',
169
            'comparativereport',
170
            'completereport',
171
            'deleteuserreport',
172
        ];
173
        if (isset($_GET['action']) && !in_array($_GET['action'], $allowed_actions)) {
174
            $error = get_lang('ActionNotAllowed');
175
        }
176
177
        // User report
178
        if (isset($_GET['action']) && $_GET['action'] == 'userreport') {
179
            if ($survey_data['anonymous'] == 0) {
180
                foreach ($people_filled as $key => &$value) {
181
                    $people_filled_userids[] = $value['invited_user'];
182
                }
183
            } else {
184
                $people_filled_userids = $people_filled;
185
            }
186
187
            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...
188
                $error = get_lang('UnknowUser');
189
            }
190
        }
191
192
        // Question report
193
        if (isset($_GET['action']) && $_GET['action'] == 'questionreport') {
194
            if (isset($_GET['question']) && !is_numeric($_GET['question'])) {
195
                $error = get_lang('UnknowQuestion');
196
            }
197
        }
198
199
        if ($error) {
200
            $tool_name = get_lang('Reporting');
201
            Display::addFlash(
202
                Display::return_message(
203
                    get_lang('Error').': '.$error,
204
                    'error',
205
                    false
206
                )
207
            );
208
            Display::display_header($tool_name);
209
            Display::display_footer();
210
            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...
211
        } else {
212
            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...
213
        }
214
    }
215
216
    /**
217
     * This function deals with the action handling.
218
     *
219
     * @param array $survey_data
220
     * @param array $people_filled
221
     *
222
     * @author Patrick Cool <[email protected]>, Ghent University
223
     *
224
     * @version February 2007
225
     */
226
    public static function handle_reporting_actions($survey_data, $people_filled)
227
    {
228
        $action = isset($_GET['action']) ? $_GET['action'] : null;
229
230
        // Getting the number of question
231
        $temp_questions_data = SurveyManager::get_questions($_GET['survey_id']);
232
233
        // Sorting like they should be displayed and removing the non-answer question types (comment and pagebreak)
234
        $my_temp_questions_data = $temp_questions_data == null ? [] : $temp_questions_data;
235
        $questions_data = [];
236
237
        foreach ($my_temp_questions_data as $key => &$value) {
238
            if ($value['type'] != 'comment' && $value['type'] != 'pagebreak') {
239
                $questions_data[$value['sort']] = $value;
240
            }
241
        }
242
243
        // Counting the number of questions that are relevant for the reporting
244
        $survey_data['number_of_questions'] = count($questions_data);
245
246
        if ($action == 'questionreport') {
247
            self::display_question_report($survey_data);
248
        }
249
        if ($action == 'userreport') {
250
            self::display_user_report($people_filled, $survey_data);
251
        }
252
        if ($action == 'comparativereport') {
253
            self::display_comparative_report();
254
        }
255
        if ($action == 'completereport') {
256
            self::display_complete_report($survey_data);
257
        }
258
        if ($action == 'deleteuserreport') {
259
            self::delete_user_report($_GET['survey_id'], $_GET['user']);
260
        }
261
    }
262
263
    /**
264
     * This function deletes the report of an user who wants to retake the survey.
265
     *
266
     * @param int $survey_id
267
     * @param int $user_id
268
     *
269
     * @author Christian Fasanando Flores <[email protected]>
270
     *
271
     * @version November 2008
272
     */
273
    public static function delete_user_report($survey_id, $user_id)
274
    {
275
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
276
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
277
        $table_survey = Database::get_course_table(TABLE_SURVEY);
278
279
        $course_id = api_get_course_int_id();
280
        $survey_id = (int) $survey_id;
281
        $user_id = Database::escape_string($user_id);
282
283
        if (!empty($survey_id) && !empty($user_id)) {
284
            // delete data from survey_answer by user_id and survey_id
285
            $sql = "DELETE FROM $table_survey_answer
286
			        WHERE c_id = $course_id AND survey_id = '".$survey_id."' AND user = '".$user_id."'";
287
            Database::query($sql);
288
            // update field answered from survey_invitation by user_id and survey_id
289
            $sql = "UPDATE $table_survey_invitation SET answered = '0'
290
			        WHERE
291
			            c_id = $course_id AND
292
			            survey_code = (
293
                            SELECT code FROM $table_survey
294
                            WHERE
295
                                c_id = $course_id AND
296
                                survey_id = '".$survey_id."'
297
                        ) AND
298
			            user = '".$user_id."'";
299
            $result = Database::query($sql);
300
        }
301
302
        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...
303
            $message = get_lang('SurveyUserAnswersHaveBeenRemovedSuccessfully').'<br />
304
					<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=userreport&survey_id='
305
                .$survey_id.'">'.
306
                get_lang('GoBack').'</a>';
307
            echo Display::return_message($message, 'confirmation', false);
308
        }
309
    }
310
311
    /**
312
     * This function displays the user report which is basically nothing more
313
     * than a one-page display of all the questions
314
     * of the survey that is filled with the answers of the person who filled the survey.
315
     *
316
     * @return string html code of the one-page survey with the answers of the selected user
317
     *
318
     * @author Patrick Cool <[email protected]>, Ghent University
319
     *
320
     * @version February 2007 - Updated March 2008
321
     */
322
    public static function display_user_report($people_filled, $survey_data)
323
    {
324
        // Database table definitions
325
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
326
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
327
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
328
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
329
330
        // Actions bar
331
        echo '<div class="actions">';
332
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'.
333
            Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('ReportingOverview'), '', ICON_SIZE_MEDIUM)
334
            .'</a>';
335
        if (isset($_GET['user'])) {
336
            if (api_is_allowed_to_edit()) {
337
                // The delete link
338
                echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=deleteuserreport&survey_id='
339
                    .$surveyId.'&'.api_get_cidreq().'&user='.Security::remove_XSS($_GET['user']).'" >'.
340
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_MEDIUM).'</a>';
341
            }
342
343
            // Export the user report
344
            echo '<a href="javascript: void(0);" onclick="document.form1a.submit();">'
345
                .Display::return_icon('export_csv.png', get_lang('ExportAsCSV'), '', ICON_SIZE_MEDIUM).'</a> ';
346
            echo '<a href="javascript: void(0);" onclick="document.form1b.submit();">'
347
                .Display::return_icon('export_excel.png', get_lang('ExportAsXLS'), '', ICON_SIZE_MEDIUM).'</a> ';
348
            echo '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='
349
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
350
                .Security::remove_XSS($_GET['user']).'">';
351
            echo '<input type="hidden" name="export_report" value="export_report">';
352
            echo '<input type="hidden" name="export_format" value="csv">';
353
            echo '</form>';
354
            echo '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='
355
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
356
                .Security::remove_XSS($_GET['user']).'">';
357
            echo '<input type="hidden" name="export_report" value="export_report">';
358
            echo '<input type="hidden" name="export_format" value="xls">';
359
            echo '</form>';
360
            echo '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='
361
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
362
        }
363
        echo '</div>';
364
365
        // Step 1: selection of the user
366
        echo "<script>
367
        function jumpMenu(targ,selObj,restore) {
368
            eval(targ+\".location='\"+selObj.options[selObj.selectedIndex].value+\"'\");
369
            if (restore) selObj.selectedIndex=0;
370
        }
371
		</script>";
372
        echo get_lang('SelectUserWhoFilledSurvey').'<br />';
373
374
        echo '<select name="user" onchange="jumpMenu(\'parent\',this,0)">';
375
        echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
376
            .Security::remove_XSS($_GET['action']).'&survey_id='.intval($_GET['survey_id']).'">'
377
            .get_lang('SelectUser').'</option>';
378
379
        foreach ($people_filled as $key => &$person) {
380
            if ($survey_data['anonymous'] == 0) {
381
                $name = $person['user_info']['complete_name_with_username'];
382
                $id = $person['user_id'];
383
                if ($id == '') {
384
                    $id = $person['invited_user'];
385
                    $name = $person['invited_user'];
386
                }
387
            } else {
388
                $name = get_lang('Anonymous').' '.($key + 1);
389
                $id = $person;
390
            }
391
            echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
392
                .Security::remove_XSS($_GET['action']).'&survey_id='.intval($_GET['survey_id']).'&user='
393
                .Security::remove_XSS($id).'" ';
394
            if (isset($_GET['user']) && $_GET['user'] == $id) {
395
                echo 'selected="selected"';
396
            }
397
            echo '>'.$name.'</option>';
398
        }
399
        echo '</select>';
400
401
        $course_id = api_get_course_int_id();
402
        // Step 2: displaying the survey and the answer of the selected users
403
        if (isset($_GET['user'])) {
404
            echo Display::return_message(
405
                get_lang('AllQuestionsOnOnePage'),
406
                'normal',
407
                false
408
            );
409
410
            // Getting all the questions and options
411
            $sql = "SELECT
412
			            survey_question.question_id,
413
			            survey_question.survey_id,
414
			            survey_question.survey_question,
415
			            survey_question.display,
416
			            survey_question.max_value,
417
			            survey_question.sort,
418
			            survey_question.type,
419
                        survey_question_option.question_option_id,
420
                        survey_question_option.option_text,
421
                        survey_question_option.sort as option_sort
422
					FROM $table_survey_question survey_question
423
					LEFT JOIN $table_survey_question_option survey_question_option
424
					ON
425
					    survey_question.question_id = survey_question_option.question_id AND
426
					    survey_question_option.c_id = $course_id
427
					WHERE
428
					    survey_question.survey_id = '".intval($_GET['survey_id'])."' AND
429
                        survey_question.c_id = $course_id
430
					ORDER BY survey_question.sort, survey_question_option.sort ASC";
431
            $result = Database::query($sql);
432
            while ($row = Database::fetch_array($result, 'ASSOC')) {
433
                if ($row['type'] != 'pagebreak') {
434
                    $questions[$row['sort']]['question_id'] = $row['question_id'];
435
                    $questions[$row['sort']]['survey_id'] = $row['survey_id'];
436
                    $questions[$row['sort']]['survey_question'] = $row['survey_question'];
437
                    $questions[$row['sort']]['display'] = $row['display'];
438
                    $questions[$row['sort']]['type'] = $row['type'];
439
                    $questions[$row['sort']]['maximum_score'] = $row['max_value'];
440
                    $questions[$row['sort']]['options'][$row['question_option_id']] = $row['option_text'];
441
                }
442
            }
443
444
            // Getting all the answers of the user
445
            $sql = "SELECT * FROM $table_survey_answer
446
			        WHERE
447
                        c_id = $course_id AND
448
                        survey_id = '".intval($_GET['survey_id'])."' AND
449
                        user = '".Database::escape_string($_GET['user'])."'";
450
            $result = Database::query($sql);
451
            while ($row = Database::fetch_array($result, 'ASSOC')) {
452
                $answers[$row['question_id']][] = $row['option_id'];
453
                $all_answers[$row['question_id']][] = $row;
454
            }
455
456
            // Displaying all the questions
457
458
            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...
459
                // If the question type is a scoring then we have to format the answers differently
460
                switch ($question['type']) {
461
                    case 'score':
462
                        $finalAnswer = [];
463
                        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...
464
                            foreach ($all_answers[$question['question_id']] as $key => &$answer_array) {
465
                                $finalAnswer[$answer_array['option_id']] = $answer_array['value'];
466
                            }
467
                        }
468
                        break;
469
                    case 'multipleresponse':
470
                        $finalAnswer = isset($answers[$question['question_id']])
471
                            ? $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...
472
                            : '';
473
                        break;
474
                    default:
475
                        $finalAnswer = '';
476
                        if (isset($all_answers[$question['question_id']])) {
477
                            $finalAnswer = $all_answers[$question['question_id']][0]['option_id'];
478
                        }
479
                        break;
480
                }
481
482
                $ch_type = 'ch_'.$question['type'];
483
                /** @var survey_question $display */
484
                $display = new $ch_type();
485
486
                $url = api_get_self();
487
                $form = new FormValidator('question', 'post', $url);
488
                $form->addHtml('<div class="survey_question_wrapper"><div class="survey_question">');
489
                $form->addHtml($question['survey_question']);
490
                $display->render($form, $question, $finalAnswer);
491
                $form->addHtml('</div></div>');
492
                $form->display();
493
            }
494
        }
495
    }
496
497
    /**
498
     * This function displays the report by question.
499
     *
500
     * It displays a table with all the options of the question and the number of users who have answered positively on
501
     * the option. The number of users who answered positive on a given option is expressed in an absolute number, in a
502
     * percentage of the total and graphically using bars By clicking on the absolute number you get a list with the
503
     * persons who have answered this. You can then click on the name of the person and you will then go to the report
504
     * by user where you see all the answers of that user.
505
     *
506
     * @param    array    All the survey data
507
     *
508
     * @return string html code that displays the report by question
509
     *
510
     * @todo allow switching between horizontal and vertical.
511
     * @todo multiple response: percentage are probably not OK
512
     * @todo the question and option text have to be shortened and should expand when the user clicks on it.
513
     * @todo the pagebreak and comment question types should not be shown => removed from $survey_data before
514
     *
515
     * @author Patrick Cool <[email protected]>, Ghent University
516
     *
517
     * @version February 2007 - Updated March 2008
518
     */
519
    public static function display_question_report($survey_data)
520
    {
521
        $singlePage = isset($_GET['single_page']) ? intval($_GET['single_page']) : 0;
522
        $course_id = api_get_course_int_id();
523
        // Database table definitions
524
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
525
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
526
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
527
528
        // Determining the offset of the sql statement (the n-th question of the survey)
529
        $offset = !isset($_GET['question']) ? 0 : intval($_GET['question']);
530
        $currentQuestion = isset($_GET['question']) ? intval($_GET['question']) : 0;
531
        $questions = [];
532
        $surveyId = intval($_GET['survey_id']);
533
        $action = Security::remove_XSS($_GET['action']);
534
535
        echo '<div class="actions">';
536
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'.
537
            Display::return_icon(
538
                'back.png',
539
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
540
                '',
541
                ICON_SIZE_MEDIUM
542
            ).'</a>';
543
        echo '</div>';
544
545
        if ($survey_data['number_of_questions'] > 0) {
546
            $limitStatement = null;
547
            if (!$singlePage) {
548
                echo '<div id="question_report_questionnumbers" class="pagination">';
549
                if ($currentQuestion != 0) {
550
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
551
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset - 1).'">'
552
                        .get_lang('PreviousQuestion').'</a></li>';
553
                }
554
555
                for ($i = 1; $i <= $survey_data['number_of_questions']; $i++) {
556
                    if ($offset != $i - 1) {
557
                        echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
558
                            .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($i - 1).'">'.$i.'</a></li>';
559
                    } else {
560
                        echo '<li class="disabled"s><a href="#">'.$i.'</a></li>';
561
                    }
562
                }
563
                if ($currentQuestion < ($survey_data['number_of_questions'] - 1)) {
564
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
565
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset + 1).'">'
566
                        .get_lang('NextQuestion').'</li></a>';
567
                }
568
                echo '</ul>';
569
                echo '</div>';
570
                $limitStatement = " LIMIT $offset, 1";
571
            }
572
573
            // Getting the question information
574
            $sql = "SELECT * FROM $table_survey_question
575
			        WHERE
576
			            c_id = $course_id AND
577
                        survey_id='".intval($_GET['survey_id'])."' AND
578
                        type <>'pagebreak' AND 
579
                        type <>'comment'
580
                    ORDER BY sort ASC
581
                    $limitStatement";
582
            $result = Database::query($sql);
583
            while ($row = Database::fetch_array($result)) {
584
                $questions[$row['question_id']] = $row;
585
            }
586
        }
587
588
        foreach ($questions as $question) {
589
            $chartData = [];
590
            $options = [];
591
            echo '<div class="title-question">';
592
            echo strip_tags(isset($question['survey_question']) ? $question['survey_question'] : null);
593
            echo '</div>';
594
595
            if ($question['type'] == 'score') {
596
                /** @todo This function should return the options as this is needed further in the code */
597
                $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...
598
            } elseif ($question['type'] == 'open') {
599
                /** @todo Also get the user who has answered this */
600
                $sql = "SELECT * FROM $table_survey_answer
601
                        WHERE
602
                            c_id = $course_id AND
603
                            survey_id='".intval($_GET['survey_id'])."' AND
604
                            question_id = '".intval($question['question_id'])."'";
605
                $result = Database::query($sql);
606
                while ($row = Database::fetch_array($result, 'ASSOC')) {
607
                    echo $row['option_id'].'<hr noshade="noshade" size="1" />';
608
                }
609
            } else {
610
                // Getting the options ORDER BY sort ASC
611
                $sql = "SELECT * FROM $table_survey_question_option
612
                        WHERE
613
                            c_id = $course_id AND
614
                            survey_id='".intval($_GET['survey_id'])."'
615
                            AND question_id = '".intval($question['question_id'])."'
616
                        ORDER BY sort ASC";
617
                $result = Database::query($sql);
618
                while ($row = Database::fetch_array($result, 'ASSOC')) {
619
                    $options[$row['question_option_id']] = $row;
620
                }
621
                // Getting the answers
622
                $sql = "SELECT *, count(answer_id) as total FROM $table_survey_answer
623
                        WHERE
624
                            c_id = $course_id AND
625
                            survey_id='".intval($_GET['survey_id'])."'
626
                            AND question_id = '".intval($question['question_id'])."'
627
                        GROUP BY option_id, value";
628
                $result = Database::query($sql);
629
                $number_of_answers = [];
630
                $data = [];
631
                while ($row = Database::fetch_array($result, 'ASSOC')) {
632
                    if (!isset($number_of_answers[$row['question_id']])) {
633
                        $number_of_answers[$row['question_id']] = 0;
634
                    }
635
                    $number_of_answers[$row['question_id']] += $row['total'];
636
                    $data[$row['option_id']] = $row;
637
                }
638
639
                foreach ($options as $option) {
640
                    $optionText = strip_tags($option['option_text']);
641
                    $optionText = html_entity_decode($optionText);
642
                    $votes = isset($data[$option['question_option_id']]['total']) ?
643
                        $data[$option['question_option_id']]['total'] : '0';
644
                    array_push($chartData, ['option' => $optionText, 'votes' => $votes]);
645
                }
646
                $chartContainerId = 'chartContainer'.$question['question_id'];
647
                echo '<div id="'.$chartContainerId.'" class="col-md-12">';
648
                echo self::drawChart($chartData, false, $chartContainerId);
649
650
                // displaying the table: headers
651
                echo '<table class="display-survey table">';
652
                echo '	<tr>';
653
                echo '		<th>&nbsp;</th>';
654
                echo '		<th>'.get_lang('AbsoluteTotal').'</th>';
655
                echo '		<th>'.get_lang('Percentage').'</th>';
656
                echo '		<th>'.get_lang('VisualRepresentation').'</th>';
657
                echo '	<tr>';
658
659
                // Displaying the table: the content
660
                if (is_array($options)) {
661
                    foreach ($options as $key => &$value) {
662
                        $absolute_number = null;
663
                        if (isset($data[$value['question_option_id']])) {
664
                            $absolute_number = $data[$value['question_option_id']]['total'];
665
                        }
666
                        if ($question['type'] == 'percentage' && empty($absolute_number)) {
667
                            continue;
668
                        }
669
                        $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...
670
                            ? $number_of_answers[$option['question_id']]
671
                            : 0;
672
                        if ($number_of_answers[$option['question_id']] == 0) {
673
                            $answers_number = 0;
674
                        } else {
675
                            $answers_number = $absolute_number / $number_of_answers[$option['question_id']] * 100;
676
                        }
677
                        echo '	<tr>';
678
                        echo '		<td class="center">'.$value['option_text'].'</td>';
679
                        echo '		<td class="center">';
680
                        if ($absolute_number != 0) {
681
                            echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action
682
                                .'&survey_id='.$surveyId.'&question='.$offset.'&viewoption='
683
                                .$value['question_option_id'].'">'.$absolute_number.'</a>';
684
                        } else {
685
                            echo '0';
686
                        }
687
688
                        echo '      </td>';
689
                        echo '		<td class="center">'.round($answers_number, 2).' %</td>';
690
                        echo '		<td class="center">';
691
                        $size = $answers_number * 2;
692
                        if ($size > 0) {
693
                            echo '<div style="border:1px solid #264269; background-color:#aecaf4; height:10px; width:'
694
                                .$size.'px">&nbsp;</div>';
695
                        } else {
696
                            echo '<div style="text-align: left;">'.get_lang("NoDataAvailable").'</div>';
697
                        }
698
                        echo ' </td>';
699
                        echo ' </tr>';
700
                    }
701
                }
702
                // displaying the table: footer (totals)
703
                echo '	<tr>';
704
                echo '		<td class="total"><b>'.get_lang('Total').'</b></td>';
705
                echo '		<td class="total"><b>'
706
                    .($number_of_answers[$option['question_id']] == 0
707
                        ? '0'
708
                        : $number_of_answers[$option['question_id']])
709
                    .'</b></td>';
710
                echo '		<td class="total">&nbsp;</td>';
711
                echo '		<td class="total">&nbsp;</td>';
712
                echo '	</tr>';
713
                echo '</table>';
714
                echo '</div>';
715
            }
716
        }
717
        if (isset($_GET['viewoption'])) {
718
            echo '<div class="answered-people">';
719
            echo '<h4>'.get_lang('PeopleWhoAnswered').': '
720
                .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 588. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
721
722
            if (is_numeric($_GET['value'])) {
723
                $sql_restriction = "AND value='".Database::escape_string($_GET['value'])."'";
724
            }
725
726
            $sql = "SELECT user FROM $table_survey_answer
727
                    WHERE
728
                        c_id = $course_id AND
729
                        option_id = '".Database::escape_string($_GET['viewoption'])."'
730
                        $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...
731
            $result = Database::query($sql);
732
            echo '<ul>';
733
            while ($row = Database::fetch_array($result, 'ASSOC')) {
734
                $user_info = api_get_user_info($row['user']);
735
                echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=userreport&survey_id='
736
                    .$surveyId.'&user='.$row['user'].'">'
737
                    .$user_info['complete_name_with_username']
738
                    .'</a></li>';
739
            }
740
            echo '</ul>';
741
            echo '</div>';
742
        }
743
    }
744
745
    /**
746
     * Display score data about a survey question.
747
     *
748
     * @param    array    Question info
749
     * @param    int    The offset of results shown
750
     */
751
    public static function display_question_report_score($survey_data, $question, $offset)
752
    {
753
        // Database table definitions
754
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
755
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
756
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
757
        $course_id = api_get_course_int_id();
758
759
        // Getting the options
760
        $sql = "SELECT * FROM $table_survey_question_option
761
                WHERE
762
                    c_id = $course_id AND
763
                    survey_id='".intval($_GET['survey_id'])."' AND
764
                    question_id = '".intval($question['question_id'])."'
765
                ORDER BY sort ASC";
766
        $result = Database::query($sql);
767
        while ($row = Database::fetch_array($result)) {
768
            $options[$row['question_option_id']] = $row;
769
        }
770
771
        // Getting the answers
772
        $sql = "SELECT *, count(answer_id) as total 
773
                FROM $table_survey_answer
774
                WHERE
775
                   c_id = $course_id AND
776
                   survey_id='".intval($_GET['survey_id'])."' AND
777
                   question_id = '".Database::escape_string($question['question_id'])."'
778
                GROUP BY option_id, value";
779
        $result = Database::query($sql);
780
        $number_of_answers = 0;
781
        while ($row = Database::fetch_array($result)) {
782
            $number_of_answers += $row['total'];
783
            $data[$row['option_id']][$row['value']] = $row;
784
        }
785
786
        $chartData = [];
787
        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...
788
            $optionText = strip_tags($option['option_text']);
789
            $optionText = html_entity_decode($optionText);
790
            for ($i = 1; $i <= $question['max_value']; $i++) {
791
                $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...
792
                if (empty($votes)) {
793
                    $votes = '0';
794
                }
795
                array_push(
796
                    $chartData,
797
                    [
798
                        'serie' => $optionText,
799
                        'option' => $i,
800
                        'votes' => $votes,
801
                    ]
802
                );
803
            }
804
        }
805
        echo '<div id="chartContainer" class="col-md-12">';
806
        echo self::drawChart($chartData, true);
807
        echo '</div>';
808
809
        // Displaying the table: headers
810
        echo '<table class="data_table">';
811
        echo '	<tr>';
812
        echo '		<th>&nbsp;</th>';
813
        echo '		<th>'.get_lang('Score').'</th>';
814
        echo '		<th>'.get_lang('AbsoluteTotal').'</th>';
815
        echo '		<th>'.get_lang('Percentage').'</th>';
816
        echo '		<th>'.get_lang('VisualRepresentation').'</th>';
817
        echo '	<tr>';
818
        // Displaying the table: the content
819
        foreach ($options as $key => &$value) {
820
            for ($i = 1; $i <= $question['max_value']; $i++) {
821
                $absolute_number = $data[$value['question_option_id']][$i]['total'];
822
                echo '	<tr>';
823
                echo '		<td>'.$value['option_text'].'</td>';
824
                echo '		<td>'.$i.'</td>';
825
                echo '		<td><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action
826
                    .'&survey_id='.intval($_GET['survey_id']).'&question='.Security::remove_XSS($offset)
827
                    .'&viewoption='.$value['question_option_id'].'&value='.$i.'">'.$absolute_number.'</a></td>';
828
                echo '		<td>'.round($absolute_number / $number_of_answers * 100, 2).' %</td>';
829
                echo '		<td>';
830
                $size = ($absolute_number / $number_of_answers * 100 * 2);
831
                if ($size > 0) {
832
                    echo '<div style="border:1px solid #264269; background-color:#aecaf4; height:10px; width:'.$size.'px">&nbsp;</div>';
833
                }
834
                echo '		</td>';
835
                echo '	</tr>';
836
            }
837
        }
838
        // Displaying the table: footer (totals)
839
        echo '	<tr>';
840
        echo '		<td style="border-top:1px solid black"><b>'.get_lang('Total').'</b></td>';
841
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
842
        echo '		<td style="border-top:1px solid black"><b>'.$number_of_answers.'</b></td>';
843
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
844
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
845
        echo '	</tr>';
846
847
        echo '</table>';
848
    }
849
850
    /**
851
     * This functions displays the complete reporting.
852
     *
853
     * @return string HTML code
854
     *
855
     * @todo open questions are not in the complete report yet.
856
     *
857
     * @author Patrick Cool <[email protected]>, Ghent University
858
     *
859
     * @version February 2007
860
     */
861
    public static function display_complete_report($survey_data)
862
    {
863
        // Database table definitions
864
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
865
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
866
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
867
868
        $surveyId = isset($_GET['survey_id']) ? intval($_GET['survey_id']) : 0;
869
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
870
871
        // Actions bar
872
        echo '<div class="actions">';
873
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'
874
            .Display::return_icon(
875
                'back.png',
876
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
877
                [],
878
                ICON_SIZE_MEDIUM
879
            )
880
            .'</a>';
881
        echo '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1a.submit();">'
882
            .Display::return_icon('export_csv.png', get_lang('ExportAsCSV'), '', ICON_SIZE_MEDIUM).'</a>';
883
        echo '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1b.submit();">'
884
            .Display::return_icon('export_excel.png', get_lang('ExportAsXLS'), '', ICON_SIZE_MEDIUM).'</a>';
885
        echo '</div>';
886
887
        // The form
888
        echo '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
889
            .$surveyId.'&'.api_get_cidreq().'">';
890
        echo '<input type="hidden" name="export_report" value="export_report">';
891
        echo '<input type="hidden" name="export_format" value="csv">';
892
        echo '</form>';
893
        echo '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
894
            .$surveyId.'&'.api_get_cidreq().'">';
895
        echo '<input type="hidden" name="export_report" value="export_report">';
896
        echo '<input type="hidden" name="export_format" value="xls">';
897
        echo '</form>';
898
899
        echo '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
900
            .$surveyId.'&'.api_get_cidreq().'">';
901
902
        // The table
903
        echo '<br /><table class="data_table" border="1">';
904
        // Getting the number of options per question
905
        echo '	<tr>';
906
        echo '		<th>';
907
        if ((isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
908
            (isset($_POST['export_report']) && $_POST['export_report'])
909
        ) {
910
            echo '<button class="cancel" type="submit" name="reset_question_filter" value="'
911
                .get_lang('ResetQuestionFilter').'">'.get_lang('ResetQuestionFilter').'</button>';
912
        }
913
        echo '<button class="save" type="submit" name="submit_question_filter" value="'.get_lang('SubmitQuestionFilter')
914
            .'">'.get_lang('SubmitQuestionFilter').'</button>';
915
        echo '</th>';
916
917
        $display_extra_user_fields = false;
918
        if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
919
                isset($_POST['export_report']) && $_POST['export_report']) ||
920
            !empty($_POST['fields_filter'])
921
        ) {
922
            // Show user fields section with a big th colspan that spans over all fields
923
            $extra_user_fields = UserManager::get_extra_fields(
924
                0,
925
                0,
926
                5,
927
                'ASC',
928
                false,
929
                true
930
            );
931
            $num = count($extra_user_fields);
932
            if ($num > 0) {
933
                echo '<th '.($num > 0 ? ' colspan="'.$num.'"' : '').'>';
934
                echo '<label><input type="checkbox" name="fields_filter" value="1" checked="checked"/> ';
935
                echo get_lang('UserFields');
936
                echo '</label>';
937
                echo '</th>';
938
                $display_extra_user_fields = true;
939
            }
940
        }
941
942
        $course_id = api_get_course_int_id();
943
        $sql = "SELECT q.question_id, q.type, q.survey_question, count(o.question_option_id) as number_of_options
944
				FROM $table_survey_question q 
945
				LEFT JOIN $table_survey_question_option o
946
				ON q.question_id = o.question_id
947
				WHERE 
948
				    q.survey_id = '".$surveyId."' AND
949
				    q.c_id = $course_id AND
950
				    o.c_id = $course_id
951
				GROUP BY q.question_id
952
				ORDER BY q.sort ASC";
953
        $result = Database::query($sql);
954
        $questions = [];
955
        while ($row = Database::fetch_array($result)) {
956
            // We show the questions if
957
            // 1. there is no question filter and the export button has not been clicked
958
            // 2. there is a quesiton filter but the question is selected for display
959
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
960
                (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))
961
            ) {
962
                // We do not show comment and pagebreak question types
963
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
964
                    echo ' <th';
965
                    // <hub> modified tst to include percentage
966
                    if ($row['number_of_options'] > 0 && $row['type'] != 'percentage') {
967
                        // </hub>
968
                        echo ' colspan="'.$row['number_of_options'].'"';
969
                    }
970
                    echo '>';
971
972
                    echo '<label><input type="checkbox" name="questions_filter[]" value="'.$row['question_id']
973
                        .'" checked="checked"/> ';
974
                    echo $row['survey_question'];
975
                    echo '</label>';
976
                    echo '</th>';
977
                }
978
                // No column at all if it's not a question
979
            }
980
            $questions[$row['question_id']] = $row;
981
        }
982
        echo '	</tr>';
983
        // Getting all the questions and options
984
        echo '	<tr>';
985
        echo '		<th>&nbsp;</th>'; // the user column
986
987
        if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
988
                isset($_POST['export_report']) && $_POST['export_report']) || !empty($_POST['fields_filter'])) {
989
            //show the fields names for user fields
990
            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...
991
                echo '<th>'.$field[3].'</th>';
992
            }
993
        }
994
995
        // cells with option (none for open question)
996
        $sql = "SELECT 	
997
                    sq.question_id, sq.survey_id,
998
                    sq.survey_question, sq.display,
999
                    sq.sort, sq.type, sqo.question_option_id,
1000
                    sqo.option_text, sqo.sort as option_sort
1001
				FROM $table_survey_question sq
1002
				LEFT JOIN $table_survey_question_option sqo
1003
				ON sq.question_id = sqo.question_id
1004
				WHERE
1005
				    sq.survey_id = '".$surveyId."' AND
1006
                    sq.c_id = $course_id AND
1007
                    sqo.c_id = $course_id
1008
				ORDER BY sq.sort ASC, sqo.sort ASC";
1009
        $result = Database::query($sql);
1010
1011
        $display_percentage_header = 1;
1012
        $possible_answers = [];
1013
        // in order to display only once the cell option (and not 100 times)
1014
        while ($row = Database::fetch_array($result)) {
1015
            // We show the options if
1016
            // 1. there is no question filter and the export button has not been clicked
1017
            // 2. there is a question filter but the question is selected for display
1018
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
1019
                (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))
1020
            ) {
1021
                // <hub> modif 05-05-2010
1022
                // we do not show comment and pagebreak question types
1023
                if ($row['type'] == 'open') {
1024
                    echo '<th>&nbsp;-&nbsp;</th>';
1025
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1026
                    $display_percentage_header = 1;
1027
                } elseif ($row['type'] == 'percentage' && $display_percentage_header) {
1028
                    echo '<th>&nbsp;%&nbsp;</th>';
1029
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1030
                    $display_percentage_header = 0;
1031
                } elseif ($row['type'] == 'percentage') {
1032
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1033
                } elseif ($row['type'] != 'comment' && $row['type'] != 'pagebreak' && $row['type'] != 'percentage') {
1034
                    echo '<th>';
1035
                    echo $row['option_text'];
1036
                    echo '</th>';
1037
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1038
                    $display_percentage_header = 1;
1039
                }
1040
                //no column at all if the question was not a question
1041
                // </hub>
1042
            }
1043
        }
1044
1045
        echo '	</tr>';
1046
1047
        // Getting all the answers of the users
1048
        $old_user = '';
1049
        $answers_of_user = [];
1050
        $sql = "SELECT * FROM $table_survey_answer
1051
                WHERE
1052
                    c_id = $course_id AND
1053
                    survey_id='".$surveyId."'
1054
                ORDER BY answer_id, user ASC";
1055
        $result = Database::query($sql);
1056
        $i = 1;
1057
        while ($row = Database::fetch_array($result)) {
1058
            if ($old_user != $row['user'] && $old_user != '') {
1059
                $userParam = $old_user;
1060
                if ($survey_data['anonymous'] != 0) {
1061
                    $userParam = $i;
1062
                    $i++;
1063
                }
1064
                self::display_complete_report_row(
1065
                    $survey_data,
1066
                    $possible_answers,
1067
                    $answers_of_user,
1068
                    $userParam,
1069
                    $questions,
1070
                    $display_extra_user_fields
1071
                );
1072
                $answers_of_user = [];
1073
            }
1074
            if (isset($questions[$row['question_id']]) && $questions[$row['question_id']]['type'] != 'open') {
1075
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1076
            } else {
1077
                $answers_of_user[$row['question_id']][0] = $row;
1078
            }
1079
            $old_user = $row['user'];
1080
        }
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
        // This is to display the last user
1095
        echo '</table>';
1096
        echo '</form>';
1097
    }
1098
1099
    /**
1100
     * This function displays a row (= a user and his/her answers) in the table of the complete report.
1101
     *
1102
     * @param array $survey_data
1103
     * @param array    Possible options
1104
     * @param array    User answers
1105
     * @param mixed    User ID or user details string
1106
     * @param bool  Whether to show extra user fields or not
1107
     *
1108
     * @author Patrick Cool <[email protected]>, Ghent University
1109
     *
1110
     * @version February 2007 - Updated March 2008
1111
     */
1112
    public static function display_complete_report_row(
1113
        $survey_data,
1114
        $possible_options,
1115
        $answers_of_user,
1116
        $user,
1117
        $questions,
1118
        $display_extra_user_fields = false
1119
    ) {
1120
        $user = Security::remove_XSS($user);
1121
        echo '<tr>';
1122
        if ($survey_data['anonymous'] == 0) {
1123
            if (intval($user) !== 0) {
1124
                $userInfo = api_get_user_info($user);
1125
                if (!empty($userInfo)) {
1126
                    $user_displayed = $userInfo['complete_name_with_username'];
1127
                } else {
1128
                    $user_displayed = '-';
1129
                }
1130
                echo '<th>
1131
                    <a href="'.api_get_self().'?action=userreport&survey_id='.intval($_GET['survey_id']).'&user='.$user.'">'
1132
                    .$user_displayed.'</a>
1133
                    </th>'; // the user column
1134
            } else {
1135
                echo '<th>'.$user.'</th>'; // the user column
1136
            }
1137
        } else {
1138
            echo '<th>'.get_lang('Anonymous').' '.$user.'</th>';
1139
        }
1140
1141
        if ($display_extra_user_fields) {
1142
            // Show user fields data, if any, for this user
1143
            $user_fields_values = UserManager::get_extra_user_data(
1144
                intval($user),
1145
                false,
1146
                false,
1147
                false,
1148
                true
1149
            );
1150
            foreach ($user_fields_values as &$value) {
1151
                echo '<td align="center">'.$value.'</td>';
1152
            }
1153
        }
1154
        if (is_array($possible_options)) {
1155
            // <hub> modified to display open answers and percentage
1156
            foreach ($possible_options as $question_id => &$possible_option) {
1157
                if ($questions[$question_id]['type'] == 'open') {
1158
                    echo '<td align="center">';
1159
                    echo $answers_of_user[$question_id]['0']['option_id'];
1160
                    echo '</td>';
1161
                } else {
1162
                    foreach ($possible_option as $option_id => &$value) {
1163
                        if ($questions[$question_id]['type'] == 'percentage') {
1164
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1165
                                echo "<td align='center'>";
1166
                                echo $answers_of_user[$question_id][$option_id]['value'];
1167
                                echo "</td>";
1168
                            }
1169
                        } else {
1170
                            echo '<td align="center">';
1171
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1172
                                if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1173
                                    echo $answers_of_user[$question_id][$option_id]['value'];
1174
                                } else {
1175
                                    echo 'v';
1176
                                }
1177
                            }
1178
                        }
1179
                    }
1180
                }
1181
            }
1182
        }
1183
        echo '</tr>';
1184
    }
1185
1186
    /**
1187
     * Quite similar to display_complete_report(), returns an HTML string
1188
     * that can be used in a csv file.
1189
     *
1190
     * @todo consider merging this function with display_complete_report
1191
     *
1192
     * @return string The contents of a csv file
1193
     *
1194
     * @author Patrick Cool <[email protected]>, Ghent University
1195
     *
1196
     * @version February 2007
1197
     */
1198
    public static function export_complete_report($survey_data, $user_id = 0)
1199
    {
1200
        // Database table definitions
1201
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1202
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1203
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1204
1205
        // The first column
1206
        $return = ';';
1207
1208
        // Show extra fields blank space (enough for extra fields on next line)
1209
        $extra_user_fields = UserManager::get_extra_fields(
1210
            0,
1211
            0,
1212
            5,
1213
            'ASC',
1214
            false,
1215
            true
1216
        );
1217
1218
        $num = count($extra_user_fields);
1219
        $return .= str_repeat(';', $num);
1220
1221
        $course_id = api_get_course_int_id();
1222
1223
        $sql = "SELECT
1224
                    questions.question_id,
1225
                    questions.type,
1226
                    questions.survey_question,
1227
                    count(options.question_option_id) as number_of_options
1228
				FROM $table_survey_question questions
1229
                LEFT JOIN $table_survey_question_option options
1230
				ON questions.question_id = options.question_id AND options.c_id = $course_id
1231
				WHERE
1232
				    questions.survey_id = '".intval($_GET['survey_id'])."' AND
1233
                    questions.c_id = $course_id
1234
				GROUP BY questions.question_id
1235
				ORDER BY questions.sort ASC";
1236
        $result = Database::query($sql);
1237
        while ($row = Database::fetch_array($result)) {
1238
            // We show the questions if
1239
            // 1. there is no question filter and the export button has not been clicked
1240
            // 2. there is a quesiton filter but the question is selected for display
1241
            if (!(isset($_POST['submit_question_filter'])) ||
1242
                (isset($_POST['submit_question_filter']) &&
1243
                    is_array($_POST['questions_filter']) &&
1244
                    in_array($row['question_id'], $_POST['questions_filter']))
1245
            ) {
1246
                // We do not show comment and pagebreak question types
1247
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
1248
                    if ($row['number_of_options'] == 0 && $row['type'] == 'open') {
1249
                        $return .= str_replace(
1250
                            "\r\n",
1251
                            '  ',
1252
                            api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1253
                        )
1254
                        .';';
1255
                    } else {
1256
                        for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1257
                            $return .= str_replace(
1258
                                "\r\n",
1259
                                '  ',
1260
                                api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1261
                            )
1262
                            .';';
1263
                        }
1264
                    }
1265
                }
1266
            }
1267
        }
1268
        $return .= "\n";
1269
1270
        // Getting all the questions and options
1271
        $return .= ';';
1272
1273
        // Show the fields names for user fields
1274
        if (!empty($extra_user_fields)) {
1275
            foreach ($extra_user_fields as &$field) {
1276
                $return .= '"'
1277
                    .str_replace(
1278
                        "\r\n",
1279
                        '  ',
1280
                        api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1281
                    )
1282
                    .'";';
1283
            }
1284
        }
1285
1286
        $sql = "SELECT
1287
		            survey_question.question_id,
1288
		            survey_question.survey_id,
1289
		            survey_question.survey_question,
1290
		            survey_question.display,
1291
		            survey_question.sort,
1292
		            survey_question.type,
1293
                    survey_question_option.question_option_id,
1294
                    survey_question_option.option_text,
1295
                    survey_question_option.sort as option_sort
1296
				FROM $table_survey_question survey_question
1297
				LEFT JOIN $table_survey_question_option survey_question_option
1298
				ON
1299
				    survey_question.question_id = survey_question_option.question_id AND
1300
				    survey_question_option.c_id = $course_id
1301
				WHERE
1302
				    survey_question.survey_id = '".intval($_GET['survey_id'])."' AND
1303
				    survey_question.c_id = $course_id
1304
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1305
        $result = Database::query($sql);
1306
        $possible_answers = [];
1307
        $possible_answers_type = [];
1308
        while ($row = Database::fetch_array($result)) {
1309
            // We show the options if
1310
            // 1. there is no question filter and the export button has not been clicked
1311
            // 2. there is a question filter but the question is selected for display
1312
            if (!(isset($_POST['submit_question_filter'])) || (
1313
                is_array($_POST['questions_filter']) &&
1314
                in_array($row['question_id'], $_POST['questions_filter'])
1315
            )
1316
            ) {
1317
                // We do not show comment and pagebreak question types
1318
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
1319
                    $row['option_text'] = str_replace(["\r", "\n"], ['', ''], $row['option_text']);
1320
                    $return .= api_html_entity_decode(strip_tags($row['option_text']), ENT_QUOTES).';';
1321
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1322
                    $possible_answers_type[$row['question_id']] = $row['type'];
1323
                }
1324
            }
1325
        }
1326
        $return .= "\n";
1327
1328
        // Getting all the answers of the users
1329
        $old_user = '';
1330
        $answers_of_user = [];
1331
        $sql = "SELECT * FROM $table_survey_answer
1332
		        WHERE c_id = $course_id AND survey_id='".intval($_GET['survey_id'])."'";
1333
        if ($user_id != 0) {
1334
            $sql .= "AND user='".Database::escape_string($user_id)."' ";
1335
        }
1336
        $sql .= "ORDER BY user ASC";
1337
1338
        $open_question_iterator = 1;
1339
        $result = Database::query($sql);
1340
        while ($row = Database::fetch_array($result)) {
1341
            if ($old_user != $row['user'] && $old_user != '') {
1342
                $return .= self::export_complete_report_row(
1343
                    $survey_data,
1344
                    $possible_answers,
1345
                    $answers_of_user,
1346
                    $old_user,
1347
                    true
1348
                );
1349
                $answers_of_user = [];
1350
            }
1351
            if ($possible_answers_type[$row['question_id']] == 'open') {
1352
                $temp_id = 'open'.$open_question_iterator;
1353
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1354
                $open_question_iterator++;
1355
            } else {
1356
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1357
            }
1358
            $old_user = $row['user'];
1359
        }
1360
        // This is to display the last user
1361
        $return .= self::export_complete_report_row(
1362
            $survey_data,
1363
            $possible_answers,
1364
            $answers_of_user,
1365
            $old_user,
1366
            true
1367
        );
1368
1369
        return $return;
1370
    }
1371
1372
    /**
1373
     * Add a line to the csv file.
1374
     *
1375
     * @param array Possible answers
1376
     * @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...
1377
     * @param mixed User ID or user details as string - Used as a string in the result string
1378
     * @param bool Whether to display user fields or not
1379
     *
1380
     * @return string One line of the csv file
1381
     *
1382
     * @author Patrick Cool <[email protected]>, Ghent University
1383
     *
1384
     * @version February 2007
1385
     */
1386
    public static function export_complete_report_row(
1387
        $survey_data,
1388
        $possible_options,
1389
        $answers_of_user,
1390
        $user,
1391
        $display_extra_user_fields = false
1392
    ) {
1393
        $return = '';
1394
        if ($survey_data['anonymous'] == 0) {
1395
            if (intval($user) !== 0) {
1396
                $userInfo = api_get_user_info($user);
1397
                if (!empty($userInfo)) {
1398
                    $user_displayed = $userInfo['complete_name_with_username'];
1399
                } else {
1400
                    $user_displayed = '-';
1401
                }
1402
                $return .= $user_displayed.';';
1403
            } else {
1404
                $return .= $user.';';
1405
            }
1406
        } else {
1407
            $return .= '-;'; // The user column
1408
        }
1409
1410
        if ($display_extra_user_fields) {
1411
            // Show user fields data, if any, for this user
1412
            $user_fields_values = UserManager::get_extra_user_data(
1413
                $user,
1414
                false,
1415
                false,
1416
                false,
1417
                true
1418
            );
1419
            foreach ($user_fields_values as &$value) {
1420
                $return .= '"'.str_replace('"', '""', api_html_entity_decode(strip_tags($value), ENT_QUOTES)).'";';
1421
            }
1422
        }
1423
1424
        if (is_array($possible_options)) {
1425
            foreach ($possible_options as $question_id => $possible_option) {
1426
                if (is_array($possible_option) && count($possible_option) > 0) {
1427
                    foreach ($possible_option as $option_id => &$value) {
1428
                        $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];
1429
                        $key = array_keys($my_answer_of_user);
1430
                        if (isset($key[0]) && substr($key[0], 0, 4) == 'open') {
1431
                            $return .= '"'.
1432
                                str_replace(
1433
                                    '"',
1434
                                    '""',
1435
                                    api_html_entity_decode(
1436
                                        strip_tags(
1437
                                            $answers_of_user[$question_id][$key[0]]['option_id']
1438
                                        ),
1439
                                        ENT_QUOTES
1440
                                    )
1441
                                ).
1442
                                '"';
1443
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
1444
                            //$return .= 'v';
1445
                            if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1446
                                $return .= $answers_of_user[$question_id][$option_id]['value'];
1447
                            } else {
1448
                                $return .= 'v';
1449
                            }
1450
                        }
1451
                        $return .= ';';
1452
                    }
1453
                }
1454
            }
1455
        }
1456
        $return .= "\n";
1457
1458
        return $return;
1459
    }
1460
1461
    /**
1462
     * Quite similar to display_complete_report(), returns an HTML string
1463
     * that can be used in a csv file.
1464
     *
1465
     * @todo consider merging this function with display_complete_report
1466
     *
1467
     * @return string The contents of a csv file
1468
     *
1469
     * @author Patrick Cool <[email protected]>, Ghent University
1470
     *
1471
     * @version February 2007
1472
     */
1473
    public static function export_complete_report_xls($survey_data, $filename, $user_id = 0)
1474
    {
1475
        $course_id = api_get_course_int_id();
1476
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1477
1478
        if (empty($course_id) || empty($surveyId)) {
1479
            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...
1480
        }
1481
1482
        $spreadsheet = new PHPExcel();
1483
        $spreadsheet->setActiveSheetIndex(0);
1484
        $worksheet = $spreadsheet->getActiveSheet();
1485
        $line = 1;
1486
        $column = 1; // Skip the first column (row titles)
1487
1488
        // Show extra fields blank space (enough for extra fields on next line)
1489
        // Show user fields section with a big th colspan that spans over all fields
1490
        $extra_user_fields = UserManager::get_extra_fields(
1491
            0,
1492
            0,
1493
            5,
1494
            'ASC',
1495
            false,
1496
            true
1497
        );
1498
        $num = count($extra_user_fields);
1499
        for ($i = 0; $i < $num; $i++) {
1500
            $worksheet->setCellValueByColumnAndRow($column, $line, '');
1501
            $column++;
1502
        }
1503
1504
        $display_extra_user_fields = true;
1505
1506
        // Database table definitions
1507
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1508
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1509
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1510
1511
        // First line (questions)
1512
        $sql = "SELECT
1513
                    questions.question_id,
1514
                    questions.type,
1515
                    questions.survey_question,
1516
                    count(options.question_option_id) as number_of_options
1517
				FROM $table_survey_question questions
1518
				LEFT JOIN $table_survey_question_option options
1519
                ON questions.question_id = options.question_id AND options.c_id = $course_id
1520
				WHERE
1521
				    questions.survey_id = $surveyId AND
1522
				    questions.c_id = $course_id
1523
				GROUP BY questions.question_id
1524
				ORDER BY questions.sort ASC";
1525
        $result = Database::query($sql);
1526
        while ($row = Database::fetch_array($result)) {
1527
            // We show the questions if
1528
            // 1. there is no question filter and the export button has not been clicked
1529
            // 2. there is a quesiton filter but the question is selected for display
1530
            if (!(isset($_POST['submit_question_filter'])) ||
1531
                (isset($_POST['submit_question_filter']) && is_array($_POST['questions_filter']) &&
1532
                in_array($row['question_id'], $_POST['questions_filter']))
1533
            ) {
1534
                // We do not show comment and pagebreak question types
1535
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
1536
                    if ($row['number_of_options'] == 0 && $row['type'] == 'open') {
1537
                        $worksheet->setCellValueByColumnAndRow(
1538
                            $column,
1539
                            $line,
1540
                            api_html_entity_decode(
1541
                                strip_tags($row['survey_question']),
1542
                                ENT_QUOTES
1543
                            )
1544
                        );
1545
                        $column++;
1546
                    } else {
1547
                        for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1548
                            $worksheet->setCellValueByColumnAndRow(
1549
                                $column,
1550
                                $line,
1551
                                api_html_entity_decode(
1552
                                    strip_tags($row['survey_question']),
1553
                                    ENT_QUOTES
1554
                                )
1555
                            );
1556
                            $column++;
1557
                        }
1558
                    }
1559
                }
1560
            }
1561
        }
1562
1563
        $line++;
1564
        $column = 1;
1565
        // Show extra field values
1566
        if ($display_extra_user_fields) {
1567
            // Show the fields names for user fields
1568
            foreach ($extra_user_fields as &$field) {
1569
                $worksheet->setCellValueByColumnAndRow(
1570
                    $column,
1571
                    $line,
1572
                    api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1573
                );
1574
                $column++;
1575
            }
1576
        }
1577
1578
        // Getting all the questions and options (second line)
1579
        $sql = "SELECT
1580
                    survey_question.question_id, 
1581
                    survey_question.survey_id, 
1582
                    survey_question.survey_question, 
1583
                    survey_question.display, 
1584
                    survey_question.sort, 
1585
                    survey_question.type,
1586
                    survey_question_option.question_option_id, 
1587
                    survey_question_option.option_text, 
1588
                    survey_question_option.sort as option_sort
1589
				FROM $table_survey_question survey_question
1590
				LEFT JOIN $table_survey_question_option survey_question_option
1591
				ON 
1592
				    survey_question.question_id = survey_question_option.question_id AND 
1593
				    survey_question_option.c_id = $course_id
1594
				WHERE 
1595
				    survey_question.survey_id = $surveyId AND
1596
				    survey_question.c_id = $course_id
1597
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1598
        $result = Database::query($sql);
1599
        $possible_answers = [];
1600
        $possible_answers_type = [];
1601
        while ($row = Database::fetch_array($result)) {
1602
            // We show the options if
1603
            // 1. there is no question filter and the export button has not been clicked
1604
            // 2. there is a quesiton filter but the question is selected for display
1605
            if (!isset($_POST['submit_question_filter']) ||
1606
                (isset($_POST['questions_filter']) && is_array($_POST['questions_filter']) &&
1607
                in_array($row['question_id'], $_POST['questions_filter']))
1608
            ) {
1609
                // We do not show comment and pagebreak question types
1610
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
1611
                    $worksheet->setCellValueByColumnAndRow(
1612
                        $column,
1613
                        $line,
1614
                        api_html_entity_decode(
1615
                            strip_tags($row['option_text']),
1616
                            ENT_QUOTES
1617
                        )
1618
                    );
1619
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1620
                    $possible_answers_type[$row['question_id']] = $row['type'];
1621
                    $column++;
1622
                }
1623
            }
1624
        }
1625
1626
        // Getting all the answers of the users
1627
        $line++;
1628
        $column = 0;
1629
        $old_user = '';
1630
        $answers_of_user = [];
1631
        $sql = "SELECT * FROM $table_survey_answer
1632
                WHERE c_id = $course_id AND survey_id = $surveyId";
1633
        if ($user_id != 0) {
1634
            $sql .= " AND user='".intval($user_id)."' ";
1635
        }
1636
        $sql .= " ORDER BY user ASC";
1637
1638
        $open_question_iterator = 1;
1639
        $result = Database::query($sql);
1640
        while ($row = Database::fetch_array($result)) {
1641
            if ($old_user != $row['user'] && $old_user != '') {
1642
                $return = self::export_complete_report_row_xls(
1643
                    $survey_data,
1644
                    $possible_answers,
1645
                    $answers_of_user,
1646
                    $old_user,
1647
                    true
1648
                );
1649
                foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
1650
                    $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
1651
                    $column++;
1652
                }
1653
                $answers_of_user = [];
1654
                $line++;
1655
                $column = 0;
1656
            }
1657
            if ($possible_answers_type[$row['question_id']] == 'open') {
1658
                $temp_id = 'open'.$open_question_iterator;
1659
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1660
                $open_question_iterator++;
1661
            } else {
1662
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1663
            }
1664
            $old_user = $row['user'];
1665
        }
1666
1667
        $return = self::export_complete_report_row_xls(
1668
            $survey_data,
1669
            $possible_answers,
1670
            $answers_of_user,
1671
            $old_user,
1672
            true
1673
        );
1674
1675
        // this is to display the last user
1676
        foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
1677
            $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
1678
            $column++;
1679
        }
1680
1681
        $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
1682
        $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
1683
        $writer->save($file);
1684
        DocumentManager::file_send_for_download($file, true, $filename);
1685
1686
        return null;
1687
    }
1688
1689
    /**
1690
     * Add a line to the csv file.
1691
     *
1692
     * @param array Possible answers
1693
     * @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...
1694
     * @param mixed User ID or user details as string - Used as a string in the result string
1695
     * @param bool Whether to display user fields or not
1696
     *
1697
     * @return string One line of the csv file
1698
     */
1699
    public static function export_complete_report_row_xls(
1700
        $survey_data,
1701
        $possible_options,
1702
        $answers_of_user,
1703
        $user,
1704
        $display_extra_user_fields = false
1705
    ) {
1706
        $return = [];
1707
        if ($survey_data['anonymous'] == 0) {
1708
            if (intval($user) !== 0) {
1709
                $userInfo = api_get_user_info($user);
1710
                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...
1711
                    $user_displayed = $userInfo['complete_name_with_username'];
1712
                } else {
1713
                    $user_displayed = '-';
1714
                }
1715
                $return[] = $user_displayed;
1716
            } else {
1717
                $return[] = $user;
1718
            }
1719
        } else {
1720
            $return[] = '-'; // The user column
1721
        }
1722
1723
        if ($display_extra_user_fields) {
1724
            //show user fields data, if any, for this user
1725
            $user_fields_values = UserManager::get_extra_user_data(
1726
                intval($user),
1727
                false,
1728
                false,
1729
                false,
1730
                true
1731
            );
1732
            foreach ($user_fields_values as $value) {
1733
                $return[] = api_html_entity_decode(strip_tags($value), ENT_QUOTES);
1734
            }
1735
        }
1736
1737
        if (is_array($possible_options)) {
1738
            foreach ($possible_options as $question_id => &$possible_option) {
1739
                if (is_array($possible_option) && count($possible_option) > 0) {
1740
                    foreach ($possible_option as $option_id => &$value) {
1741
                        $my_answers_of_user = isset($answers_of_user[$question_id])
1742
                            ? $answers_of_user[$question_id]
1743
                            : [];
1744
                        $key = array_keys($my_answers_of_user);
1745
                        if (isset($key[0]) && substr($key[0], 0, 4) == 'open') {
1746
                            $return[] = api_html_entity_decode(
1747
                                strip_tags($answers_of_user[$question_id][$key[0]]['option_id']),
1748
                                ENT_QUOTES
1749
                            );
1750
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
1751
                            if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1752
                                $return[] = $answers_of_user[$question_id][$option_id]['value'];
1753
                            } else {
1754
                                $return[] = 'v';
1755
                            }
1756
                        } else {
1757
                            $return[] = '';
1758
                        }
1759
                    }
1760
                }
1761
            }
1762
        }
1763
1764
        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...
1765
    }
1766
1767
    /**
1768
     * This function displays the comparative report which
1769
     * allows you to compare two questions
1770
     * A comparative report creates a table where one question
1771
     * is on the x axis and a second question is on the y axis.
1772
     * In the intersection is the number of people who have
1773
     * answered positive on both options.
1774
     *
1775
     * @return string HTML code
1776
     *
1777
     * @author Patrick Cool <[email protected]>, Ghent University
1778
     *
1779
     * @version February 2007
1780
     */
1781
    public static function display_comparative_report()
1782
    {
1783
        // Allowed question types for comparative report
1784
        $allowed_question_types = [
1785
            'yesno',
1786
            'multiplechoice',
1787
            'multipleresponse',
1788
            'dropdown',
1789
            'percentage',
1790
            'score',
1791
        ];
1792
1793
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1794
1795
        // Getting all the questions
1796
        $questions = SurveyManager::get_questions($surveyId);
1797
1798
        // Actions bar
1799
        echo '<div class="actions">';
1800
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq()
1801
            .'">'
1802
            .Display::return_icon(
1803
                'back.png',
1804
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
1805
                [],
1806
                ICON_SIZE_MEDIUM
1807
            )
1808
            .'</a>';
1809
        echo '</div>';
1810
1811
        // Displaying an information message that only the questions with predefined answers can be used in a comparative report
1812
        echo Display::return_message(get_lang('OnlyQuestionsWithPredefinedAnswers'), 'normal', false);
1813
1814
        $xAxis = isset($_GET['xaxis']) ? Security::remove_XSS($_GET['xaxis']) : '';
1815
        $yAxis = isset($_GET['yaxis']) ? Security::remove_XSS($_GET['yaxis']) : '';
1816
1817
        $url = api_get_self().'?'.api_get_cidreq().'&action='.Security::remove_XSS($_GET['action'])
1818
            .'&survey_id='.$surveyId.'&xaxis='.$xAxis.'&y='.$yAxis;
1819
1820
        $form = new FormValidator('compare', 'get', $url);
1821
        $form->addHidden('action', Security::remove_XSS($_GET['action']));
1822
        $form->addHidden('survey_id', $surveyId);
1823
        $optionsX = ['----'];
1824
        $optionsY = ['----'];
1825
        $defaults = [];
1826
        foreach ($questions as $key => &$question) {
1827
            if (is_array($allowed_question_types)) {
1828
                if (in_array($question['type'], $allowed_question_types)) {
1829
                    //echo '<option value="'.$question['question_id'].'"';
1830
                    if (isset($_GET['xaxis']) && $_GET['xaxis'] == $question['question_id']) {
1831
                        $defaults['xaxis'] = $question['question_id'];
1832
                    }
1833
1834
                    if (isset($_GET['yaxis']) && $_GET['yaxis'] == $question['question_id']) {
1835
                        $defaults['yaxis'] = $question['question_id'];
1836
                    }
1837
1838
                    $optionsX[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 50);
1839
                    $optionsY[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 50);
1840
                }
1841
            }
1842
        }
1843
1844
        $form->addSelect('xaxis', get_lang('SelectXAxis'), $optionsX);
1845
        $form->addSelect('yaxis', get_lang('SelectYAxis'), $optionsY);
1846
1847
        $form->addButtonSearch(get_lang('CompareQuestions'));
1848
        $form->setDefaults($defaults);
1849
        $form->display();
1850
1851
        // Getting all the information of the x axis
1852
        if (is_numeric($xAxis)) {
1853
            $question_x = SurveyManager::get_question($xAxis);
1854
        }
1855
1856
        // Getting all the information of the y axis
1857
        if (is_numeric($yAxis)) {
1858
            $question_y = SurveyManager::get_question($yAxis);
1859
        }
1860
1861
        if (is_numeric($xAxis) && is_numeric($yAxis)) {
1862
            // Getting the answers of the two questions
1863
            $answers_x = self::get_answers_of_question_by_user($surveyId, $xAxis);
1864
            $answers_y = self::get_answers_of_question_by_user($surveyId, $yAxis);
1865
1866
            // Displaying the table
1867
            $tableHtml = '<table border="1" class="data_table">';
1868
            $xOptions = [];
1869
            // The header
1870
            $tableHtml .= '<tr>';
1871
            for ($ii = 0; $ii <= count($question_x['answers']); $ii++) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_x does not seem to be defined for all execution paths leading up to this point.
Loading history...
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

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

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

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

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