Completed
Push — master ( 27e209...a08afa )
by Julito
186:04 queued 150:53
created

SurveyUtil   F

Complexity

Total Complexity 470

Size/Duplication

Total Lines 3639
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3639
rs 0.6314
c 0
b 0
f 0
wmc 470

48 Methods

Rating   Name   Duplication   Size   Complexity  
F display_user_report() 0 171 21
F display_complete_report() 0 236 48
F handle_reporting_actions() 0 34 11
F display_question_report() 0 223 34
B store_answer() 0 44 4
B delete_user_report() 0 35 4
A remove_answer() 0 12 1
C check_first_last_question() 0 29 8
C check_parameters() 0 61 15
C display_complete_report_row() 0 72 14
B isSurveyAnsweredFlagged() 0 22 5
A invitationExists() 0 18 1
F make_field_list() 0 143 27
B display_survey_list_for_coach() 0 42 3
F saveInvitations() 0 117 23
A get_answers_of_question_by_user() 0 22 3
F display_comparative_report() 0 236 32
C export_complete_report_row() 0 73 18
B drawChart() 0 59 7
A get_number_of_survey_invitations() 0 17 1
D display_question_report_score() 0 97 10
B save_invitation() 0 20 6
C comparative_check() 0 35 8
A checkIfSurveyHasAnswers() 0 19 3
D get_survey_data() 0 120 9
A show_link_available() 0 51 3
A modify_filter_for_coach() 0 13 1
B send_invitation_mail() 0 62 5
B displaySurveyListForDrh() 0 35 2
F export_complete_report_xls() 0 214 31
A checkHideEditionToolsByCode() 0 17 4
A get_number_of_surveys() 0 17 2
C get_survey_data_for_coach() 0 70 7
B get_survey_invitations_data() 0 26 2
A save_invite_mail() 0 18 2
C getSurveyList() 0 113 11
C get_invited_users() 0 63 12
A anonymous_filter() 0 6 2
B display_survey_list() 0 43 4
A display_survey_search_form() 0 11 1
F export_complete_report() 0 172 24
A flagSurveyAsAnswered() 0 10 2
A get_number_of_surveys_for_coach() 0 5 1
A get_invitations() 0 19 2
B survey_search_restriction() 0 18 6
C modify_filter() 0 75 11
C export_complete_report_row_xls() 0 66 16
B update_count_invited() 0 34 3

How to fix   Complexity   

Complex Class

Complex classes like SurveyUtil often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SurveyUtil, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CSurvey;
5
use ChamiloSession as Session;
6
7
/**
8
 * This class offers a series of general utility functions for survey querying and display
9
 * @package chamilo.survey
10
 */
11
class SurveyUtil
12
{
13
    /**
14
     * Checks whether the given survey has a pagebreak question as the first
15
     * or the last question.
16
     * If so, break the current process, displaying an error message
17
     * @param    integer $survey_id Survey ID (database ID)
18
     * @param    boolean $continue Optional. Whether to continue the current
19
     * process or exit when breaking condition found. Defaults to true (do not break).
20
     * @return    void
21
     */
22
    public static function check_first_last_question($survey_id, $continue = true)
23
    {
24
        // Table definitions
25
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
26
        $course_id = api_get_course_int_id();
27
28
        // Getting the information of the question
29
        $sql = "SELECT * FROM $tbl_survey_question
30
                WHERE c_id = $course_id AND survey_id='".Database::escape_string($survey_id)."'
31
                ORDER BY sort ASC";
32
        $result = Database::query($sql);
33
        $total = Database::num_rows($result);
34
        $counter = 1;
35
        $error = false;
36
        while ($row = Database::fetch_array($result, 'ASSOC')) {
37
            if ($counter == 1 && $row['type'] == 'pagebreak') {
38
                echo Display::return_message(get_lang('PagebreakNotFirst'), 'error', false);
39
                $error = true;
40
            }
41
            if ($counter == $total && $row['type'] == 'pagebreak') {
42
                echo Display::return_message(get_lang('PagebreakNotLast'), 'error', false);
43
                $error = true;
44
            }
45
            $counter++;
46
        }
47
48
        if (!$continue && $error) {
49
            Display::display_footer();
50
            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...
51
        }
52
    }
53
54
    /**
55
     * This function removes an (or multiple) answer(s) of a user on a question of a survey
56
     *
57
     * @param mixed   The user id or email of the person who fills the survey
58
     * @param integer The survey id
59
     * @param integer The question id
60
     * @param integer The option id
61
     *
62
     * @author Patrick Cool <[email protected]>, Ghent University
63
     * @version January 2007
64
     */
65
    public static function remove_answer($user, $survey_id, $question_id, $course_id)
66
    {
67
        $course_id = intval($course_id);
68
        // table definition
69
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
70
        $sql = "DELETE FROM $table
71
				WHERE
72
				    c_id = $course_id AND
73
                    user = '".Database::escape_string($user)."' AND
74
                    survey_id = '".intval($survey_id)."' AND
75
                    question_id = '".intval($question_id)."'";
76
        Database::query($sql);
77
    }
78
79
    /**
80
     * This function stores an answer of a user on a question of a survey
81
     *
82
     * @param mixed   The user id or email of the person who fills the survey
83
     * @param integer Survey id
84
     * @param integer Question id
85
     * @param integer Option id
86
     * @param string  Option value
87
     * @param array $survey_data Survey data settings
88
     * @return bool False if insufficient data, true otherwise
89
     *
90
     * @author Patrick Cool <[email protected]>, Ghent University
91
     * @version January 2007
92
     */
93
    public static function store_answer(
94
        $user,
95
        $survey_id,
96
        $question_id,
97
        $option_id,
98
        $option_value,
99
        $survey_data
100
    ) {
101
        // If the question_id is empty, don't store an answer
102
        if (empty($question_id)) {
103
            return false;
104
        }
105
        // Table definition
106
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
107
108
        // Make the survey anonymous
109
        if ($survey_data['anonymous'] == 1) {
110
            $surveyUser = Session::read('surveyuser');
111
            if (empty($surveyUser)) {
112
                $user = md5($user.time());
113
                Session::write('surveyuser', $user);
114
            } else {
115
                $user = Session::read('surveyuser');
116
            }
117
        }
118
119
        $course_id = $survey_data['c_id'];
120
121
        $sql = "INSERT INTO $table_survey_answer (c_id, user, survey_id, question_id, option_id, value) VALUES (
122
				$course_id,
123
				'".Database::escape_string($user)."',
124
				'".Database::escape_string($survey_id)."',
125
				'".Database::escape_string($question_id)."',
126
				'".Database::escape_string($option_id)."',
127
				'".Database::escape_string($option_value)."'
128
				)";
129
        Database::query($sql);
130
        $insertId = Database::insert_id();
131
132
        $sql = "UPDATE $table_survey_answer SET answer_id = $insertId 
133
                WHERE iid = $insertId";
134
        Database::query($sql);
135
136
        return true;
137
    }
138
139
    /**
140
     * This function checks the parameters that are used in this page
141
     *
142
     * @return string $people_filled The header, an error and the footer if any parameter fails, else it returns true
143
     * @author Patrick Cool <[email protected]>, Ghent University
144
     * @version February 2007
145
     */
146
    public static function check_parameters($people_filled)
147
    {
148
        $error = false;
149
150
        // Getting the survey data
151
        $survey_data = SurveyManager::get_survey($_GET['survey_id']);
152
153
        // $_GET['survey_id'] has to be numeric
154
        if (!is_numeric($_GET['survey_id'])) {
155
            $error = get_lang('IllegalSurveyId');
156
        }
157
158
        // $_GET['action']
159
        $allowed_actions = [
160
            'overview',
161
            'questionreport',
162
            'userreport',
163
            'comparativereport',
164
            'completereport',
165
            'deleteuserreport'
166
        ];
167
        if (isset($_GET['action']) && !in_array($_GET['action'], $allowed_actions)) {
168
            $error = get_lang('ActionNotAllowed');
169
        }
170
171
        // User report
172
        if (isset($_GET['action']) && $_GET['action'] == 'userreport') {
173
            if ($survey_data['anonymous'] == 0) {
174
                foreach ($people_filled as $key => & $value) {
175
                    $people_filled_userids[] = $value['invited_user'];
176
                }
177
            } else {
178
                $people_filled_userids = $people_filled;
179
            }
180
181
            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...
182
                $error = get_lang('UnknowUser');
183
            }
184
        }
185
186
        // Question report
187
        if (isset($_GET['action']) && $_GET['action'] == 'questionreport') {
188
            if (isset($_GET['question']) && !is_numeric($_GET['question'])) {
189
                $error = get_lang('UnknowQuestion');
190
            }
191
        }
192
193
        if ($error) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $error of type false|string is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
194
            $tool_name = get_lang('Reporting');
195
            Display::addFlash(
196
                Display::return_message(
197
                    get_lang('Error').': '.$error,
198
                    'error',
199
                    false
200
                )
201
            );
202
            Display::display_header($tool_name);
203
            Display::display_footer();
204
            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...
205
        } else {
206
            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...
207
        }
208
    }
209
210
    /**
211
     * This function deals with the action handling
212
     * @param array $survey_data
213
     * @param array $people_filled
214
     * @return void
215
     * @author Patrick Cool <[email protected]>, Ghent University
216
     * @version February 2007
217
     */
218
    public static function handle_reporting_actions($survey_data, $people_filled)
219
    {
220
        $action = isset($_GET['action']) ? $_GET['action'] : null;
221
222
        // Getting the number of question
223
        $temp_questions_data = SurveyManager::get_questions($_GET['survey_id']);
224
225
        // Sorting like they should be displayed and removing the non-answer question types (comment and pagebreak)
226
        $my_temp_questions_data = $temp_questions_data == null ? [] : $temp_questions_data;
227
        $questions_data = [];
228
229
        foreach ($my_temp_questions_data as $key => & $value) {
230
            if ($value['type'] != 'comment' && $value['type'] != 'pagebreak') {
231
                $questions_data[$value['sort']] = $value;
232
            }
233
        }
234
235
        // Counting the number of questions that are relevant for the reporting
236
        $survey_data['number_of_questions'] = count($questions_data);
237
238
        if ($action == 'questionreport') {
239
            self::display_question_report($survey_data);
240
        }
241
        if ($action == 'userreport') {
242
            self::display_user_report($people_filled, $survey_data);
243
        }
244
        if ($action == 'comparativereport') {
245
            self::display_comparative_report();
246
        }
247
        if ($action == 'completereport') {
248
            self::display_complete_report($survey_data);
249
        }
250
        if ($action == 'deleteuserreport') {
251
            self::delete_user_report($_GET['survey_id'], $_GET['user']);
252
        }
253
    }
254
255
    /**
256
     * This function deletes the report of an user who wants to retake the survey
257
     * @param integer $survey_id
258
     * @param integer $user_id
259
     * @return void
260
     * @author Christian Fasanando Flores <[email protected]>
261
     * @version November 2008
262
     */
263
    public static function delete_user_report($survey_id, $user_id)
264
    {
265
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
266
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
267
        $table_survey = Database::get_course_table(TABLE_SURVEY);
268
269
        $course_id = api_get_course_int_id();
270
        $survey_id = (int) $survey_id;
271
        $user_id = Database::escape_string($user_id);
272
273
        if (!empty($survey_id) && !empty($user_id)) {
274
            // delete data from survey_answer by user_id and survey_id
275
            $sql = "DELETE FROM $table_survey_answer
276
			        WHERE c_id = $course_id AND survey_id = '".$survey_id."' AND user = '".$user_id."'";
277
            Database::query($sql);
278
            // update field answered from survey_invitation by user_id and survey_id
279
            $sql = "UPDATE $table_survey_invitation SET answered = '0'
280
			        WHERE
281
			            c_id = $course_id AND
282
			            survey_code = (
283
                            SELECT code FROM $table_survey
284
                            WHERE
285
                                c_id = $course_id AND
286
                                survey_id = '".$survey_id."'
287
                        ) AND
288
			            user = '".$user_id."'";
289
            $result = Database::query($sql);
290
        }
291
292
        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...
293
            $message = get_lang('SurveyUserAnswersHaveBeenRemovedSuccessfully').'<br />
294
					<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=userreport&survey_id='
295
                .$survey_id.'">'.
296
                get_lang('GoBack').'</a>';
297
            echo Display::return_message($message, 'confirmation', false);
298
        }
299
    }
300
301
    /**
302
     * This function displays the user report which is basically nothing more
303
     * than a one-page display of all the questions
304
     * of the survey that is filled with the answers of the person who filled the survey.
305
     *
306
     * @return string html code of the one-page survey with the answers of the selected user
307
     * @author Patrick Cool <[email protected]>, Ghent University
308
     * @version February 2007 - Updated March 2008
309
     */
310
    public static function display_user_report($people_filled, $survey_data)
311
    {
312
        // Database table definitions
313
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
314
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
315
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
316
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
317
318
        // Actions bar
319
        echo '<div class="actions">';
320
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'.
321
            Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('ReportingOverview'), '', ICON_SIZE_MEDIUM)
322
            .'</a>';
323
        if (isset($_GET['user'])) {
324
            if (api_is_allowed_to_edit()) {
325
                // The delete link
326
                echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=deleteuserreport&survey_id='
327
                    .$surveyId.'&'.api_get_cidreq().'&user='.Security::remove_XSS($_GET['user']).'" >'.
328
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_MEDIUM).'</a>';
329
            }
330
331
            // Export the user report
332
            echo '<a href="javascript: void(0);" onclick="document.form1a.submit();">'
333
                .Display::return_icon('export_csv.png', get_lang('ExportAsCSV'), '', ICON_SIZE_MEDIUM).'</a> ';
334
            echo '<a href="javascript: void(0);" onclick="document.form1b.submit();">'
335
                .Display::return_icon('export_excel.png', get_lang('ExportAsXLS'), '', ICON_SIZE_MEDIUM).'</a> ';
336
            echo '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='
337
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
338
                .Security::remove_XSS($_GET['user']).'">';
339
            echo '<input type="hidden" name="export_report" value="export_report">';
340
            echo '<input type="hidden" name="export_format" value="csv">';
341
            echo '</form>';
342
            echo '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='
343
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'&user_id='
344
                .Security::remove_XSS($_GET['user']).'">';
345
            echo '<input type="hidden" name="export_report" value="export_report">';
346
            echo '<input type="hidden" name="export_format" value="xls">';
347
            echo '</form>';
348
            echo '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='
349
                .Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
350
        }
351
        echo '</div>';
352
353
        // Step 1: selection of the user
354
        echo "<script>
355
        function jumpMenu(targ,selObj,restore) {
356
            eval(targ+\".location='\"+selObj.options[selObj.selectedIndex].value+\"'\");
357
            if (restore) selObj.selectedIndex=0;
358
        }
359
		</script>";
360
        echo get_lang('SelectUserWhoFilledSurvey').'<br />';
361
362
        echo '<select name="user" onchange="jumpMenu(\'parent\',this,0)">';
363
        echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
364
            .Security::remove_XSS($_GET['action']).'&survey_id='.intval($_GET['survey_id']).'">'
365
            .get_lang('SelectUser').'</option>';
366
367
        foreach ($people_filled as $key => & $person) {
368
            if ($survey_data['anonymous'] == 0) {
369
                $name = $person['user_info']['complete_name_with_username'];
370
                $id = $person['user_id'];
371
                if ($id == '') {
372
                    $id = $person['invited_user'];
373
                    $name = $person['invited_user'];
374
                }
375
            } else {
376
                $name = get_lang('Anonymous').' '.($key + 1);
377
                $id = $person;
378
            }
379
            echo '<option value="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='
380
                .Security::remove_XSS($_GET['action']).'&survey_id='.intval($_GET['survey_id']).'&user='
381
                .Security::remove_XSS($id).'" ';
382
            if (isset($_GET['user']) && $_GET['user'] == $id) {
383
                echo 'selected="selected"';
384
            }
385
            echo '>'.$name.'</option>';
386
        }
387
        echo '</select>';
388
389
        $course_id = api_get_course_int_id();
390
        // Step 2: displaying the survey and the answer of the selected users
391
        if (isset($_GET['user'])) {
392
            echo Display::return_message(
393
                get_lang('AllQuestionsOnOnePage'),
394
                'normal',
395
                false
396
            );
397
398
            // Getting all the questions and options
399
            $sql = "SELECT
400
			            survey_question.question_id,
401
			            survey_question.survey_id,
402
			            survey_question.survey_question,
403
			            survey_question.display,
404
			            survey_question.max_value,
405
			            survey_question.sort,
406
			            survey_question.type,
407
                        survey_question_option.question_option_id,
408
                        survey_question_option.option_text,
409
                        survey_question_option.sort as option_sort
410
					FROM $table_survey_question survey_question
411
					LEFT JOIN $table_survey_question_option survey_question_option
412
					ON
413
					    survey_question.question_id = survey_question_option.question_id AND
414
					    survey_question_option.c_id = $course_id
415
					WHERE
416
					    survey_question.survey_id = '".intval($_GET['survey_id'])."' AND
417
                        survey_question.c_id = $course_id
418
					ORDER BY survey_question.sort, survey_question_option.sort ASC";
419
            $result = Database::query($sql);
420
            while ($row = Database::fetch_array($result, 'ASSOC')) {
421
                if ($row['type'] != 'pagebreak') {
422
                    $questions[$row['sort']]['question_id'] = $row['question_id'];
423
                    $questions[$row['sort']]['survey_id'] = $row['survey_id'];
424
                    $questions[$row['sort']]['survey_question'] = $row['survey_question'];
425
                    $questions[$row['sort']]['display'] = $row['display'];
426
                    $questions[$row['sort']]['type'] = $row['type'];
427
                    $questions[$row['sort']]['maximum_score'] = $row['max_value'];
428
                    $questions[$row['sort']]['options'][$row['question_option_id']] = $row['option_text'];
429
                }
430
            }
431
432
            // Getting all the answers of the user
433
            $sql = "SELECT * FROM $table_survey_answer
434
			        WHERE
435
                        c_id = $course_id AND
436
                        survey_id = '".intval($_GET['survey_id'])."' AND
437
                        user = '".Database::escape_string($_GET['user'])."'";
438
            $result = Database::query($sql);
439
            while ($row = Database::fetch_array($result, 'ASSOC')) {
440
                $answers[$row['question_id']][] = $row['option_id'];
441
                $all_answers[$row['question_id']][] = $row;
442
            }
443
444
            // Displaying all the questions
445
446
            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...
447
                // If the question type is a scoring then we have to format the answers differently
448
                switch ($question['type']) {
449
                    case 'score':
450
                        $finalAnswer = [];
451
                        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...
452
                            foreach ($all_answers[$question['question_id']] as $key => & $answer_array) {
453
                                $finalAnswer[$answer_array['option_id']] = $answer_array['value'];
454
                            }
455
                        }
456
                        break;
457
                    case 'multipleresponse':
458
                        $finalAnswer = isset($answers[$question['question_id']])
459
                            ? $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...
460
                            : '';
461
                        break;
462
                    default:
463
                        $finalAnswer = '';
464
                        if (isset($all_answers[$question['question_id']])) {
465
                            $finalAnswer = $all_answers[$question['question_id']][0]['option_id'];
466
                        }
467
                        break;
468
                }
469
470
                $ch_type = 'ch_'.$question['type'];
471
                /** @var survey_question $display */
472
                $display = new $ch_type;
473
474
                $url = api_get_self();
475
                $form = new FormValidator('question', 'post', $url);
476
                $form->addHtml('<div class="survey_question_wrapper"><div class="survey_question">');
477
                $form->addHtml($question['survey_question']);
478
                $display->render($form, $question, $finalAnswer);
0 ignored issues
show
Bug introduced by
It seems like $finalAnswer can also be of type string; however, parameter $answers of survey_question::render() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

478
                $display->render($form, $question, /** @scrutinizer ignore-type */ $finalAnswer);
Loading history...
479
                $form->addHtml('</div></div>');
480
                $form->display();
481
            }
482
        }
483
    }
484
485
    /**
486
     * This function displays the report by question.
487
     *
488
     * It displays a table with all the options of the question and the number of users who have answered positively on
489
     * the option. The number of users who answered positive on a given option is expressed in an absolute number, in a
490
     * percentage of the total and graphically using bars By clicking on the absolute number you get a list with the
491
     * persons who have answered this. You can then click on the name of the person and you will then go to the report
492
     * by user where you see all the answers of that user.
493
     *
494
     * @param    array    All the survey data
495
     * @return   string    html code that displays the report by question
496
     * @todo allow switching between horizontal and vertical.
497
     * @todo multiple response: percentage are probably not OK
498
     * @todo the question and option text have to be shortened and should expand when the user clicks on it.
499
     * @todo the pagebreak and comment question types should not be shown => removed from $survey_data before
500
     * @author Patrick Cool <[email protected]>, Ghent University
501
     * @version February 2007 - Updated March 2008
502
     */
503
    public static function display_question_report($survey_data)
504
    {
505
        $singlePage = isset($_GET['single_page']) ? intval($_GET['single_page']) : 0;
506
        $course_id = api_get_course_int_id();
507
        // Database table definitions
508
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
509
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
510
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
511
512
        // Determining the offset of the sql statement (the n-th question of the survey)
513
        $offset = !isset($_GET['question']) ? 0 : intval($_GET['question']);
514
        $currentQuestion = isset($_GET['question']) ? intval($_GET['question']) : 0;
515
        $questions = [];
516
        $surveyId = intval($_GET['survey_id']);
517
        $action = Security::remove_XSS($_GET['action']);
518
519
        echo '<div class="actions">';
520
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'.
521
            Display::return_icon(
522
                'back.png',
523
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
524
                '',
525
                ICON_SIZE_MEDIUM
526
            ).'</a>';
527
        echo '</div>';
528
529
        if ($survey_data['number_of_questions'] > 0) {
530
            $limitStatement = null;
531
            if (!$singlePage) {
532
                echo '<div id="question_report_questionnumbers" class="pagination">';
533
                if ($currentQuestion != 0) {
534
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
535
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset - 1).'">'
536
                        .get_lang('PreviousQuestion').'</a></li>';
537
                }
538
539
                for ($i = 1; $i <= $survey_data['number_of_questions']; $i++) {
540
                    if ($offset != $i - 1) {
541
                        echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
542
                            .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($i - 1).'">'.$i.'</a></li>';
543
                    } else {
544
                        echo '<li class="disabled"s><a href="#">'.$i.'</a></li>';
545
                    }
546
                }
547
                if ($currentQuestion < ($survey_data['number_of_questions'] - 1)) {
548
                    echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action.'&'
549
                        .api_get_cidreq().'&survey_id='.$surveyId.'&question='.($offset + 1).'">'
550
                        .get_lang('NextQuestion').'</li></a>';
551
                }
552
                echo '</ul>';
553
                echo '</div>';
554
                $limitStatement = " LIMIT $offset, 1";
555
            }
556
557
            // Getting the question information
558
            $sql = "SELECT * FROM $table_survey_question
559
			        WHERE
560
			            c_id = $course_id AND
561
                        survey_id='".intval($_GET['survey_id'])."' AND
562
                        type <>'pagebreak' AND 
563
                        type <>'comment'
564
                    ORDER BY sort ASC
565
                    $limitStatement";
566
            $result = Database::query($sql);
567
            while ($row = Database::fetch_array($result)) {
568
                $questions[$row['question_id']] = $row;
569
            }
570
        }
571
572
        foreach ($questions as $question) {
573
            $chartData = [];
574
            $options = [];
575
            echo '<div class="title-question">';
576
            echo strip_tags(isset($question['survey_question']) ? $question['survey_question'] : null);
577
            echo '</div>';
578
579
            if ($question['type'] == 'score') {
580
                /** @todo This function should return the options as this is needed further in the code */
581
                $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...
582
            } elseif ($question['type'] == 'open') {
583
                /** @todo Also get the user who has answered this */
584
                $sql = "SELECT * FROM $table_survey_answer
585
                        WHERE
586
                            c_id = $course_id AND
587
                            survey_id='".intval($_GET['survey_id'])."' AND
588
                            question_id = '".intval($question['question_id'])."'";
589
                $result = Database::query($sql);
590
                while ($row = Database::fetch_array($result, 'ASSOC')) {
591
                    echo $row['option_id'].'<hr noshade="noshade" size="1" />';
592
                }
593
            } else {
594
                // Getting the options ORDER BY sort ASC
595
                $sql = "SELECT * FROM $table_survey_question_option
596
                        WHERE
597
                            c_id = $course_id AND
598
                            survey_id='".intval($_GET['survey_id'])."'
599
                            AND question_id = '".intval($question['question_id'])."'
600
                        ORDER BY sort ASC";
601
                $result = Database::query($sql);
602
                while ($row = Database::fetch_array($result, 'ASSOC')) {
603
                    $options[$row['question_option_id']] = $row;
604
                }
605
                // Getting the answers
606
                $sql = "SELECT *, count(answer_id) as total FROM $table_survey_answer
607
                        WHERE
608
                            c_id = $course_id AND
609
                            survey_id='".intval($_GET['survey_id'])."'
610
                            AND question_id = '".intval($question['question_id'])."'
611
                        GROUP BY option_id, value";
612
                $result = Database::query($sql);
613
                $number_of_answers = [];
614
                $data = [];
615
                while ($row = Database::fetch_array($result, 'ASSOC')) {
616
                    if (!isset($number_of_answers[$row['question_id']])) {
617
                        $number_of_answers[$row['question_id']] = 0;
618
                    }
619
                    $number_of_answers[$row['question_id']] += $row['total'];
620
                    $data[$row['option_id']] = $row;
621
                }
622
623
                foreach ($options as $option) {
624
                    $optionText = strip_tags($option['option_text']);
625
                    $optionText = html_entity_decode($optionText);
626
                    $votes = isset($data[$option['question_option_id']]['total']) ?
627
                        $data[$option['question_option_id']]['total'] : '0';
628
                    array_push($chartData, ['option' => $optionText, 'votes' => $votes]);
629
                }
630
                $chartContainerId = 'chartContainer'.$question['question_id'];
631
                echo '<div id="'.$chartContainerId.'" class="col-md-12">';
632
                echo self::drawChart($chartData, false, $chartContainerId);
633
634
                // displaying the table: headers
635
                echo '<table class="display-survey table">';
636
                echo '	<tr>';
637
                echo '		<th>&nbsp;</th>';
638
                echo '		<th>'.get_lang('AbsoluteTotal').'</th>';
639
                echo '		<th>'.get_lang('Percentage').'</th>';
640
                echo '		<th>'.get_lang('VisualRepresentation').'</th>';
641
                echo '	<tr>';
642
643
                // Displaying the table: the content
644
                if (is_array($options)) {
645
                    foreach ($options as $key => & $value) {
646
                        $absolute_number = null;
647
                        if (isset($data[$value['question_option_id']])) {
648
                            $absolute_number = $data[$value['question_option_id']]['total'];
649
                        }
650
                        if ($question['type'] == 'percentage' && empty($absolute_number)) {
651
                            continue;
652
                        }
653
                        $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...
654
                            ? $number_of_answers[$option['question_id']]
655
                            : 0;
656
                        if ($number_of_answers[$option['question_id']] == 0) {
657
                            $answers_number = 0;
658
                        } else {
659
                            $answers_number = $absolute_number / $number_of_answers[$option['question_id']] * 100;
660
                        }
661
                        echo '	<tr>';
662
                        echo '		<td class="center">'.$value['option_text'].'</td>';
663
                        echo '		<td class="center">';
664
                        if ($absolute_number != 0) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $absolute_number of type null|mixed to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
665
                            echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action
666
                                .'&survey_id='.$surveyId.'&question='.$offset.'&viewoption='
667
                                .$value['question_option_id'].'">'.$absolute_number.'</a>';
668
                        } else {
669
                            echo '0';
670
                        }
671
672
                        echo '      </td>';
673
                        echo '		<td class="center">'.round($answers_number, 2).' %</td>';
674
                        echo '		<td class="center">';
675
                        $size = $answers_number * 2;
676
                        if ($size > 0) {
677
                            echo '<div style="border:1px solid #264269; background-color:#aecaf4; height:10px; width:'
678
                                .$size.'px">&nbsp;</div>';
679
                        } else {
680
                            echo '<div style="text-align: left;">'.get_lang("NoDataAvailable").'</div>';
681
                        }
682
                        echo ' </td>';
683
                        echo ' </tr>';
684
                    }
685
                }
686
                // displaying the table: footer (totals)
687
                echo '	<tr>';
688
                echo '		<td class="total"><b>'.get_lang('Total').'</b></td>';
689
                echo '		<td class="total"><b>'
690
                    .($number_of_answers[$option['question_id']] == 0
691
                        ? '0'
692
                        : $number_of_answers[$option['question_id']])
693
                    .'</b></td>';
694
                echo '		<td class="total">&nbsp;</td>';
695
                echo '		<td class="total">&nbsp;</td>';
696
                echo '	</tr>';
697
                echo '</table>';
698
                echo '</div>';
699
            }
700
        }
701
        if (isset($_GET['viewoption'])) {
702
            echo '<div class="answered-people">';
703
            echo '<h4>'.get_lang('PeopleWhoAnswered').': '
704
                .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 572. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
705
706
            if (is_numeric($_GET['value'])) {
707
                $sql_restriction = "AND value='".Database::escape_string($_GET['value'])."'";
708
            }
709
710
            $sql = "SELECT user FROM $table_survey_answer
711
                    WHERE
712
                        c_id = $course_id AND
713
                        option_id = '".Database::escape_string($_GET['viewoption'])."'
714
                        $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...
715
            $result = Database::query($sql);
716
            echo '<ul>';
717
            while ($row = Database::fetch_array($result, 'ASSOC')) {
718
                $user_info = api_get_user_info($row['user']);
719
                echo '<li><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action=userreport&survey_id='
720
                    .$surveyId.'&user='.$row['user'].'">'
721
                    .$user_info['complete_name_with_username']
722
                    .'</a></li>';
723
            }
724
            echo '</ul>';
725
            echo '</div>';
726
        }
727
    }
728
729
    /**
730
     * Display score data about a survey question
731
     * @param    array    Question info
732
     * @param    integer    The offset of results shown
733
     * @return   void    (direct output)
734
     */
735
    public static function display_question_report_score($survey_data, $question, $offset)
736
    {
737
        // Database table definitions
738
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
739
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
740
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
741
        $course_id = api_get_course_int_id();
742
743
        // Getting the options
744
        $sql = "SELECT * FROM $table_survey_question_option
745
                WHERE
746
                    c_id = $course_id AND
747
                    survey_id='".intval($_GET['survey_id'])."' AND
748
                    question_id = '".intval($question['question_id'])."'
749
                ORDER BY sort ASC";
750
        $result = Database::query($sql);
751
        while ($row = Database::fetch_array($result)) {
752
            $options[$row['question_option_id']] = $row;
753
        }
754
755
        // Getting the answers
756
        $sql = "SELECT *, count(answer_id) as total 
757
                FROM $table_survey_answer
758
                WHERE
759
                   c_id = $course_id AND
760
                   survey_id='".intval($_GET['survey_id'])."' AND
761
                   question_id = '".Database::escape_string($question['question_id'])."'
762
                GROUP BY option_id, value";
763
        $result = Database::query($sql);
764
        $number_of_answers = 0;
765
        while ($row = Database::fetch_array($result)) {
766
            $number_of_answers += $row['total'];
767
            $data[$row['option_id']][$row['value']] = $row;
768
        }
769
770
        $chartData = [];
771
        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...
772
            $optionText = strip_tags($option['option_text']);
773
            $optionText = html_entity_decode($optionText);
774
            for ($i = 1; $i <= $question['max_value']; $i++) {
775
                $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...
776
                if (empty($votes)) {
777
                    $votes = '0';
778
                }
779
                array_push(
780
                    $chartData,
781
                    [
782
                        'serie' => $optionText,
783
                        'option' => $i,
784
                        'votes' => $votes
785
                    ]
786
                );
787
            }
788
        }
789
        echo '<div id="chartContainer" class="col-md-12">';
790
        echo self::drawChart($chartData, true);
791
        echo '</div>';
792
793
        // Displaying the table: headers
794
        echo '<table class="data_table">';
795
        echo '	<tr>';
796
        echo '		<th>&nbsp;</th>';
797
        echo '		<th>'.get_lang('Score').'</th>';
798
        echo '		<th>'.get_lang('AbsoluteTotal').'</th>';
799
        echo '		<th>'.get_lang('Percentage').'</th>';
800
        echo '		<th>'.get_lang('VisualRepresentation').'</th>';
801
        echo '	<tr>';
802
        // Displaying the table: the content
803
        foreach ($options as $key => & $value) {
804
            for ($i = 1; $i <= $question['max_value']; $i++) {
805
                $absolute_number = $data[$value['question_option_id']][$i]['total'];
806
                echo '	<tr>';
807
                echo '		<td>'.$value['option_text'].'</td>';
808
                echo '		<td>'.$i.'</td>';
809
                echo '		<td><a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?action='.$action
810
                    .'&survey_id='.intval($_GET['survey_id']).'&question='.Security::remove_XSS($offset)
811
                    .'&viewoption='.$value['question_option_id'].'&value='.$i.'">'.$absolute_number.'</a></td>';
812
                echo '		<td>'.round($absolute_number / $number_of_answers * 100, 2).' %</td>';
813
                echo '		<td>';
814
                $size = ($absolute_number / $number_of_answers * 100 * 2);
815
                if ($size > 0) {
816
                    echo '<div style="border:1px solid #264269; background-color:#aecaf4; height:10px; width:'.$size.'px">&nbsp;</div>';
817
                }
818
                echo '		</td>';
819
                echo '	</tr>';
820
            }
821
        }
822
        // Displaying the table: footer (totals)
823
        echo '	<tr>';
824
        echo '		<td style="border-top:1px solid black"><b>'.get_lang('Total').'</b></td>';
825
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
826
        echo '		<td style="border-top:1px solid black"><b>'.$number_of_answers.'</b></td>';
827
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
828
        echo '		<td style="border-top:1px solid black">&nbsp;</td>';
829
        echo '	</tr>';
830
831
        echo '</table>';
832
    }
833
834
    /**
835
     * This functions displays the complete reporting
836
     * @return string    HTML code
837
     * @todo open questions are not in the complete report yet.
838
     * @author Patrick Cool <[email protected]>, Ghent University
839
     * @version February 2007
840
     */
841
    public static function display_complete_report($survey_data)
842
    {
843
        // Database table definitions
844
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
845
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
846
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
847
848
        $surveyId = isset($_GET['survey_id']) ? intval($_GET['survey_id']) : 0;
849
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
850
851
        // Actions bar
852
        echo '<div class="actions">';
853
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq().'">'
854
            .Display::return_icon(
855
                'back.png',
856
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
857
                [],
858
                ICON_SIZE_MEDIUM
859
            )
860
            .'</a>';
861
        echo '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1a.submit();">'
862
            .Display::return_icon('export_csv.png', get_lang('ExportAsCSV'), '', ICON_SIZE_MEDIUM).'</a>';
863
        echo '<a class="survey_export_link" href="javascript: void(0);" onclick="document.form1b.submit();">'
864
            .Display::return_icon('export_excel.png', get_lang('ExportAsXLS'), '', ICON_SIZE_MEDIUM).'</a>';
865
        echo '</div>';
866
867
        // The form
868
        echo '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
869
            .$surveyId.'&'.api_get_cidreq().'">';
870
        echo '<input type="hidden" name="export_report" value="export_report">';
871
        echo '<input type="hidden" name="export_format" value="csv">';
872
        echo '</form>';
873
        echo '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
874
            .$surveyId.'&'.api_get_cidreq().'">';
875
        echo '<input type="hidden" name="export_report" value="export_report">';
876
        echo '<input type="hidden" name="export_format" value="xls">';
877
        echo '</form>';
878
879
        echo '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='
880
            .$surveyId.'&'.api_get_cidreq().'">';
881
882
        // The table
883
        echo '<br /><table class="data_table" border="1">';
884
        // Getting the number of options per question
885
        echo '	<tr>';
886
        echo '		<th>';
887
        if ((isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
888
            (isset($_POST['export_report']) && $_POST['export_report'])
889
        ) {
890
            echo '<button class="cancel" type="submit" name="reset_question_filter" value="'
891
                .get_lang('ResetQuestionFilter').'">'.get_lang('ResetQuestionFilter').'</button>';
892
        }
893
        echo '<button class="save" type="submit" name="submit_question_filter" value="'.get_lang('SubmitQuestionFilter')
894
            .'">'.get_lang('SubmitQuestionFilter').'</button>';
895
        echo '</th>';
896
897
        $display_extra_user_fields = false;
898
        if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
899
                isset($_POST['export_report']) && $_POST['export_report']) ||
900
            !empty($_POST['fields_filter'])
901
        ) {
902
            // Show user fields section with a big th colspan that spans over all fields
903
            $extra_user_fields = UserManager::get_extra_fields(
904
                0,
905
                0,
906
                5,
907
                'ASC',
908
                false,
909
                true
910
            );
911
            $num = count($extra_user_fields);
912
            if ($num > 0) {
913
                echo '<th '.($num > 0 ? ' colspan="'.$num.'"' : '').'>';
914
                echo '<label><input type="checkbox" name="fields_filter" value="1" checked="checked"/> ';
915
                echo get_lang('UserFields');
916
                echo '</label>';
917
                echo '</th>';
918
                $display_extra_user_fields = true;
919
            }
920
        }
921
922
        $course_id = api_get_course_int_id();
923
        $sql = "SELECT q.question_id, q.type, q.survey_question, count(o.question_option_id) as number_of_options
924
				FROM $table_survey_question q 
925
				LEFT JOIN $table_survey_question_option o
926
				ON q.question_id = o.question_id
927
				WHERE 
928
				    q.survey_id = '".$surveyId."' AND
929
				    q.c_id = $course_id AND
930
				    o.c_id = $course_id
931
				GROUP BY q.question_id
932
				ORDER BY q.sort ASC";
933
        $result = Database::query($sql);
934
        $questions = [];
935
        while ($row = Database::fetch_array($result)) {
936
            // We show the questions if
937
            // 1. there is no question filter and the export button has not been clicked
938
            // 2. there is a quesiton filter but the question is selected for display
939
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
940
                (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))
941
            ) {
942
                // We do not show comment and pagebreak question types
943
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
944
                    echo ' <th';
945
                    // <hub> modified tst to include percentage
946
                    if ($row['number_of_options'] > 0 && $row['type'] != 'percentage') {
947
                        // </hub>
948
                        echo ' colspan="'.$row['number_of_options'].'"';
949
                    }
950
                    echo '>';
951
952
                    echo '<label><input type="checkbox" name="questions_filter[]" value="'.$row['question_id']
953
                        .'" checked="checked"/> ';
954
                    echo $row['survey_question'];
955
                    echo '</label>';
956
                    echo '</th>';
957
                }
958
                // No column at all if it's not a question
959
            }
960
            $questions[$row['question_id']] = $row;
961
        }
962
        echo '	</tr>';
963
        // Getting all the questions and options
964
        echo '	<tr>';
965
        echo '		<th>&nbsp;</th>'; // the user column
966
967
        if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter'] ||
968
                isset($_POST['export_report']) && $_POST['export_report']) || !empty($_POST['fields_filter'])) {
969
            //show the fields names for user fields
970
            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...
971
                echo '<th>'.$field[3].'</th>';
972
            }
973
        }
974
975
        // cells with option (none for open question)
976
        $sql = "SELECT 	
977
                    sq.question_id, sq.survey_id,
978
                    sq.survey_question, sq.display,
979
                    sq.sort, sq.type, sqo.question_option_id,
980
                    sqo.option_text, sqo.sort as option_sort
981
				FROM $table_survey_question sq
982
				LEFT JOIN $table_survey_question_option sqo
983
				ON sq.question_id = sqo.question_id
984
				WHERE
985
				    sq.survey_id = '".$surveyId."' AND
986
                    sq.c_id = $course_id AND
987
                    sqo.c_id = $course_id
988
				ORDER BY sq.sort ASC, sqo.sort ASC";
989
        $result = Database::query($sql);
990
991
        $display_percentage_header = 1;
992
        $possible_answers = [];
993
        // in order to display only once the cell option (and not 100 times)
994
        while ($row = Database::fetch_array($result)) {
995
            // We show the options if
996
            // 1. there is no question filter and the export button has not been clicked
997
            // 2. there is a question filter but the question is selected for display
998
            if (!(isset($_POST['submit_question_filter']) && $_POST['submit_question_filter']) ||
999
                (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))
1000
            ) {
1001
                // <hub> modif 05-05-2010
1002
                // we do not show comment and pagebreak question types
1003
                if ($row['type'] == 'open') {
1004
                    echo '<th>&nbsp;-&nbsp;</th>';
1005
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1006
                    $display_percentage_header = 1;
1007
                } elseif ($row['type'] == 'percentage' && $display_percentage_header) {
1008
                    echo '<th>&nbsp;%&nbsp;</th>';
1009
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1010
                    $display_percentage_header = 0;
1011
                } elseif ($row['type'] == 'percentage') {
1012
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1013
                } elseif ($row['type'] <> 'comment' && $row['type'] <> 'pagebreak' && $row['type'] <> 'percentage') {
1014
                    echo '<th>';
1015
                    echo $row['option_text'];
1016
                    echo '</th>';
1017
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1018
                    $display_percentage_header = 1;
1019
                }
1020
                //no column at all if the question was not a question
1021
                // </hub>
1022
            }
1023
        }
1024
1025
        echo '	</tr>';
1026
1027
        // Getting all the answers of the users
1028
        $old_user = '';
1029
        $answers_of_user = [];
1030
        $sql = "SELECT * FROM $table_survey_answer
1031
                WHERE
1032
                    c_id = $course_id AND
1033
                    survey_id='".$surveyId."'
1034
                ORDER BY answer_id, user ASC";
1035
        $result = Database::query($sql);
1036
        $i = 1;
1037
        while ($row = Database::fetch_array($result)) {
1038
            if ($old_user != $row['user'] && $old_user != '') {
1039
                $userParam = $old_user;
1040
                if ($survey_data['anonymous'] != 0) {
1041
                    $userParam = $i;
1042
                    $i++;
1043
                }
1044
                self::display_complete_report_row(
1045
                    $survey_data,
1046
                    $possible_answers,
1047
                    $answers_of_user,
1048
                    $userParam,
1049
                    $questions,
1050
                    $display_extra_user_fields
1051
                );
1052
                $answers_of_user = [];
1053
            }
1054
            if (isset($questions[$row['question_id']]) && $questions[$row['question_id']]['type'] != 'open') {
1055
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1056
            } else {
1057
                $answers_of_user[$row['question_id']][0] = $row;
1058
            }
1059
            $old_user = $row['user'];
1060
        }
1061
        $userParam = $old_user;
1062
        if ($survey_data['anonymous'] != 0) {
1063
            $userParam = $i;
1064
            $i++;
1065
        }
1066
        self::display_complete_report_row(
1067
            $survey_data,
1068
            $possible_answers,
1069
            $answers_of_user,
1070
            $userParam,
1071
            $questions,
1072
            $display_extra_user_fields
1073
        );
1074
        // This is to display the last user
1075
        echo '</table>';
1076
        echo '</form>';
1077
    }
1078
1079
    /**
1080
     * This function displays a row (= a user and his/her answers) in the table of the complete report.
1081
     *
1082
     * @param array $survey_data
1083
     * @param array    Possible options
1084
     * @param array    User answers
1085
     * @param mixed    User ID or user details string
1086
     * @param boolean  Whether to show extra user fields or not
1087
     * @author Patrick Cool <[email protected]>, Ghent University
1088
     * @version February 2007 - Updated March 2008
1089
     */
1090
    public static function display_complete_report_row(
1091
        $survey_data,
1092
        $possible_options,
1093
        $answers_of_user,
1094
        $user,
1095
        $questions,
1096
        $display_extra_user_fields = false
1097
    ) {
1098
        $user = Security::remove_XSS($user);
1099
        echo '<tr>';
1100
        if ($survey_data['anonymous'] == 0) {
1101
            if (intval($user) !== 0) {
1102
                $userInfo = api_get_user_info($user);
1103
                if (!empty($userInfo)) {
1104
                    $user_displayed = $userInfo['complete_name_with_username'];
1105
                } else {
1106
                    $user_displayed = '-';
1107
                }
1108
                echo '<th>
1109
                    <a href="'.api_get_self().'?action=userreport&survey_id='.intval($_GET['survey_id']).'&user='.$user.'">'
1110
                    .$user_displayed.'</a>
1111
                    </th>'; // the user column
1112
            } else {
1113
                echo '<th>'.$user.'</th>'; // the user column
1114
            }
1115
        } else {
1116
            echo '<th>'.get_lang('Anonymous').' '.$user.'</th>';
1117
        }
1118
1119
        if ($display_extra_user_fields) {
1120
            // Show user fields data, if any, for this user
1121
            $user_fields_values = UserManager::get_extra_user_data(
1122
                intval($user),
1123
                false,
1124
                false,
1125
                false,
1126
                true
1127
            );
1128
            foreach ($user_fields_values as & $value) {
1129
                echo '<td align="center">'.$value.'</td>';
1130
            }
1131
        }
1132
        if (is_array($possible_options)) {
1133
            // <hub> modified to display open answers and percentage
1134
            foreach ($possible_options as $question_id => & $possible_option) {
1135
                if ($questions[$question_id]['type'] == 'open') {
1136
                    echo '<td align="center">';
1137
                    echo $answers_of_user[$question_id]['0']['option_id'];
1138
                    echo '</td>';
1139
                } else {
1140
                    foreach ($possible_option as $option_id => & $value) {
1141
                        if ($questions[$question_id]['type'] == 'percentage') {
1142
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1143
                                echo "<td align='center'>";
1144
                                echo $answers_of_user[$question_id][$option_id]['value'];
1145
                                echo "</td>";
1146
                            }
1147
                        } else {
1148
                            echo '<td align="center">';
1149
                            if (!empty($answers_of_user[$question_id][$option_id])) {
1150
                                if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1151
                                    echo $answers_of_user[$question_id][$option_id]['value'];
1152
                                } else {
1153
                                    echo 'v';
1154
                                }
1155
                            }
1156
                        }
1157
                    }
1158
                }
1159
            }
1160
        }
1161
        echo '</tr>';
1162
    }
1163
1164
    /**
1165
     * Quite similar to display_complete_report(), returns an HTML string
1166
     * that can be used in a csv file
1167
     * @todo consider merging this function with display_complete_report
1168
     * @return    string    The contents of a csv file
1169
     * @author Patrick Cool <[email protected]>, Ghent University
1170
     * @version February 2007
1171
     */
1172
    public static function export_complete_report($survey_data, $user_id = 0)
1173
    {
1174
        // Database table definitions
1175
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1176
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1177
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1178
1179
        // The first column
1180
        $return = ';';
1181
1182
        // Show extra fields blank space (enough for extra fields on next line)
1183
        $extra_user_fields = UserManager::get_extra_fields(
1184
            0,
1185
            0,
1186
            5,
1187
            'ASC',
1188
            false,
1189
            true
1190
        );
1191
1192
        $num = count($extra_user_fields);
1193
        $return .= str_repeat(';', $num);
1194
1195
        $course_id = api_get_course_int_id();
1196
1197
        $sql = "SELECT
1198
                    questions.question_id,
1199
                    questions.type,
1200
                    questions.survey_question,
1201
                    count(options.question_option_id) as number_of_options
1202
				FROM $table_survey_question questions
1203
                LEFT JOIN $table_survey_question_option options
1204
				ON questions.question_id = options.question_id AND options.c_id = $course_id
1205
				WHERE
1206
				    questions.survey_id = '".intval($_GET['survey_id'])."' AND
1207
                    questions.c_id = $course_id
1208
				GROUP BY questions.question_id
1209
				ORDER BY questions.sort ASC";
1210
        $result = Database::query($sql);
1211
        while ($row = Database::fetch_array($result)) {
1212
            // We show the questions if
1213
            // 1. there is no question filter and the export button has not been clicked
1214
            // 2. there is a quesiton filter but the question is selected for display
1215
            if (!(isset($_POST['submit_question_filter'])) ||
1216
                (isset($_POST['submit_question_filter']) &&
1217
                    is_array($_POST['questions_filter']) &&
1218
                    in_array($row['question_id'], $_POST['questions_filter']))
1219
            ) {
1220
                // We do not show comment and pagebreak question types
1221
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
1222
                    if ($row['number_of_options'] == 0 && $row['type'] == 'open') {
1223
                        $return .= str_replace(
1224
                            "\r\n",
1225
                            '  ',
1226
                            api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1227
                        )
1228
                        .';';
1229
                    } else {
1230
                        for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1231
                            $return .= str_replace(
1232
                                "\r\n",
1233
                                '  ',
1234
                                api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES)
1235
                            )
1236
                            .';';
1237
                        }
1238
                    }
1239
                }
1240
            }
1241
        }
1242
        $return .= "\n";
1243
1244
        // Getting all the questions and options
1245
        $return .= ';';
1246
1247
        // Show the fields names for user fields
1248
        if (!empty($extra_user_fields)) {
1249
            foreach ($extra_user_fields as & $field) {
1250
                $return .= '"'
1251
                    .str_replace(
1252
                        "\r\n",
1253
                        '  ',
1254
                        api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1255
                    )
1256
                    .'";';
1257
            }
1258
        }
1259
1260
        $sql = "SELECT
1261
		            survey_question.question_id,
1262
		            survey_question.survey_id,
1263
		            survey_question.survey_question,
1264
		            survey_question.display,
1265
		            survey_question.sort,
1266
		            survey_question.type,
1267
                    survey_question_option.question_option_id,
1268
                    survey_question_option.option_text,
1269
                    survey_question_option.sort as option_sort
1270
				FROM $table_survey_question survey_question
1271
				LEFT JOIN $table_survey_question_option survey_question_option
1272
				ON
1273
				    survey_question.question_id = survey_question_option.question_id AND
1274
				    survey_question_option.c_id = $course_id
1275
				WHERE
1276
				    survey_question.survey_id = '".intval($_GET['survey_id'])."' AND
1277
				    survey_question.c_id = $course_id
1278
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1279
        $result = Database::query($sql);
1280
        $possible_answers = [];
1281
        $possible_answers_type = [];
1282
        while ($row = Database::fetch_array($result)) {
1283
            // We show the options if
1284
            // 1. there is no question filter and the export button has not been clicked
1285
            // 2. there is a question filter but the question is selected for display
1286
            if (!(isset($_POST['submit_question_filter'])) || (
1287
                is_array($_POST['questions_filter']) &&
1288
                in_array($row['question_id'], $_POST['questions_filter'])
1289
            )
1290
            ) {
1291
                // We do not show comment and pagebreak question types
1292
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
1293
                    $row['option_text'] = str_replace(["\r", "\n"], ['', ''], $row['option_text']);
1294
                    $return .= api_html_entity_decode(strip_tags($row['option_text']), ENT_QUOTES).';';
1295
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1296
                    $possible_answers_type[$row['question_id']] = $row['type'];
1297
                }
1298
            }
1299
        }
1300
        $return .= "\n";
1301
1302
        // Getting all the answers of the users
1303
        $old_user = '';
1304
        $answers_of_user = [];
1305
        $sql = "SELECT * FROM $table_survey_answer
1306
		        WHERE c_id = $course_id AND survey_id='".intval($_GET['survey_id'])."'";
1307
        if ($user_id != 0) {
1308
            $sql .= "AND user='".Database::escape_string($user_id)."' ";
1309
        }
1310
        $sql .= "ORDER BY user ASC";
1311
1312
        $open_question_iterator = 1;
1313
        $result = Database::query($sql);
1314
        while ($row = Database::fetch_array($result)) {
1315
            if ($old_user != $row['user'] && $old_user != '') {
1316
                $return .= self::export_complete_report_row(
1317
                    $survey_data,
1318
                    $possible_answers,
1319
                    $answers_of_user,
1320
                    $old_user,
1321
                    true
1322
                );
1323
                $answers_of_user = [];
1324
            }
1325
            if ($possible_answers_type[$row['question_id']] == 'open') {
1326
                $temp_id = 'open'.$open_question_iterator;
1327
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1328
                $open_question_iterator++;
1329
            } else {
1330
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1331
            }
1332
            $old_user = $row['user'];
1333
        }
1334
        // This is to display the last user
1335
        $return .= self::export_complete_report_row(
1336
            $survey_data,
1337
            $possible_answers,
1338
            $answers_of_user,
1339
            $old_user,
1340
            true
1341
        );
1342
1343
        return $return;
1344
    }
1345
1346
    /**
1347
     * Add a line to the csv file
1348
     *
1349
     * @param array Possible answers
1350
     * @param array User's answers
1351
     * @param mixed User ID or user details as string - Used as a string in the result string
1352
     * @param boolean Whether to display user fields or not
1353
     * @return string One line of the csv file
1354
     * @author Patrick Cool <[email protected]>, Ghent University
1355
     * @version February 2007
1356
     */
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...
1357
    public static function export_complete_report_row(
1358
        $survey_data,
1359
        $possible_options,
1360
        $answers_of_user,
1361
        $user,
1362
        $display_extra_user_fields = false
1363
    ) {
1364
        $return = '';
1365
        if ($survey_data['anonymous'] == 0) {
1366
            if (intval($user) !== 0) {
1367
                $userInfo = api_get_user_info($user);
1368
                if (!empty($userInfo)) {
1369
                    $user_displayed = $userInfo['complete_name_with_username'];
1370
                } else {
1371
                    $user_displayed = '-';
1372
                }
1373
                $return .= $user_displayed.';';
1374
            } else {
1375
                $return .= $user.';';
1376
            }
1377
        } else {
1378
            $return .= '-;'; // The user column
1379
        }
1380
1381
        if ($display_extra_user_fields) {
1382
            // Show user fields data, if any, for this user
1383
            $user_fields_values = UserManager::get_extra_user_data(
1384
                $user,
1385
                false,
1386
                false,
1387
                false,
1388
                true
1389
            );
1390
            foreach ($user_fields_values as & $value) {
1391
                $return .= '"'.str_replace('"', '""', api_html_entity_decode(strip_tags($value), ENT_QUOTES)).'";';
1392
            }
1393
        }
1394
1395
        if (is_array($possible_options)) {
1396
            foreach ($possible_options as $question_id => $possible_option) {
1397
                if (is_array($possible_option) && count($possible_option) > 0) {
1398
                    foreach ($possible_option as $option_id => & $value) {
1399
                        $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];
1400
                        $key = array_keys($my_answer_of_user);
1401
                        if (isset($key[0]) && substr($key[0], 0, 4) == 'open') {
1402
                            $return .= '"'.
1403
                                str_replace(
1404
                                    '"',
1405
                                    '""',
1406
                                    api_html_entity_decode(
1407
                                        strip_tags(
1408
                                            $answers_of_user[$question_id][$key[0]]['option_id']
1409
                                        ),
1410
                                        ENT_QUOTES
1411
                                    )
1412
                                ).
1413
                                '"';
1414
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
1415
                            //$return .= 'v';
1416
                            if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1417
                                $return .= $answers_of_user[$question_id][$option_id]['value'];
1418
                            } else {
1419
                                $return .= 'v';
1420
                            }
1421
                        }
1422
                        $return .= ';';
1423
                    }
1424
                }
1425
            }
1426
        }
1427
        $return .= "\n";
1428
1429
        return $return;
1430
    }
1431
1432
    /**
1433
     * Quite similar to display_complete_report(), returns an HTML string
1434
     * that can be used in a csv file
1435
     * @todo consider merging this function with display_complete_report
1436
     * @return string The contents of a csv file
1437
     * @author Patrick Cool <[email protected]>, Ghent University
1438
     * @version February 2007
1439
     */
1440
    public static function export_complete_report_xls($survey_data, $filename, $user_id = 0)
1441
    {
1442
        $course_id = api_get_course_int_id();
1443
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1444
1445
        if (empty($course_id) || empty($surveyId)) {
1446
            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...
1447
        }
1448
1449
        $spreadsheet = new PHPExcel();
1450
        $spreadsheet->setActiveSheetIndex(0);
1451
        $worksheet = $spreadsheet->getActiveSheet();
1452
        $line = 1;
1453
        $column = 1; // Skip the first column (row titles)
1454
1455
        // Show extra fields blank space (enough for extra fields on next line)
1456
        // Show user fields section with a big th colspan that spans over all fields
1457
        $extra_user_fields = UserManager::get_extra_fields(
1458
            0,
1459
            0,
1460
            5,
1461
            'ASC',
1462
            false,
1463
            true
1464
        );
1465
        $num = count($extra_user_fields);
1466
        for ($i = 0; $i < $num; $i++) {
1467
            $worksheet->setCellValueByColumnAndRow($column, $line, '');
1468
            $column++;
1469
        }
1470
1471
        $display_extra_user_fields = true;
1472
1473
        // Database table definitions
1474
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1475
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1476
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1477
1478
        // First line (questions)
1479
        $sql = "SELECT
1480
                    questions.question_id,
1481
                    questions.type,
1482
                    questions.survey_question,
1483
                    count(options.question_option_id) as number_of_options
1484
				FROM $table_survey_question questions
1485
				LEFT JOIN $table_survey_question_option options
1486
                ON questions.question_id = options.question_id AND options.c_id = $course_id
1487
				WHERE
1488
				    questions.survey_id = $surveyId AND
1489
				    questions.c_id = $course_id
1490
				GROUP BY questions.question_id
1491
				ORDER BY questions.sort ASC";
1492
        $result = Database::query($sql);
1493
        while ($row = Database::fetch_array($result)) {
1494
            // We show the questions if
1495
            // 1. there is no question filter and the export button has not been clicked
1496
            // 2. there is a quesiton filter but the question is selected for display
1497
            if (!(isset($_POST['submit_question_filter'])) ||
1498
                (isset($_POST['submit_question_filter']) && is_array($_POST['questions_filter']) &&
1499
                in_array($row['question_id'], $_POST['questions_filter']))
1500
            ) {
1501
                // We do not show comment and pagebreak question types
1502
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
1503
                    if ($row['number_of_options'] == 0 && $row['type'] == 'open') {
1504
                        $worksheet->setCellValueByColumnAndRow(
1505
                            $column,
1506
                            $line,
1507
                            api_html_entity_decode(
1508
                                strip_tags($row['survey_question']),
1509
                                ENT_QUOTES
1510
                            )
1511
                        );
1512
                        $column++;
1513
                    } else {
1514
                        for ($ii = 0; $ii < $row['number_of_options']; $ii++) {
1515
                            $worksheet->setCellValueByColumnAndRow(
1516
                                $column,
1517
                                $line,
1518
                                api_html_entity_decode(
1519
                                    strip_tags($row['survey_question']),
1520
                                    ENT_QUOTES
1521
                                )
1522
                            );
1523
                            $column++;
1524
                        }
1525
                    }
1526
                }
1527
            }
1528
        }
1529
1530
        $line++;
1531
        $column = 1;
1532
        // Show extra field values
1533
        if ($display_extra_user_fields) {
1534
            // Show the fields names for user fields
1535
            foreach ($extra_user_fields as & $field) {
1536
                $worksheet->setCellValueByColumnAndRow(
1537
                    $column,
1538
                    $line,
1539
                    api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
1540
                );
1541
                $column++;
1542
            }
1543
        }
1544
1545
        // Getting all the questions and options (second line)
1546
        $sql = "SELECT
1547
                    survey_question.question_id, 
1548
                    survey_question.survey_id, 
1549
                    survey_question.survey_question, 
1550
                    survey_question.display, 
1551
                    survey_question.sort, 
1552
                    survey_question.type,
1553
                    survey_question_option.question_option_id, 
1554
                    survey_question_option.option_text, 
1555
                    survey_question_option.sort as option_sort
1556
				FROM $table_survey_question survey_question
1557
				LEFT JOIN $table_survey_question_option survey_question_option
1558
				ON 
1559
				    survey_question.question_id = survey_question_option.question_id AND 
1560
				    survey_question_option.c_id = $course_id
1561
				WHERE 
1562
				    survey_question.survey_id = $surveyId AND
1563
				    survey_question.c_id = $course_id
1564
				ORDER BY survey_question.sort ASC, survey_question_option.sort ASC";
1565
        $result = Database::query($sql);
1566
        $possible_answers = [];
1567
        $possible_answers_type = [];
1568
        while ($row = Database::fetch_array($result)) {
1569
            // We show the options if
1570
            // 1. there is no question filter and the export button has not been clicked
1571
            // 2. there is a quesiton filter but the question is selected for display
1572
            if (!isset($_POST['submit_question_filter']) ||
1573
                (isset($_POST['questions_filter']) && is_array($_POST['questions_filter']) &&
1574
                in_array($row['question_id'], $_POST['questions_filter']))
1575
            ) {
1576
                // We do not show comment and pagebreak question types
1577
                if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
1578
                    $worksheet->setCellValueByColumnAndRow(
1579
                        $column,
1580
                        $line,
1581
                        api_html_entity_decode(
1582
                            strip_tags($row['option_text']),
1583
                            ENT_QUOTES
1584
                        )
1585
                    );
1586
                    $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
1587
                    $possible_answers_type[$row['question_id']] = $row['type'];
1588
                    $column++;
1589
                }
1590
            }
1591
        }
1592
1593
        // Getting all the answers of the users
1594
        $line++;
1595
        $column = 0;
1596
        $old_user = '';
1597
        $answers_of_user = [];
1598
        $sql = "SELECT * FROM $table_survey_answer
1599
                WHERE c_id = $course_id AND survey_id = $surveyId";
1600
        if ($user_id != 0) {
1601
            $sql .= " AND user='".intval($user_id)."' ";
1602
        }
1603
        $sql .= " ORDER BY user ASC";
1604
1605
        $open_question_iterator = 1;
1606
        $result = Database::query($sql);
1607
        while ($row = Database::fetch_array($result)) {
1608
            if ($old_user != $row['user'] && $old_user != '') {
1609
                $return = self::export_complete_report_row_xls(
1610
                    $survey_data,
1611
                    $possible_answers,
1612
                    $answers_of_user,
1613
                    $old_user,
1614
                    true
1615
                );
1616
                foreach ($return as $elem) {
1617
                    $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
1618
                    $column++;
1619
                }
1620
                $answers_of_user = [];
1621
                $line++;
1622
                $column = 0;
1623
            }
1624
            if ($possible_answers_type[$row['question_id']] == 'open') {
1625
                $temp_id = 'open'.$open_question_iterator;
1626
                $answers_of_user[$row['question_id']][$temp_id] = $row;
1627
                $open_question_iterator++;
1628
            } else {
1629
                $answers_of_user[$row['question_id']][$row['option_id']] = $row;
1630
            }
1631
            $old_user = $row['user'];
1632
        }
1633
1634
        $return = self::export_complete_report_row_xls(
1635
            $survey_data,
1636
            $possible_answers,
1637
            $answers_of_user,
1638
            $old_user,
1639
            true
1640
        );
1641
1642
        // this is to display the last user
1643
        foreach ($return as $elem) {
0 ignored issues
show
Bug introduced by
The expression $return of type string is not traversable.
Loading history...
1644
            $worksheet->setCellValueByColumnAndRow($column, $line, $elem);
1645
            $column++;
1646
        }
1647
1648
        $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
1649
        $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
1650
        $writer->save($file);
1651
        DocumentManager::file_send_for_download($file, true, $filename);
1652
1653
        return null;
1654
    }
1655
1656
    /**
1657
     * Add a line to the csv file
1658
     *
1659
     * @param array Possible answers
1660
     * @param array User's answers
1661
     * @param mixed User ID or user details as string - Used as a string in the result string
1662
     * @param boolean Whether to display user fields or not
1663
     * @return string One line of the csv file
1664
     */
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...
1665
    public static function export_complete_report_row_xls(
1666
        $survey_data,
1667
        $possible_options,
1668
        $answers_of_user,
1669
        $user,
1670
        $display_extra_user_fields = false
1671
    ) {
1672
        $return = [];
1673
        if ($survey_data['anonymous'] == 0) {
1674
            if (intval($user) !== 0) {
1675
                $userInfo = api_get_user_info($user);
1676
                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...
1677
                    $user_displayed = $userInfo['complete_name_with_username'];
1678
                } else {
1679
                    $user_displayed = '-';
1680
                }
1681
                $return[] = $user_displayed;
1682
            } else {
1683
                $return[] = $user;
1684
            }
1685
        } else {
1686
            $return[] = '-'; // The user column
1687
        }
1688
1689
        if ($display_extra_user_fields) {
1690
            //show user fields data, if any, for this user
1691
            $user_fields_values = UserManager::get_extra_user_data(
1692
                intval($user),
1693
                false,
1694
                false,
1695
                false,
1696
                true
1697
            );
1698
            foreach ($user_fields_values as $value) {
1699
                $return[] = api_html_entity_decode(strip_tags($value), ENT_QUOTES);
1700
            }
1701
        }
1702
1703
        if (is_array($possible_options)) {
1704
            foreach ($possible_options as $question_id => & $possible_option) {
1705
                if (is_array($possible_option) && count($possible_option) > 0) {
1706
                    foreach ($possible_option as $option_id => & $value) {
1707
                        $my_answers_of_user = isset($answers_of_user[$question_id])
1708
                            ? $answers_of_user[$question_id]
1709
                            : [];
1710
                        $key = array_keys($my_answers_of_user);
1711
                        if (isset($key[0]) && substr($key[0], 0, 4) == 'open') {
1712
                            $return[] = api_html_entity_decode(
1713
                                strip_tags($answers_of_user[$question_id][$key[0]]['option_id']),
1714
                                ENT_QUOTES
1715
                            );
1716
                        } elseif (!empty($answers_of_user[$question_id][$option_id])) {
1717
                            if ($answers_of_user[$question_id][$option_id]['value'] != 0) {
1718
                                $return[] = $answers_of_user[$question_id][$option_id]['value'];
1719
                            } else {
1720
                                $return[] = 'v';
1721
                            }
1722
                        } else {
1723
                            $return[] = '';
1724
                        }
1725
                    }
1726
                }
1727
            }
1728
        }
1729
1730
        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...
1731
    }
1732
1733
    /**
1734
     * This function displays the comparative report which
1735
     * allows you to compare two questions
1736
     * A comparative report creates a table where one question
1737
     * is on the x axis and a second question is on the y axis.
1738
     * In the intersection is the number of people who have
1739
     * answered positive on both options.
1740
     *
1741
     * @return string HTML code
1742
     *
1743
     * @author Patrick Cool <[email protected]>, Ghent University
1744
     * @version February 2007
1745
     */
1746
    public static function display_comparative_report()
1747
    {
1748
        // Allowed question types for comparative report
1749
        $allowed_question_types = [
1750
            'yesno',
1751
            'multiplechoice',
1752
            'multipleresponse',
1753
            'dropdown',
1754
            'percentage',
1755
            'score'
1756
        ];
1757
1758
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
1759
1760
        // Getting all the questions
1761
        $questions = SurveyManager::get_questions($surveyId);
1762
1763
        // Actions bar
1764
        echo '<div class="actions">';
1765
        echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/reporting.php?survey_id='.$surveyId.'&'.api_get_cidreq()
1766
            .'">'
1767
            .Display::return_icon(
1768
                'back.png',
1769
                get_lang('BackTo').' '.get_lang('ReportingOverview'),
1770
                [],
1771
                ICON_SIZE_MEDIUM
1772
            )
1773
            .'</a>';
1774
        echo '</div>';
1775
1776
        // Displaying an information message that only the questions with predefined answers can be used in a comparative report
1777
        echo Display::return_message(get_lang('OnlyQuestionsWithPredefinedAnswers'), 'normal', false);
1778
1779
        $xAxis = isset($_GET['xaxis']) ? Security::remove_XSS($_GET['xaxis']) : '';
1780
        $yAxis = isset($_GET['yaxis']) ? Security::remove_XSS($_GET['yaxis']) : '';
1781
1782
        $url = api_get_self().'?'.api_get_cidreq().'&action='.Security::remove_XSS($_GET['action'])
1783
            .'&survey_id='.$surveyId.'&xaxis='.$xAxis.'&y='.$yAxis;
1784
1785
        $form = new FormValidator('compare', 'get', $url);
1786
        $form->addHidden('action', Security::remove_XSS($_GET['action']));
1787
        $form->addHidden('survey_id', $surveyId);
1788
        $optionsX = ['----'];
1789
        $optionsY = ['----'];
1790
        $defaults = [];
1791
        foreach ($questions as $key => & $question) {
1792
            if (is_array($allowed_question_types)) {
1793
                if (in_array($question['type'], $allowed_question_types)) {
1794
                    //echo '<option value="'.$question['question_id'].'"';
1795
                    if (isset($_GET['xaxis']) && $_GET['xaxis'] == $question['question_id']) {
1796
                        $defaults['xaxis'] = $question['question_id'];
1797
                    }
1798
1799
                    if (isset($_GET['yaxis']) && $_GET['yaxis'] == $question['question_id']) {
1800
                        $defaults['yaxis'] = $question['question_id'];
1801
                    }
1802
1803
                    $optionsX[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 50);
1804
                    $optionsY[$question['question_id']] = api_substr(strip_tags($question['question']), 0, 50);
1805
                }
1806
            }
1807
        }
1808
1809
        $form->addSelect('xaxis', get_lang('SelectXAxis'), $optionsX);
1810
        $form->addSelect('yaxis', get_lang('SelectYAxis'), $optionsY);
1811
1812
        $form->addButtonSearch(get_lang('CompareQuestions'));
1813
        $form->setDefaults($defaults);
1814
        $form->display();
1815
1816
        // Getting all the information of the x axis
1817
        if (is_numeric($xAxis)) {
1818
            $question_x = SurveyManager::get_question($xAxis);
1819
        }
1820
1821
        // Getting all the information of the y axis
1822
        if (is_numeric($yAxis)) {
1823
            $question_y = SurveyManager::get_question($yAxis);
1824
        }
1825
1826
        if (is_numeric($xAxis) && is_numeric($yAxis)) {
1827
            // Getting the answers of the two questions
1828
            $answers_x = self::get_answers_of_question_by_user($surveyId, $xAxis);
1829
            $answers_y = self::get_answers_of_question_by_user($surveyId, $yAxis);
1830
1831
            // Displaying the table
1832
            $tableHtml = '<table border="1" class="data_table">';
1833
            $xOptions = [];
1834
            // The header
1835
            $tableHtml .= '<tr>';
1836
            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...
1837
                if ($ii == 0) {
1838
                    $tableHtml .= '<th>&nbsp;</th>';
1839
                } else {
1840
                    if ($question_x['type'] == 'score') {
1841
                        for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
1842
                            $tableHtml .= '<th>'.$question_x['answers'][($ii - 1)].'<br />'.$x.'</th>';
1843
                        }
1844
                        $x = '';
1845
                    } else {
1846
                        $tableHtml .= '<th>'.$question_x['answers'][($ii - 1)].'</th>';
1847
                    }
1848
                    $optionText = strip_tags($question_x['answers'][$ii - 1]);
1849
                    $optionText = html_entity_decode($optionText);
1850
                    array_push($xOptions, trim($optionText));
1851
                }
1852
            }
1853
            $tableHtml .= '</tr>';
1854
            $chartData = [];
1855
            // The main part
1856
            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...
1857
                $currentYQuestion = strip_tags($question_y['answers'][$ij]);
1858
                $currentYQuestion = html_entity_decode($currentYQuestion);
1859
                // The Y axis is a scoring question type so we have more rows than the options (actually options * maximum score)
1860
                if ($question_y['type'] == 'score') {
1861
                    for ($y = 1; $y <= $question_y['maximum_score']; $y++) {
1862
                        $tableHtml .= '<tr>';
1863
                        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...
1864
                            if ($question_x['type'] == 'score') {
1865
                                for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
1866
                                    if ($ii == 0) {
1867
                                        $tableHtml .= '<th>'.$question_y['answers'][($ij)].' '.$y.'</th>';
1868
                                        break;
1869
                                    } else {
1870
                                        $tableHtml .= '<td align="center">';
1871
                                        $votes = self::comparative_check(
1872
                                            $answers_x,
1873
                                            $answers_y,
1874
                                            $question_x['answersid'][($ii - 1)],
1875
                                            $question_y['answersid'][($ij)],
1876
                                            $x,
1877
                                            $y
1878
                                        );
1879
                                        $tableHtml .= $votes;
1880
                                        array_push(
1881
                                            $chartData,
1882
                                            [
1883
                                                'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
1884
                                                'option' => $x,
1885
                                                'votes' => $votes
1886
                                            ]
1887
                                        );
1888
                                        $tableHtml .= '</td>';
1889
                                    }
1890
                                }
1891
                            } else {
1892
                                if ($ii == 0) {
1893
                                    $tableHtml .= '<th>'.$question_y['answers'][$ij].' '.$y.'</th>';
1894
                                } else {
1895
                                    $tableHtml .= '<td align="center">';
1896
                                    $votes = self::comparative_check(
1897
                                        $answers_x,
1898
                                        $answers_y,
1899
                                        $question_x['answersid'][($ii - 1)],
1900
                                        $question_y['answersid'][($ij)],
1901
                                        0,
1902
                                        $y
1903
                                    );
1904
                                    $tableHtml .= $votes;
1905
                                    array_push(
1906
                                        $chartData,
1907
                                        [
1908
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
1909
                                            'option' => $y,
1910
                                            'votes' => $votes
1911
                                        ]
1912
                                    );
1913
                                    $tableHtml .= '</td>';
1914
                                }
1915
                            }
1916
                        }
1917
                        $tableHtml .= '</tr>';
1918
                    }
1919
                } else {
1920
                    // The Y axis is NOT a score question type so the number of rows = the number of options
1921
                    $tableHtml .= '<tr>';
1922
                    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...
1923
                        if ($question_x['type'] == 'score') {
1924
                            for ($x = 1; $x <= $question_x['maximum_score']; $x++) {
1925
                                if ($ii == 0) {
1926
                                    $tableHtml .= '<th>'.$question_y['answers'][$ij].'</th>';
1927
                                    break;
1928
                                } else {
1929
                                    $tableHtml .= '<td align="center">';
1930
                                    $votes = self::comparative_check(
1931
                                        $answers_x,
1932
                                        $answers_y,
1933
                                        $question_x['answersid'][($ii - 1)],
1934
                                        $question_y['answersid'][($ij)],
1935
                                        $x,
1936
                                        0
1937
                                    );
1938
                                    $tableHtml .= $votes;
1939
                                    array_push(
1940
                                        $chartData,
1941
                                        [
1942
                                            'serie' => [$currentYQuestion, $xOptions[$ii - 1]],
1943
                                            'option' => $x,
1944
                                            'votes' => $votes
1945
                                        ]
1946
                                    );
1947
                                    $tableHtml .= '</td>';
1948
                                }
1949
                            }
1950
                        } else {
1951
                            if ($ii == 0) {
1952
                                $tableHtml .= '<th>'.$question_y['answers'][($ij)].'</th>';
1953
                            } else {
1954
                                $tableHtml .= '<td align="center">';
1955
                                $votes = self::comparative_check(
1956
                                    $answers_x,
1957
                                    $answers_y,
1958
                                    $question_x['answersid'][($ii - 1)],
1959
                                    $question_y['answersid'][($ij)]
1960
                                );
1961
                                $tableHtml .= $votes;
1962
                                array_push(
1963
                                    $chartData,
1964
                                    [
1965
                                        'serie' => $xOptions[$ii - 1],
1966
                                        'option' => $currentYQuestion,
1967
                                        'votes' => $votes
1968
                                    ]
1969
                                );
1970
                                $tableHtml .= '</td>';
1971
                            }
1972
                        }
1973
                    }
1974
                    $tableHtml .= '</tr>';
1975
                }
1976
            }
1977
            $tableHtml .= '</table>';
1978
            echo '<div id="chartContainer" class="col-md-12">';
1979
            echo self::drawChart($chartData, true);
1980
            echo '</div>';
1981
            echo $tableHtml;
1982
        }
1983
    }
1984
1985
    /**
1986
     * Get all the answers of a question grouped by user
1987
     *
1988
     * @param integer $survey_id Survey ID
1989
     * @param integer $question_id Question ID
1990
     * @return array Array containing all answers of all users, grouped by user
1991
     *
1992
     * @author Patrick Cool <[email protected]>, Ghent University
1993
     * @version February 2007 - Updated March 2008
1994
     */
1995
    public static function get_answers_of_question_by_user($survey_id, $question_id)
1996
    {
1997
        $course_id = api_get_course_int_id();
1998
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1999
2000
        $sql = "SELECT * FROM $table_survey_answer
2001
                WHERE 
2002
                  c_id = $course_id AND 
2003
                  survey_id='".intval($survey_id)."' AND 
2004
                  question_id='".intval($question_id)."'
2005
                ORDER BY USER ASC";
2006
        $result = Database::query($sql);
2007
        $return = [];
2008
        while ($row = Database::fetch_array($result)) {
2009
            if ($row['value'] == 0) {
2010
                $return[$row['user']][] = $row['option_id'];
2011
            } else {
2012
                $return[$row['user']][] = $row['option_id'].'*'.$row['value'];
2013
            }
2014
        }
2015
2016
        return $return;
2017
    }
2018
2019
    /**
2020
     * Count the number of users who answer positively on both options
2021
     *
2022
     * @param array All answers of the x axis
2023
     * @param array All answers of the y axis
2024
     * @param integer x axis value (= the option_id of the first question)
2025
     * @param integer y axis value (= the option_id of the second question)
2026
     * @return integer Number of users who have answered positively to both options
2027
     *
2028
     * @author Patrick Cool <[email protected]>, Ghent University
2029
     * @version February 2007
2030
     */
2031
    public static function comparative_check(
2032
        $answers_x,
2033
        $answers_y,
2034
        $option_x,
2035
        $option_y,
2036
        $value_x = 0,
2037
        $value_y = 0
2038
    ) {
2039
        if ($value_x == 0) {
2040
            $check_x = $option_x;
2041
        } else {
2042
            $check_x = $option_x.'*'.$value_x;
2043
        }
2044
        if ($value_y == 0) {
2045
            $check_y = $option_y;
2046
        } else {
2047
            $check_y = $option_y.'*'.$value_y;
2048
        }
2049
2050
        $counter = 0;
2051
        if (is_array($answers_x)) {
2052
            foreach ($answers_x as $user => & $answers) {
2053
                // Check if the user has given $option_x as answer
2054
                if (in_array($check_x, $answers)) {
2055
                    // Check if the user has given $option_y as an answer
2056
                    if (!is_null($answers_y[$user]) &&
2057
                        in_array($check_y, $answers_y[$user])
2058
                    ) {
2059
                        $counter++;
2060
                    }
2061
                }
2062
            }
2063
        }
2064
2065
        return $counter;
2066
    }
2067
2068
    /**
2069
     * Get all the information about the invitations of a certain survey
2070
     *
2071
     * @return array Lines of invitation [user, code, date, empty element]
2072
     *
2073
     * @author Patrick Cool <[email protected]>, Ghent University
2074
     * @version January 2007
2075
     *
2076
     * @todo use survey_id parameter instead of $_GET
2077
     */
2078
    public static function get_survey_invitations_data()
2079
    {
2080
        $course_id = api_get_course_int_id();
2081
        // Database table definition
2082
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
2083
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2084
2085
        $sql = "SELECT
2086
					survey_invitation.user as col1,
2087
					survey_invitation.invitation_code as col2,
2088
					survey_invitation.invitation_date as col3,
2089
					'' as col4
2090
                FROM $table_survey_invitation survey_invitation
2091
                LEFT JOIN $table_user user
2092
                ON survey_invitation.user = user.user_id
2093
                WHERE
2094
                    survey_invitation.c_id = $course_id AND
2095
                    survey_invitation.survey_id = '".intval($_GET['survey_id'])."' AND
2096
                    session_id='".api_get_session_id()."'  ";
2097
        $res = Database::query($sql);
2098
        $data = [];
2099
        while ($row = Database::fetch_array($res)) {
2100
            $data[] = $row;
2101
        }
2102
2103
        return $data;
2104
    }
2105
2106
    /**
2107
     * Get the total number of survey invitations for a given survey (through $_GET['survey_id'])
2108
     *
2109
     * @return integer Total number of survey invitations
2110
     *
2111
     * @todo use survey_id parameter instead of $_GET
2112
     *
2113
     * @author Patrick Cool <[email protected]>, Ghent University
2114
     * @version January 2007
2115
     */
2116
    public static function get_number_of_survey_invitations()
2117
    {
2118
        $course_id = api_get_course_int_id();
2119
2120
        // Database table definition
2121
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2122
2123
        $sql = "SELECT count(user) AS total
2124
		        FROM $table
2125
		        WHERE
2126
                    c_id = $course_id AND
2127
                    survey_id='".intval($_GET['survey_id'])."' AND
2128
                    session_id='".api_get_session_id()."' ";
2129
        $res = Database::query($sql);
2130
        $row = Database::fetch_array($res, 'ASSOC');
2131
2132
        return $row['total'];
2133
    }
2134
2135
    /**
2136
     * Save the invitation mail
2137
     *
2138
     * @param string Text of the e-mail
2139
     * @param integer Whether the mail contents are for invite mail (0, default) or reminder mail (1)
2140
     *
2141
     * @author Patrick Cool <[email protected]>, Ghent University
2142
     * @version January 2007
2143
     */
2144
    public static function save_invite_mail($mailtext, $mail_subject, $reminder = 0)
2145
    {
2146
        $course_id = api_get_course_int_id();
2147
        // Database table definition
2148
        $table_survey = Database::get_course_table(TABLE_SURVEY);
2149
2150
        // Reminder or not
2151
        if ($reminder == 0) {
2152
            $mail_field = 'invite_mail';
2153
        } else {
2154
            $mail_field = 'reminder_mail';
2155
        }
2156
2157
        $sql = "UPDATE $table_survey SET
2158
		        mail_subject='".Database::escape_string($mail_subject)."',
2159
		        $mail_field = '".Database::escape_string($mailtext)."'
2160
		        WHERE c_id = $course_id AND survey_id = '".intval($_GET['survey_id'])."'";
2161
        Database::query($sql);
2162
    }
2163
2164
    /**
2165
     * This function saves all the invitations of course users
2166
     * and additional users in the database
2167
     * and sends the invitations by email
2168
     *
2169
     * @param $users_array Users $array array can be both a list of course uids AND a list of additional emailaddresses
2170
     * @param $invitation_title Title $string of the invitation, used as the title of the mail
2171
     * @param $invitation_text Text $string of the invitation, used as the text of the mail.
2172
     *                         The text has to contain a **link** string or this will automatically be added to the end
2173
     * @param int $reminder
2174
     * @param bool $sendmail
2175
     * @param int $remindUnAnswered
2176
     * @return int
2177
     * @internal param
2178
     * @internal param
2179
     * @internal param
2180
     *                 The text has to contain a **link** string or this will automatically be added to the end
2181
     * @author Patrick Cool <[email protected]>, Ghent University
2182
     * @author Julio Montoya - Adding auto-generated link support
2183
     * @version January 2007
2184
     */
2185
    public static function saveInvitations(
2186
        $users_array,
2187
        $invitation_title,
2188
        $invitation_text,
2189
        $reminder = 0,
2190
        $sendmail = false,
2191
        $remindUnAnswered = 0
2192
    ) {
2193
        if (!is_array($users_array)) {
2194
            // Should not happen
2195
2196
            return 0;
2197
        }
2198
2199
        // Getting the survey information
2200
        $survey_data = SurveyManager::get_survey($_GET['survey_id']);
2201
        $survey_invitations = self::get_invitations($survey_data['survey_code']);
2202
        $already_invited = self::get_invited_users($survey_data['code']);
2203
2204
        // Remind unanswered is a special version of remind all reminder
2205
        $exclude_users = [];
2206
        if ($remindUnAnswered == 1) { // Remind only unanswered users
2207
            $reminder = 1;
2208
            $exclude_users = SurveyManager::get_people_who_filled_survey($_GET['survey_id']);
2209
        }
2210
2211
        $counter = 0; // Nr of invitations "sent" (if sendmail option)
2212
        $course_id = api_get_course_int_id();
2213
        $session_id = api_get_session_id();
2214
        $result = CourseManager::separateUsersGroups($users_array);
2215
2216
        $groupList = $result['groups'];
2217
        $users_array = $result['users'];
2218
2219
        foreach ($groupList as $groupId) {
2220
            $userGroupList = GroupManager::getStudents($groupId);
2221
            $userGroupIdList = array_column($userGroupList, 'user_id');
2222
            $users_array = array_merge($users_array, $userGroupIdList);
2223
2224
            $params = [
2225
                'c_id' => $course_id,
2226
                'session_id' => $session_id,
2227
                'group_id' => $groupId,
2228
                'survey_code' => $survey_data['code']
2229
            ];
2230
2231
            $invitationExists = self::invitationExists(
2232
                $course_id,
2233
                $session_id,
2234
                $groupId,
2235
                $survey_data['code']
2236
            );
2237
            if (empty($invitationExists)) {
2238
                self::save_invitation($params);
2239
            }
2240
        }
2241
2242
        $users_array = array_unique($users_array);
2243
2244
        foreach ($users_array as $key => $value) {
2245
            if (!isset($value) || $value == '') {
2246
                continue;
2247
            }
2248
2249
            // Skip user if reminding only unanswered people
2250
            if (in_array($value, $exclude_users)) {
2251
                continue;
2252
            }
2253
2254
            // Get the unique invitation code if we already have it
2255
            if ($reminder == 1 && array_key_exists($value, $survey_invitations)) {
2256
                $invitation_code = $survey_invitations[$value]['invitation_code'];
2257
            } else {
2258
                $invitation_code = md5($value.microtime());
2259
            }
2260
            $new_user = false; // User not already invited
2261
            // Store the invitation if user_id not in $already_invited['course_users'] OR email is not in $already_invited['additional_users']
2262
            $addit_users_array = isset($already_invited['additional_users']) && !empty($already_invited['additional_users'])
2263
                    ? explode(';', $already_invited['additional_users'])
2264
                    : [];
2265
            $my_alredy_invited = $already_invited['course_users'] == null ? [] : $already_invited['course_users'];
2266
            if ((is_numeric($value) && !in_array($value, $my_alredy_invited)) ||
2267
                (!is_numeric($value) && !in_array($value, $addit_users_array))
2268
            ) {
2269
                $new_user = true;
2270
                if (!array_key_exists($value, $survey_invitations)) {
2271
                    $params = [
2272
                        'c_id' => $course_id,
2273
                        'session_id' => $session_id,
2274
                        'user' => $value,
2275
                        'survey_code' => $survey_data['code'],
2276
                        'invitation_code' => $invitation_code,
2277
                        'invitation_date' => api_get_utc_datetime()
2278
                    ];
2279
                    self::save_invitation($params);
2280
                }
2281
            }
2282
2283
            // Send the email if checkboxed
2284
            if (($new_user || $reminder == 1) && $sendmail) {
2285
                // Make a change for absolute url
2286
                if (isset($invitation_text)) {
2287
                    $invitation_text = api_html_entity_decode($invitation_text, ENT_QUOTES);
2288
                    $invitation_text = str_replace('src="../../', 'src="'.api_get_path(WEB_PATH), $invitation_text);
2289
                    $invitation_text = trim(stripslashes($invitation_text));
2290
                }
2291
                self::send_invitation_mail(
2292
                    $value,
2293
                    $invitation_code,
2294
                    $invitation_title,
2295
                    $invitation_text
2296
                );
2297
                $counter++;
2298
            }
2299
        }
2300
2301
        return $counter; // Number of invitations sent
2302
    }
2303
2304
    /**
2305
     * @param $params
2306
     * @return bool|int
2307
     */
2308
    public static function save_invitation($params)
2309
    {
2310
        // Database table to store the invitations data
2311
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2312
        if (!empty($params['c_id']) &&
2313
            (!empty($params['user']) || !empty($params['group_id'])) &&
2314
            !empty($params['survey_code'])
2315
        ) {
2316
            $insertId = Database::insert($table, $params);
2317
            if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2318
                $sql = "UPDATE $table 
2319
                        SET survey_invitation_id = $insertId
2320
                        WHERE iid = $insertId";
2321
                Database::query($sql);
2322
            }
2323
2324
            return $insertId;
2325
        }
2326
2327
        return false;
2328
    }
2329
2330
    /**
2331
     * @param int $courseId
2332
     * @param int $sessionId
2333
     * @param int $groupId
2334
     * @param string $surveyCode
2335
     * @return int
2336
     */
2337
    public static function invitationExists($courseId, $sessionId, $groupId, $surveyCode)
2338
    {
2339
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
2340
        $courseId = intval($courseId);
2341
        $sessionId = intval($sessionId);
2342
        $groupId = intval($groupId);
2343
        $surveyCode = Database::escape_string($surveyCode);
2344
2345
        $sql = "SELECT survey_invitation_id FROM $table
2346
                WHERE
2347
                    c_id = $courseId AND
2348
                    session_id = $sessionId AND
2349
                    group_id = $groupId AND
2350
                    survey_code = '$surveyCode'
2351
                ";
2352
        $result = Database::query($sql);
2353
2354
        return Database::num_rows($result);
2355
    }
2356
2357
    /**
2358
     * Send the invitation by mail.
2359
     *
2360
     * @param int invitedUser - the userId (course user) or emailaddress of additional user
2361
     * $param string $invitation_code - the unique invitation code for the URL
2362
     * @return void
2363
     */
2364
    public static function send_invitation_mail(
2365
        $invitedUser,
2366
        $invitation_code,
2367
        $invitation_title,
2368
        $invitation_text
2369
    ) {
2370
        $_user = api_get_user_info();
2371
        $_course = api_get_course_info();
2372
2373
        // Replacing the **link** part with a valid link for the user
2374
        $survey_link = api_get_path(WEB_CODE_PATH).'survey/fillsurvey.php?course='.$_course['code'].'&invitationcode='
2375
            .$invitation_code;
2376
        $text_link = '<a href="'.$survey_link.'">'.get_lang('ClickHereToAnswerTheSurvey')."</a><br />\r\n<br />\r\n"
2377
            .get_lang('OrCopyPasteTheFollowingUrl')." <br />\r\n ".$survey_link;
2378
2379
        $replace_count = 0;
2380
        $full_invitation_text = api_str_ireplace('**link**', $text_link, $invitation_text, $replace_count);
2381
        if ($replace_count < 1) {
2382
            $full_invitation_text = $full_invitation_text."<br />\r\n<br />\r\n".$text_link;
2383
        }
2384
2385
        // Sending the mail
2386
        $sender_name = api_get_person_name($_user['firstName'], $_user['lastName'], null, PERSON_NAME_EMAIL_ADDRESS);
2387
        $sender_email = $_user['mail'];
2388
        $sender_user_id = api_get_user_id();
2389
2390
        $replyto = [];
2391
        if (api_get_setting('survey_email_sender_noreply') == 'noreply') {
2392
            $noreply = api_get_setting('noreply_email_address');
2393
            if (!empty($noreply)) {
2394
                $replyto['Reply-to'] = $noreply;
2395
                $sender_name = $noreply;
2396
                $sender_email = $noreply;
2397
                $sender_user_id = null;
2398
            }
2399
        }
2400
2401
        // Optionally: finding the e-mail of the course user
2402
        if (is_numeric($invitedUser)) {
2403
            MessageManager::send_message(
2404
                $invitedUser,
2405
                $invitation_title,
2406
                $full_invitation_text,
2407
                [],
2408
                [],
2409
                null,
2410
                null,
2411
                null,
2412
                null,
2413
                $sender_user_id
2414
            );
2415
        } else {
2416
            /** @todo check if the address is a valid email */
2417
            $recipient_email = $invitedUser;
2418
            @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

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