Completed
Push — master ( f41061...196bfc )
by Julito
09:03
created

SurveyUtil::update_count_invited()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 38
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2327
                $sql = "UPDATE $table
2328
                        SET survey_invitation_id = $insertId
2329
                        WHERE iid = $insertId";
2330
                Database::query($sql);
2331
            }
2332
2333
            return $insertId;
2334
        }
2335
2336
        return false;
2337
    }
2338
2339
    /**
2340
     * @param int    $courseId
2341
     * @param int    $sessionId
2342
     * @param int    $groupId
2343
     * @param string $surveyCode
2344
     *
2345
     * @return int
2346
     */
2347
    public static function invitationExists($courseId, $sessionId, $groupId, $surveyCode)
2348
    {
2349
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2350
        $courseId = (int) $courseId;
2351
        $sessionId = (int) $sessionId;
2352
        $groupId = (int) $groupId;
2353
        $surveyCode = Database::escape_string($surveyCode);
2354
2355
        $sql = "SELECT survey_invitation_id FROM $table
2356
                WHERE
2357
                    c_id = $courseId AND
2358
                    session_id = $sessionId AND
2359
                    group_id = $groupId AND
2360
                    survey_code = '$surveyCode'
2361
                ";
2362
        $result = Database::query($sql);
2363
2364
        return Database::num_rows($result);
2365
    }
2366
2367
    /**
2368
     * Send the invitation by mail.
2369
     *
2370
     * @param int invitedUser - the userId (course user) or emailaddress of additional user
2371
     * $param string $invitation_code - the unique invitation code for the URL
2372
     */
2373
    public static function send_invitation_mail(
2374
        $invitedUser,
2375
        $invitation_code,
2376
        $invitation_title,
2377
        $invitation_text
2378
    ) {
2379
        $_user = api_get_user_info();
2380
        $_course = api_get_course_info();
2381
        $sessionId = api_get_session_id();
2382
2383
        // Replacing the **link** part with a valid link for the user
2384
        $link = self::generateFillSurveyLink($invitation_code, $_course, $sessionId);
2385
2386
        $text_link = '<a href="'.$link.'">'.get_lang('ClickHereToAnswerTheSurvey')."</a><br />\r\n<br />\r\n"
2387
            .get_lang('OrCopyPasteTheFollowingUrl')." <br /> \r\n <br /> \r\n ".$link;
2388
2389
        $replace_count = 0;
2390
        $full_invitation_text = api_str_ireplace('**link**', $text_link, $invitation_text, $replace_count);
2391
        if ($replace_count < 1) {
2392
            $full_invitation_text = $full_invitation_text."<br />\r\n<br />\r\n".$text_link;
2393
        }
2394
2395
        // Sending the mail
2396
        $sender_name = api_get_person_name($_user['firstName'], $_user['lastName'], null, PERSON_NAME_EMAIL_ADDRESS);
2397
        $sender_email = $_user['mail'];
2398
        $sender_user_id = api_get_user_id();
2399
2400
        $replyto = [];
2401
        if (api_get_setting('survey_email_sender_noreply') == 'noreply') {
2402
            $noreply = api_get_setting('noreply_email_address');
2403
            if (!empty($noreply)) {
2404
                $replyto['Reply-to'] = $noreply;
2405
                $sender_name = $noreply;
2406
                $sender_email = $noreply;
2407
                $sender_user_id = null;
2408
            }
2409
        }
2410
2411
        // Optionally: finding the e-mail of the course user
2412
        if (is_numeric($invitedUser)) {
2413
            MessageManager::send_message(
2414
                $invitedUser,
2415
                $invitation_title,
2416
                $full_invitation_text,
2417
                [],
2418
                [],
2419
                null,
2420
                null,
2421
                null,
2422
                null,
2423
                $sender_user_id,
2424
                true
2425
            );
2426
        } else {
2427
            @api_mail_html(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for api_mail_html(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

2427
            /** @scrutinizer ignore-unhandled */ @api_mail_html(

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

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