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

SurveyManager   F

Complexity

Total Complexity 194

Size/Duplication

Total Lines 2018
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 2018
rs 0.6314
c 0
b 0
f 0
wmc 194

34 Methods

Rating   Name   Duplication   Size   Complexity  
A generate_survey_hash() 0 5 1
B save_shared_question_options() 0 22 4
B store_shared_survey() 0 44 4
B emptySurveyFromId() 0 30 2
B get_people_who_filled_survey() 0 50 6
A is_user_filled_survey() 0 19 2
F save_question() 0 180 33
A delete_all_survey_questions() 0 23 2
C copySurveySession() 0 109 11
A validate_survey_hash() 0 8 2
B save_shared_question() 0 45 3
B get_questions() 0 35 4
B get_question() 0 65 5
B move_survey_question() 0 43 6
A survey_generation_hash_available() 0 7 2
F store_survey() 0 327 40
A delete_shared_survey_question() 0 18 1
A delete_survey_question() 0 19 2
A delete_all_survey_answers() 0 10 1
A generateSurveyCode() 0 3 1
B delete_all_survey_invitations_by_user() 0 22 4
B empty_survey() 0 31 3
A generate_survey_link() 0 15 1
C save_question_options() 0 45 11
B icon_question() 0 34 2
C get_survey() 0 63 10
B update_survey_answered() 0 41 2
C copy_survey() 0 119 8
A delete_all_survey_questions_options() 0 18 2
A delete_survey_question_option() 0 23 2
B delete_survey() 0 49 4
B generate_unique_code() 0 23 4
B protectByMandatory() 0 63 6
A get_surveys() 0 20 3

How to fix   Complexity   

Complex Class

Complex classes like SurveyManager 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 SurveyManager, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CSurveyInvitation;
5
use Doctrine\Common\Collections\Criteria;
6
7
/**
8
 * Class SurveyManager
9
 * @package chamilo.survey
10
 * @author Patrick Cool <[email protected]>, Ghent University:
11
 * cleanup, refactoring and rewriting large parts (if not all) of the code
12
 * @author Julio Montoya <[email protected]>, Personality Test modification
13
 * and rewriting large parts of the code
14
 * @author cfasanando
15
 * @todo move this file to inc/lib
16
 * @todo use consistent naming for the functions (save vs store for instance)
17
 */
18
class SurveyManager
19
{
20
    /**
21
     * @param $code
22
     *
23
     * @return string
24
     */
25
    public static function generate_unique_code($code)
26
    {
27
        if (empty($code)) {
28
            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...
29
        }
30
        $course_id = api_get_course_int_id();
31
        $table_survey = Database::get_course_table(TABLE_SURVEY);
32
        $code = Database::escape_string($code);
33
        $num = 0;
34
        $new_code = $code;
35
        while (true) {
36
            $sql = "SELECT * FROM $table_survey
37
                    WHERE code = '$new_code' AND c_id = $course_id";
38
            $result = Database::query($sql);
39
            if (Database::num_rows($result)) {
40
                $num++;
41
                $new_code = $code.$num;
42
            } else {
43
                break;
44
            }
45
        }
46
47
        return $code.$num;
48
    }
49
50
    /**
51
     * Deletes all survey invitations of a user
52
     * @param int $user_id
53
     *
54
     * @return boolean
55
     * @assert ('') === false
56
     */
57
    public static function delete_all_survey_invitations_by_user($user_id)
58
    {
59
        $user_id = intval($user_id);
60
        if (empty($user_id)) {
61
            return false;
62
        }
63
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
64
        $table_survey = Database::get_course_table(TABLE_SURVEY);
65
66
        $sql = "SELECT survey_invitation_id, survey_code
67
                FROM $table_survey_invitation WHERE user = '$user_id' AND c_id <> 0 ";
68
        $result = Database::query($sql);
69
        while ($row = Database::fetch_array($result, 'ASSOC')) {
70
            $survey_invitation_id = $row['survey_invitation_id'];
71
            $survey_code = $row['survey_code'];
72
            $sql2 = "DELETE FROM $table_survey_invitation
73
                    WHERE survey_invitation_id = '$survey_invitation_id' AND c_id <> 0";
74
            if (Database::query($sql2)) {
75
                $sql3 = "UPDATE $table_survey SET
76
                            invited = invited-1
77
                        WHERE c_id <> 0 AND code ='$survey_code'";
78
                Database::query($sql3);
79
            }
80
        }
81
    }
82
83
    /**
84
     *
85
     * @param string $course_code
86
     * @param int $session_id
87
     *
88
     * @return array
89
     * @assert ('') === false
90
     */
91
    public static function get_surveys($course_code, $session_id = 0)
92
    {
93
        $table_survey = Database::get_course_table(TABLE_SURVEY);
94
        if (empty($course_code)) {
95
            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 array.
Loading history...
96
        }
97
        $course_info = api_get_course_info($course_code);
98
99
        if (empty($course_info)) {
100
            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 array.
Loading history...
101
        }
102
103
        $session_condition = api_get_session_condition($session_id, true, true);
104
105
        $sql = "SELECT * FROM $table_survey
106
                WHERE c_id = {$course_info['real_id']} $session_condition ";
107
        $result = Database::query($sql);
108
        $result = Database::store_result($result, 'ASSOC');
109
110
        return $result;
111
    }
112
113
    /**
114
     * Retrieves all the survey information
115
     *
116
     * @param integer $survey_id the id of the survey
117
     * @param boolean $shared this parameter determines if
118
     * we have to get the information of a survey from the central (shared) database or from the
119
     *          course database
120
     * @param string course code optional
121
     *
122
     * @author Patrick Cool <[email protected]>, Ghent University
123
     * @version February 2007
124
     * @assert ('') === false
125
     * @return array
126
     *
127
     * @todo this is the same function as in create_new_survey.php
128
     */
129
    public static function get_survey(
130
        $survey_id,
131
        $shared = 0,
132
        $course_code = '',
133
        $simple_return = false
134
    ) {
135
        // Table definition
136
        if (!empty($course_code)) {
137
            $my_course_id = $course_code;
138
        } elseif (isset($_GET['course'])) {
139
            $my_course_id = Security::remove_XSS($_GET['course']);
140
        } else {
141
            $my_course_id = api_get_course_id();
142
        }
143
        $courseInfo = api_get_course_info($my_course_id);
144
        $table_survey = Database::get_course_table(TABLE_SURVEY);
145
146
        if ($shared != 0) {
147
            $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
148
            $sql = "SELECT * FROM $table_survey
149
                    WHERE survey_id='".intval($survey_id)."' ";
150
        } else {
151
            if (empty($courseInfo)) {
152
                return [];
153
            }
154
            $sql = "SELECT * FROM $table_survey
155
		            WHERE
156
		                survey_id='".intval($survey_id)."' AND
157
		                c_id = ".$courseInfo['real_id'];
158
        }
159
160
        $result = Database::query($sql);
161
        $return = [];
162
163
        if (Database::num_rows($result) > 0) {
164
            $return = Database::fetch_array($result, 'ASSOC');
165
            if ($simple_return) {
166
                return $return;
167
            }
168
            // We do this (temporarily) to have the array match the quickform elements immediately
169
            // idealiter the fields in the db match the quickform fields
170
            $return['survey_code'] = $return['code'];
171
            $return['survey_title'] = $return['title'];
172
            $return['survey_subtitle'] = $return['subtitle'];
173
            $return['survey_language'] = $return['lang'];
174
            $return['start_date'] = $return['avail_from'];
175
            $return['end_date'] = $return['avail_till'];
176
            $return['survey_share'] = $return['is_shared'];
177
            $return['survey_introduction'] = $return['intro'];
178
            $return['survey_thanks'] = $return['surveythanks'];
179
            $return['survey_type'] = $return['survey_type'];
180
            $return['one_question_per_page'] = $return['one_question_per_page'];
181
            $return['show_form_profile'] = $return['show_form_profile'];
182
            $return['input_name_list'] = isset($return['input_name_list']) ? $return['input_name_list'] : null;
183
            $return['shuffle'] = $return['shuffle'];
184
            $return['parent_id'] = $return['parent_id'];
185
            $return['survey_version'] = $return['survey_version'];
186
            $return['anonymous'] = $return['anonymous'];
187
            $return['c_id'] = isset($return['c_id']) ? $return['c_id'] : 0;
188
            $return['session_id'] = isset($return['session_id']) ? $return['session_id'] : 0;
189
        }
190
191
        return $return;
192
    }
193
194
    /**
195
     * @param string $code
196
     * @return string
197
     */
198
    public static function generateSurveyCode($code)
199
    {
200
        return strtolower(CourseManager::generate_course_code($code));
201
    }
202
203
    /**
204
     * This function stores a survey in the database.
205
     *
206
     * @param array $values
207
     *
208
     * @return array $return the type of return message that has to be displayed and the message in it
209
     *
210
     * @author Patrick Cool <[email protected]>, Ghent University
211
     * @version February 2007
212
     */
213
    public static function store_survey($values)
214
    {
215
        $_user = api_get_user_info();
216
        $course_id = api_get_course_int_id();
217
        $session_id = api_get_session_id();
218
        $courseCode = api_get_course_id();
219
        $table_survey = Database::get_course_table(TABLE_SURVEY);
220
        $shared_survey_id = 0;
221
222
        if (!isset($values['survey_id'])) {
223
            // Check if the code doesn't soon exists in this language
224
            $sql = 'SELECT 1 FROM '.$table_survey.'
225
			        WHERE
226
			            c_id = '.$course_id.' AND
227
			            code="'.Database::escape_string($values['survey_code']).'" AND
228
			            lang="'.Database::escape_string($values['survey_language']).'"';
229
            $rs = Database::query($sql);
230
            if (Database::num_rows($rs) > 0) {
231
                Display::addFlash(
232
                    Display::return_message(
233
                        get_lang('ThisSurveyCodeSoonExistsInThisLanguage'),
234
                        'error'
235
                    )
236
                );
237
                $return['type'] = 'error';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
238
                $return['id'] = isset($values['survey_id']) ? $values['survey_id'] : 0;
239
240
                return $return;
241
            }
242
243
            if (!isset($values['anonymous'])) {
244
                $values['anonymous'] = 0;
245
            }
246
247
            $values['anonymous'] = intval($values['anonymous']);
248
            $additional['columns'] = '';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$additional was never initialized. Although not strictly required by PHP, it is generally a good practice to add $additional = array(); before regardless.
Loading history...
249
            $extraParams = [];
250
251
            if ($values['anonymous'] == 0) {
252
                // Input_name_list
253
                $values['show_form_profile'] = isset($values['show_form_profile']) ? $values['show_form_profile'] : 0;
254
                $extraParams['show_form_profile'] = $values['show_form_profile'];
255
256
                if ($values['show_form_profile'] == 1) {
257
                    // Input_name_list
258
                    $fields = explode(',', $values['input_name_list']);
259
                    $field_values = '';
260
                    foreach ($fields as & $field) {
261
                        if ($field != '') {
262
                            if ($values[$field] == '') {
263
                                $values[$field] = 0;
264
                            }
265
                            $field_values .= $field.':'.$values[$field].'@';
266
                        }
267
                    }
268
                    $extraParams['form_fields'] = $field_values;
269
                } else {
270
                    $extraParams['form_fields'] = '';
271
                }
272
            } else {
273
                // Input_name_list
274
                $extraParams['show_form_profile'] = 0;
275
                $extraParams['form_fields'] = '';
276
            }
277
278
            if ($values['survey_type'] == 1) {
279
                $extraParams['survey_type'] = 1;
280
                $extraParams['shuffle'] = $values['shuffle'];
281
                $extraParams['one_question_per_page'] = $values['one_question_per_page'];
282
                $extraParams['parent_id'] = $values['parent_id'];
283
284
                // Logic for versioning surveys
285
                if (!empty($values['parent_id'])) {
286
                    $versionValue = '';
287
                    $sql = 'SELECT survey_version
288
                            FROM '.$table_survey.'
289
					        WHERE
290
					            c_id = '.$course_id.' AND
291
					            parent_id = '.intval($values['parent_id']).'
292
                            ORDER BY survey_version DESC
293
                            LIMIT 1';
294
                    $rs = Database::query($sql);
295
                    if (Database::num_rows($rs) === 0) {
296
                        $sql = 'SELECT survey_version FROM '.$table_survey.'
297
						        WHERE
298
						            c_id = '.$course_id.' AND
299
						            survey_id = '.intval($values['parent_id']);
300
                        $rs = Database::query($sql);
301
                        $getversion = Database::fetch_array($rs, 'ASSOC');
302
                        if (empty($getversion['survey_version'])) {
303
                            $versionValue = ++$getversion['survey_version'];
304
                        } else {
305
                            $versionValue = $getversion['survey_version'];
306
                        }
307
                    } else {
308
                        $row = Database::fetch_array($rs, 'ASSOC');
309
                        $pos = api_strpos($row['survey_version']);
0 ignored issues
show
Bug introduced by
The call to api_strpos() has too few arguments starting with needle. ( Ignorable by Annotation )

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

309
                        $pos = /** @scrutinizer ignore-call */ api_strpos($row['survey_version']);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
310
                        if ($pos === false) {
311
                            $row['survey_version'] = $row['survey_version'] + 1;
312
                            $versionValue = $row['survey_version'];
313
                        } else {
314
                            $getlast = explode('\.', $row['survey_version']);
315
                            $lastversion = array_pop($getlast);
316
                            $lastversion = $lastversion + 1;
317
                            $add = implode('.', $getlast);
318
                            if ($add != '') {
319
                                $insertnewversion = $add.'.'.$lastversion;
320
                            } else {
321
                                $insertnewversion = $lastversion;
322
                            }
323
                            $versionValue = $insertnewversion;
324
                        }
325
                    }
326
                    $extraParams['survey_version'] = $versionValue;
327
                }
328
            }
329
330
            $params = [
331
                'c_id' => $course_id,
332
                'code' => self::generateSurveyCode($values['survey_code']),
333
                'title' => $values['survey_title'],
334
                'subtitle' => $values['survey_subtitle'],
335
                'author' => $_user['user_id'],
336
                'lang' => $values['survey_language'],
337
                'avail_from' => $values['start_date'],
338
                'avail_till' => $values['end_date'],
339
                'is_shared' => $shared_survey_id,
340
                'template' => 'template',
341
                'intro' => $values['survey_introduction'],
342
                'surveythanks' => $values['survey_thanks'],
343
                'creation_date' => api_get_utc_datetime(),
344
                'anonymous' => $values['anonymous'],
345
                'session_id' => api_get_session_id(),
346
                'visible_results' => $values['visible_results']
347
            ];
348
349
            $params = array_merge($params, $extraParams);
350
            $survey_id = Database::insert($table_survey, $params);
351
            if ($survey_id > 0) {
352
                $sql = "UPDATE $table_survey SET survey_id = $survey_id
353
                        WHERE iid = $survey_id";
354
                Database::query($sql);
355
356
                // Insert into item_property
357
                api_item_property_update(
358
                    api_get_course_info(),
359
                    TOOL_SURVEY,
360
                    $survey_id,
0 ignored issues
show
Bug introduced by
It seems like $survey_id can also be of type false; however, parameter $item_id of api_item_property_update() does only seem to accept integer, 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

360
                    /** @scrutinizer ignore-type */ $survey_id,
Loading history...
361
                    'SurveyAdded',
362
                    api_get_user_id()
363
                );
364
            }
365
366
            if ($values['survey_type'] == 1 && !empty($values['parent_id'])) {
367
                self::copy_survey($values['parent_id'], $survey_id);
0 ignored issues
show
Bug introduced by
It seems like $survey_id can also be of type false; however, parameter $new_survey_id of SurveyManager::copy_survey() does only seem to accept integer, 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

367
                self::copy_survey($values['parent_id'], /** @scrutinizer ignore-type */ $survey_id);
Loading history...
368
            }
369
370
            Display::addFlash(
371
                Display::return_message(
372
                    get_lang('SurveyCreatedSuccesfully'),
373
                    'success'
374
                )
375
            );
376
            $return['id'] = $survey_id;
377
        } else {
378
            // Check whether the code doesn't soon exists in this language
379
            $sql = 'SELECT 1 FROM '.$table_survey.'
380
			        WHERE
381
			            c_id = '.$course_id.' AND
382
			            code = "'.Database::escape_string($values['survey_code']).'" AND
383
			            lang = "'.Database::escape_string($values['survey_language']).'" AND
384
			            survey_id !='.intval($values['survey_id']);
385
            $rs = Database::query($sql);
386
            if (Database::num_rows($rs) > 0) {
387
                Display::addFlash(
388
                    Display::return_message(
389
                        get_lang('ThisSurveyCodeSoonExistsInThisLanguage'),
390
                        'error'
391
                    )
392
                );
393
                $return['type'] = 'error';
394
                $return['id'] = isset($values['survey_id']) ? $values['survey_id'] : 0;
395
396
                return $return;
397
            }
398
399
            if (!isset($values['anonymous'])
400
                || (isset($values['anonymous']) && $values['anonymous'] == '')
401
            ) {
402
                $values['anonymous'] = 0;
403
            }
404
405
            $values['shuffle'] = isset($values['shuffle']) ? $values['shuffle'] : null;
406
            $values['one_question_per_page'] = isset($values['one_question_per_page'])
407
                ? $values['one_question_per_page']
408
                : null;
409
            $values['show_form_profile'] = isset($values['show_form_profile']) ? $values['show_form_profile'] : null;
410
411
            $extraParams = [];
412
            $extraParams['shuffle'] = $values['shuffle'];
413
            $extraParams['one_question_per_page'] = $values['one_question_per_page'];
414
            $extraParams['shuffle'] = $values['shuffle'];
415
416
            if ($values['anonymous'] == 0) {
417
                $extraParams['show_form_profile'] = $values['show_form_profile'];
418
                if ($values['show_form_profile'] == 1) {
419
                    $fields = explode(',', $values['input_name_list']);
420
                    $field_values = '';
421
                    foreach ($fields as &$field) {
422
                        if ($field != '') {
423
                            if (!isset($values[$field]) ||
424
                                (isset($values[$field]) && $values[$field] == '')
425
                            ) {
426
                                $values[$field] = 0;
427
                            }
428
                            $field_values .= $field.':'.$values[$field].'@';
429
                        }
430
                    }
431
                    $extraParams['form_fields'] = $field_values;
432
                } else {
433
                    $extraParams['form_fields'] = '';
434
                }
435
            } else {
436
                $extraParams['show_form_profile'] = 0;
437
                $extraParams['form_fields'] = '';
438
            }
439
440
            $params = [
441
                'title' => $values['survey_title'],
442
                'subtitle' => $values['survey_subtitle'],
443
                'author' => $_user['user_id'],
444
                'lang' => $values['survey_language'],
445
                'avail_from' => $values['start_date'],
446
                'avail_till' => $values['end_date'],
447
                'is_shared' => $shared_survey_id,
448
                'template' => 'template',
449
                'intro' => $values['survey_introduction'],
450
                'surveythanks' => $values['survey_thanks'],
451
                'anonymous' => $values['anonymous'],
452
                'session_id' => api_get_session_id(),
453
                'visible_results' => $values['visible_results'],
454
            ];
455
456
            $params = array_merge($params, $extraParams);
457
            Database::update(
458
                $table_survey,
459
                $params,
460
                [
461
                    'c_id = ? AND survey_id = ?' => [
462
                        $course_id,
463
                        $values['survey_id'],
464
                    ],
465
                ]
466
            );
467
468
            // Update into item_property (update)
469
            api_item_property_update(
470
                api_get_course_info(),
471
                TOOL_SURVEY,
472
                $values['survey_id'],
473
                'SurveyUpdated',
474
                api_get_user_id()
475
            );
476
477
            Display::addFlash(
478
                Display::return_message(
479
                    get_lang('SurveyUpdatedSuccesfully'),
480
                    'confirmation'
481
                )
482
            );
483
484
            $return['id'] = $values['survey_id'];
485
        }
486
487
        $survey_id = intval($return['id']);
488
489
        // Gradebook
490
        $gradebook_option = false;
491
        if (isset($values['survey_qualify_gradebook'])) {
492
            $gradebook_option = $values['survey_qualify_gradebook'] > 0;
493
        }
494
495
        $gradebook_link_type = 8;
496
497
        $link_info = GradebookUtils::isResourceInCourseGradebook(
498
            $courseCode,
499
            $gradebook_link_type,
500
            $survey_id,
501
            $session_id
502
        );
503
504
        $gradebook_link_id = isset($link_info['id']) ? $link_info['id'] : false;
505
506
        if ($gradebook_option) {
507
            if ($survey_id > 0) {
508
                $title_gradebook = ''; // Not needed here.
509
                $description_gradebook = ''; // Not needed here.
510
                $survey_weight = floatval($_POST['survey_weight']);
511
                $max_score = 1;
512
513
                if (!$gradebook_link_id) {
514
                    GradebookUtils::add_resource_to_course_gradebook(
515
                        $values['category_id'],
516
                        $courseCode,
517
                        $gradebook_link_type,
518
                        $survey_id,
519
                        $title_gradebook,
520
                        $survey_weight,
521
                        $max_score,
522
                        $description_gradebook,
523
                        1,
524
                        $session_id
525
                    );
526
                } else {
527
                    GradebookUtils::updateResourceFromCourseGradebook(
528
                        $gradebook_link_id,
529
                        $courseCode,
530
                        $survey_weight
531
                    );
532
                }
533
            }
534
        } else {
535
            // Delete everything of the gradebook for this $linkId
536
            GradebookUtils::remove_resource_from_course_gradebook($gradebook_link_id);
537
        }
538
539
        return $return;
540
    }
541
542
    /**
543
     * This function stores a shared survey in the central database.
544
     *
545
     * @param array $values
546
     * @return array $return the type of return message that has to be displayed and the message in it
547
     *
548
     * @author Patrick Cool <[email protected]>, Ghent University
549
     * @version February 2007
550
     */
551
    public function store_shared_survey($values)
552
    {
553
        $_user = api_get_user_info();
554
        $_course = api_get_course_info();
555
556
        // Table definitions
557
        $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
558
559
        if (!$values['survey_id'] ||
560
            !is_numeric($values['survey_id']) ||
561
            $values['survey_share']['survey_share'] == 'true'
562
        ) {
563
            $sql = "INSERT INTO $table_survey (code, title, subtitle, author, lang, template, intro, surveythanks, creation_date, course_code) VALUES (
564
                    '".Database::escape_string($values['survey_code'])."',
565
                    '".Database::escape_string($values['survey_title'])."',
566
                    '".Database::escape_string($values['survey_subtitle'])."',
567
                    '".intval($_user['user_id'])."',
568
                    '".Database::escape_string($values['survey_language'])."',
569
                    '".Database::escape_string('template')."',
570
                    '".Database::escape_string($values['survey_introduction'])."',
571
                    '".Database::escape_string($values['survey_thanks'])."',
572
                    '".api_get_utc_datetime()."',
573
                    '".$_course['id']."')";
574
            Database::query($sql);
575
            $return = Database::insert_id();
576
577
            $sql = "UPDATE $table_survey SET survey_id = $return WHERE iid = $return";
578
            Database::query($sql);
579
        } else {
580
            $sql = "UPDATE $table_survey SET
581
                        code 			= '".Database::escape_string($values['survey_code'])."',
582
                        title 			= '".Database::escape_string($values['survey_title'])."',
583
                        subtitle 		= '".Database::escape_string($values['survey_subtitle'])."',
584
                        author 			= '".intval($_user['user_id'])."',
585
                        lang 			= '".Database::escape_string($values['survey_language'])."',
586
                        template 		= '".Database::escape_string('template')."',
587
                        intro			= '".Database::escape_string($values['survey_introduction'])."',
588
                        surveythanks	= '".Database::escape_string($values['survey_thanks'])."'
589
					WHERE survey_id = '".Database::escape_string($values['survey_share']['survey_share'])."'";
590
            Database::query($sql);
591
            $return = $values['survey_share']['survey_share'];
592
        }
593
594
        return $return;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $return also could return the type string which is incompatible with the documented return type array.
Loading history...
595
    }
596
597
    /**
598
     * This function deletes a survey (and also all the question in that survey
599
     *
600
     * @param int $survey_id id of the survey that has to be deleted
601
     * @param bool $shared
602
     * @param int $course_id
603
     * @return true
604
     *
605
     * @author Patrick Cool <[email protected]>, Ghent University
606
     * @version January 2007
607
     */
608
    public static function delete_survey($survey_id, $shared = false, $course_id = 0)
609
    {
610
        // Database table definitions
611
        if (empty($course_id)) {
612
            $course_id = api_get_course_int_id();
613
        }
614
615
        $survey_id = intval($survey_id);
616
617
        if (empty($survey_id)) {
618
            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 true.
Loading history...
619
        }
620
621
        $course_info = api_get_course_info_by_id($course_id);
622
        $course_id = $course_info['real_id'];
623
624
        $table_survey = Database::get_course_table(TABLE_SURVEY);
625
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
626
627
        if ($shared) {
628
            $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
629
            // Deleting the survey
630
            $sql = "DELETE FROM $table_survey
631
                    WHERE survey_id='".$survey_id."'";
632
            Database::query($sql);
633
        } else {
634
            $sql = "DELETE FROM $table_survey
635
                    WHERE c_id = $course_id AND survey_id='".$survey_id."'";
636
            Database::query($sql);
637
        }
638
639
        // Deleting groups of this survey
640
        $sql = "DELETE FROM $table_survey_question_group
641
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
642
        Database::query($sql);
643
644
        // Deleting the questions of the survey
645
        self::delete_all_survey_questions($survey_id, $shared);
646
647
        // Update into item_property (delete)
648
        api_item_property_update(
649
            $course_info,
650
            TOOL_SURVEY,
651
            $survey_id,
652
            'SurveyDeleted',
653
            api_get_user_id()
654
        );
655
656
        return true;
657
    }
658
659
    /**
660
     * @param int $survey_id
661
     * @param int $new_survey_id
662
     * @param int $targetCourseId
663
     *
664
     * @return bool
665
     */
666
    public static function copy_survey(
667
        $survey_id,
668
        $new_survey_id = null,
669
        $targetCourseId = null
670
    ) {
671
        $course_id = api_get_course_int_id();
672
        if (!$targetCourseId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $targetCourseId of type null|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null 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...
673
            $targetCourseId = $course_id;
674
        }
675
676
        // Database table definitions
677
        $table_survey = Database::get_course_table(TABLE_SURVEY);
678
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
679
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
680
        $table_survey_options = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
681
        $survey_id = intval($survey_id);
682
683
        // Get groups
684
        $survey_data = self::get_survey($survey_id, 0, null, true);
685
        if (empty($survey_data)) {
686
            return true;
687
        }
688
689
        if (empty($new_survey_id)) {
690
            $params = $survey_data;
691
            $params['code'] = self::generate_unique_code($params['code']);
692
            $params['c_id'] = $targetCourseId;
693
            unset($params['survey_id']);
694
            $params['session_id'] = api_get_session_id();
695
            $params['title'] = $params['title'].' '.get_lang('Copy');
696
            unset($params['iid']);
697
            Database::insert($table_survey, $params);
698
            $new_survey_id = Database::insert_id();
699
700
            if ($new_survey_id) {
701
                $sql = "UPDATE $table_survey SET survey_id = $new_survey_id
702
                        WHERE iid = $new_survey_id";
703
                Database::query($sql);
704
705
                // Insert into item_property
706
                api_item_property_update(
707
                    api_get_course_info(),
708
                    TOOL_SURVEY,
709
                    $new_survey_id,
710
                    'SurveyAdded',
711
                    api_get_user_id()
712
                );
713
            }
714
        } else {
715
            $new_survey_id = intval($new_survey_id);
716
        }
717
718
        $sql = "SELECT * FROM $table_survey_question_group
719
                WHERE c_id = $course_id AND  survey_id='".$survey_id."'";
720
        $res = Database::query($sql);
721
        while ($row = Database::fetch_array($res, 'ASSOC')) {
722
            $params = [
723
                'c_id' => $targetCourseId,
724
                'name' => $row['name'],
725
                'description' => $row['description'],
726
                'survey_id' => $new_survey_id
727
            ];
728
            $insertId = Database::insert($table_survey_question_group, $params);
729
730
            $sql = "UPDATE $table_survey_question_group SET id = iid
731
                    WHERE iid = $insertId";
732
            Database::query($sql);
733
734
            $group_id[$row['id']] = $insertId;
735
        }
736
737
        // Get questions
738
        $sql = "SELECT * FROM $table_survey_question
739
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
740
        $res = Database::query($sql);
741
        while ($row = Database::fetch_array($res, 'ASSOC')) {
742
            $params = [
743
                'c_id' => $targetCourseId,
744
                'survey_id' => $new_survey_id,
745
                'survey_question' => $row['survey_question'],
746
                'survey_question_comment' => $row['survey_question_comment'],
747
                'type' => $row['type'],
748
                'display' => $row['display'],
749
                'sort' => $row['sort'],
750
                'shared_question_id' => $row['shared_question_id'],
751
                'max_value' => $row['max_value'],
752
                'survey_group_pri' => $row['survey_group_pri'],
753
                'survey_group_sec1' => $row['survey_group_sec1'],
754
                'survey_group_sec2' => $row['survey_group_sec2']
755
            ];
756
            $insertId = Database::insert($table_survey_question, $params);
757
            $sql = "UPDATE $table_survey_question SET question_id = iid WHERE iid = $insertId";
758
            Database::query($sql);
759
760
            $question_id[$row['question_id']] = $insertId;
761
        }
762
763
        // Get questions options
764
        $sql = "SELECT * FROM $table_survey_options
765
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
766
767
        $res = Database::query($sql);
768
        while ($row = Database::fetch_array($res, 'ASSOC')) {
769
            $params = [
770
                'c_id' => $targetCourseId,
771
                'question_id' => $question_id[$row['question_id']],
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_id does not seem to be defined for all execution paths leading up to this point.
Loading history...
772
                'survey_id' => $new_survey_id,
773
                'option_text' => $row['option_text'],
774
                'sort' => $row['sort'],
775
                'value' => $row['value']
776
            ];
777
            $insertId = Database::insert($table_survey_options, $params);
778
779
            $sql = "UPDATE $table_survey_options SET question_option_id = $insertId
780
                    WHERE iid = $insertId";
781
            Database::query($sql);
782
        }
783
784
        return $new_survey_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $new_survey_id returns the type integer|string which is incompatible with the documented return type boolean.
Loading history...
785
    }
786
787
    /**
788
     * This function duplicates a survey (and also all the question in that survey
789
     *
790
     * @param int $survey_id id of the survey that has to be duplicated
791
     * @param int $courseId id of the course which survey has to be duplicated
792
     * @return true
793
     *
794
     * @author Eric Marguin <[email protected]>, Elixir Interactive
795
     * @version October 2007
796
     */
797
    public static function empty_survey($survey_id, $courseId = 0)
798
    {
799
        // Database table definitions
800
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
801
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
802
        $table_survey = Database::get_course_table(TABLE_SURVEY);
803
804
        $courseId = (int) $courseId;
805
        $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
806
807
        $datas = self::get_survey($survey_id);
808
        $session_where = '';
809
        if (api_get_session_id() != 0) {
810
            $session_where = ' AND session_id = "'.api_get_session_id().'" ';
811
        }
812
813
        $sql = 'DELETE FROM '.$table_survey_invitation.'
814
		        WHERE
815
		            c_id = '.$courseId.' AND
816
		            survey_code = "'.Database::escape_string($datas['code']).'" '.$session_where.' ';
817
        Database::query($sql);
818
819
        $sql = 'DELETE FROM '.$table_survey_answer.'
820
		        WHERE c_id = '.$courseId.' AND survey_id='.intval($survey_id);
821
        Database::query($sql);
822
823
        $sql = 'UPDATE '.$table_survey.' SET invited=0, answered=0
824
		        WHERE c_id = '.$courseId.' AND survey_id='.intval($survey_id);
825
        Database::query($sql);
826
827
        return true;
828
    }
829
830
    /**
831
     * This function recalculates the number of people who have taken the survey (=filled at least one question)
832
     *
833
     * @param array $survey_data
834
     * @param array $user
835
     * @param string $survey_code
836
     * @return bool
837
     *
838
     * @author Patrick Cool <[email protected]>, Ghent University
839
     * @version February 2007
840
     */
841
    public static function update_survey_answered($survey_data, $user, $survey_code)
842
    {
843
        // Database table definitions
844
        $table_survey = Database::get_course_table(TABLE_SURVEY);
845
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
846
847
        $survey_id = $survey_data['survey_id'];
848
        $course_id = $survey_data['c_id'];
849
        $session_id = $survey_data['session_id'];
850
851
        // Getting a list with all the people who have filled the survey
852
        $people_filled = self::get_people_who_filled_survey($survey_id, false, $course_id);
853
854
        $number = intval(count($people_filled));
855
856
        // Storing this value in the survey table
857
        $sql = "UPDATE $table_survey
858
		        SET answered = $number
859
		        WHERE
860
                    c_id = $course_id AND
861
		            survey_id = ".intval($survey_id);
862
        Database::query($sql);
863
864
        $allow = api_get_configuration_value('survey_answered_at_field');
865
        // Requires DB change:
866
        // ALTER TABLE c_survey_invitation ADD answered_at DATETIME DEFAULT NULL;
867
        $answeredAt = '';
868
        if ($allow) {
869
            $answeredAt = "answered_at = '".api_get_utc_datetime()."',";
870
        }
871
872
        // Storing that the user has finished the survey.
873
        $sql = "UPDATE $table_survey_invitation
874
            SET $answeredAt
875
                answered = 1
876
                WHERE
877
                    c_id = $course_id AND
878
                    session_id = $session_id AND
879
                    user ='".Database::escape_string($user)."' AND
880
                    survey_code='".Database::escape_string($survey_code)."'";
881
        Database::query($sql);
882
    }
883
884
    /***
885
     * SURVEY QUESTION FUNCTIONS
886
     */
887
888
    /**
889
     * This function return the "icon" of the question type
890
     *
891
     * @author Patrick Cool <[email protected]>, Ghent University
892
     * @version February 2007
893
     */
894
    public static function icon_question($type)
895
    {
896
        // the possible question types
897
        $possible_types = [
898
            'personality',
899
            'yesno',
900
            'multiplechoice',
901
            'multipleresponse',
902
            'open',
903
            'dropdown',
904
            'comment',
905
            'pagebreak',
906
            'percentage',
907
            'score',
908
        ];
909
910
        // the images array
911
        $icon_question = [
912
            'yesno' => 'yesno.png',
913
            'personality' => 'yesno.png',
914
            'multiplechoice' => 'mcua.png',
915
            'multipleresponse' => 'mcma.png',
916
            'open' => 'open_answer.png',
917
            'dropdown' => 'dropdown.png',
918
            'percentage' => 'percentagequestion.png',
919
            'score' => 'scorequestion.png',
920
            'comment' => 'commentquestion.png',
921
            'pagebreak' => 'page_end.png',
922
        ];
923
924
        if (in_array($type, $possible_types)) {
925
            return $icon_question[$type];
926
        } else {
927
            return false;
928
        }
929
    }
930
931
    /**
932
     * This function retrieves all the information of a question
933
     *
934
     * @param integer $question_id the id of the question
935
     * @param bool $shared
936
     * @return array
937
     *
938
     * @author Patrick Cool <[email protected]>, Ghent University
939
     * @version January 2007
940
     *
941
     * @todo one sql call should do the trick
942
     */
943
    public static function get_question($question_id, $shared = false)
944
    {
945
        // Table definitions
946
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
947
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
948
        $course_id = api_get_course_int_id();
949
950
        $sql = "SELECT * FROM $tbl_survey_question
951
                WHERE c_id = $course_id AND question_id='".intval($question_id)."'
952
                ORDER BY `sort` ";
953
954
        $sqlOption = "  SELECT * FROM $table_survey_question_option
955
                        WHERE c_id = $course_id AND question_id='".intval($question_id)."'
956
                        ORDER BY `sort` ";
957
958
        if ($shared) {
959
            $tbl_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
960
            $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
961
962
            $sql = "SELECT * FROM $tbl_survey_question
963
                    WHERE question_id='".intval($question_id)."'
964
                    ORDER BY `sort` ";
965
            $sqlOption = "SELECT * FROM $table_survey_question_option
966
                          WHERE question_id='".intval($question_id)."'
967
                          ORDER BY `sort` ";
968
        }
969
970
        // Getting the information of the question
971
972
        $result = Database::query($sql);
973
        $row = Database::fetch_array($result, 'ASSOC');
974
975
        $return['survey_id'] = $row['survey_id'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
976
        $return['question_id'] = $row['question_id'];
977
        $return['type'] = $row['type'];
978
        $return['question'] = $row['survey_question'];
979
        $return['horizontalvertical'] = $row['display'];
980
        $return['shared_question_id'] = $row['shared_question_id'];
981
        $return['maximum_score'] = $row['max_value'];
982
        $return['is_required'] = api_get_configuration_value('allow_required_survey_questions')
983
            ? $row['is_required']
984
            : false;
985
986
        if ($row['survey_group_pri'] != 0) {
987
            $return['assigned'] = $row['survey_group_pri'];
988
            $return['choose'] = 1;
989
        } else {
990
            $return['assigned1'] = $row['survey_group_sec1'];
991
            $return['assigned2'] = $row['survey_group_sec2'];
992
            $return['choose'] = 2;
993
        }
994
995
        // Getting the information of the question options
996
997
        $result = Database::query($sqlOption);
998
        while ($row = Database::fetch_array($result, 'ASSOC')) {
999
            /** @todo this should be renamed to options instead of answers */
1000
            $return['answers'][] = $row['option_text'];
1001
            $return['values'][] = $row['value'];
1002
1003
            /** @todo this can be done more elegantly (used in reporting) */
1004
            $return['answersid'][] = $row['question_option_id'];
1005
        }
1006
1007
        return $return;
1008
    }
1009
1010
    /**
1011
     * This function gets all the question of any given survey
1012
     *
1013
     * @param integer $survey_id the id of the survey
1014
     * @param int $course_id
1015
     * @return array containing all the questions of the survey
1016
     *
1017
     * @author Patrick Cool <[email protected]>, Ghent University
1018
     * @version February 2007
1019
     *
1020
     * @todo one sql call should do the trick
1021
     */
1022
    public static function get_questions($survey_id, $course_id = 0)
1023
    {
1024
        // Table definitions
1025
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1026
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1027
1028
        $course_id = (int) $course_id;
1029
        if (empty($course_id)) {
1030
            $course_id = api_get_course_int_id();
1031
        }
1032
1033
        // Getting the information of the question
1034
        $sql = "SELECT * FROM $tbl_survey_question
1035
		        WHERE c_id = $course_id AND survey_id='".intval($survey_id)."'";
1036
        $result = Database::query($sql);
1037
        $return = [];
1038
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1039
            $return[$row['question_id']]['survey_id'] = $row['survey_id'];
1040
            $return[$row['question_id']]['question_id'] = $row['question_id'];
1041
            $return[$row['question_id']]['type'] = $row['type'];
1042
            $return[$row['question_id']]['question'] = $row['survey_question'];
1043
            $return[$row['question_id']]['horizontalvertical'] = $row['display'];
1044
            $return[$row['question_id']]['maximum_score'] = $row['max_value'];
1045
            $return[$row['question_id']]['sort'] = $row['sort'];
1046
        }
1047
1048
        // Getting the information of the question options
1049
        $sql = "SELECT * FROM $table_survey_question_option
1050
		        WHERE c_id = $course_id AND survey_id='".intval($survey_id)."'";
1051
        $result = Database::query($sql);
1052
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1053
            $return[$row['question_id']]['answers'][] = $row['option_text'];
1054
        }
1055
1056
        return $return;
1057
    }
1058
1059
    /**
1060
     * This function saves a question in the database.
1061
     * This can be either an update of an existing survey or storing a new survey
1062
     * @param array $survey_data
1063
     * @param array $form_content all the information of the form
1064
     *
1065
     * @author Patrick Cool <[email protected]>, Ghent University
1066
     * @version January 2007
1067
     */
1068
    public static function save_question($survey_data, $form_content)
1069
    {
1070
        $return_message = '';
1071
        if (strlen($form_content['question']) > 1) {
1072
            // Checks length of the question
1073
            $empty_answer = false;
1074
1075
            if ($survey_data['survey_type'] == 1) {
1076
                if (empty($form_content['choose'])) {
1077
                    $return_message = 'PleaseChooseACondition';
1078
1079
                    return $return_message;
1080
                }
1081
1082
                if (($form_content['choose'] == 2) &&
1083
                    ($form_content['assigned1'] == $form_content['assigned2'])
1084
                ) {
1085
                    $return_message = 'ChooseDifferentCategories';
1086
1087
                    return $return_message;
1088
                }
1089
            }
1090
1091
            if ($form_content['type'] != 'percentage') {
1092
                if (isset($form_content['answers'])) {
1093
                    for ($i = 0; $i < count($form_content['answers']); $i++) {
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...
1094
                        if (strlen($form_content['answers'][$i]) < 1) {
1095
                            $empty_answer = true;
1096
                            break;
1097
                        }
1098
                    }
1099
                }
1100
            }
1101
1102
            if ($form_content['type'] == 'score') {
1103
                if (strlen($form_content['maximum_score']) < 1) {
1104
                    $empty_answer = true;
1105
                }
1106
            }
1107
            $additional = [];
1108
            $course_id = api_get_course_int_id();
1109
1110
            if (!$empty_answer) {
1111
                // Table definitions
1112
                $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1113
1114
                // Getting all the information of the survey
1115
                $survey_data = self::get_survey($form_content['survey_id']);
1116
1117
                // Storing the question in the shared database
1118
                if (is_numeric($survey_data['survey_share']) && $survey_data['survey_share'] != 0) {
1119
                    $shared_question_id = self::save_shared_question($form_content, $survey_data);
0 ignored issues
show
Bug Best Practice introduced by
The method SurveyManager::save_shared_question() is not static, but was called statically. ( Ignorable by Annotation )

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

1119
                    /** @scrutinizer ignore-call */ 
1120
                    $shared_question_id = self::save_shared_question($form_content, $survey_data);
Loading history...
1120
                    $form_content['shared_question_id'] = $shared_question_id;
1121
                }
1122
1123
                // Storing a new question
1124
                if ($form_content['question_id'] == '' || !is_numeric($form_content['question_id'])) {
1125
                    // Finding the max sort order of the questions in the given survey
1126
                    $sql = "SELECT max(sort) AS max_sort
1127
					        FROM $tbl_survey_question
1128
                            WHERE c_id = $course_id AND survey_id='".intval($form_content['survey_id'])."'";
1129
                    $result = Database::query($sql);
1130
                    $row = Database::fetch_array($result, 'ASSOC');
1131
                    $max_sort = $row['max_sort'];
1132
1133
                    // Some variables defined for survey-test type
1134
                    $extraParams = [];
1135
                    if (isset($_POST['choose'])) {
1136
                        if ($_POST['choose'] == 1) {
1137
                            $extraParams['survey_group_pri'] = $_POST['assigned'];
1138
                        } elseif ($_POST['choose'] == 2) {
1139
                            $extraParams['survey_group_sec1'] = $_POST['assigned1'];
1140
                            $extraParams['survey_group_sec2'] = $_POST['assigned2'];
1141
                        }
1142
                    }
1143
1144
                    $questionComment = isset($form_content['question_comment'])
1145
                        ? $form_content['question_comment']
1146
                        : '';
1147
                    $maxScore = isset($form_content['maximum_score']) ? $form_content['maximum_score'] : '';
1148
                    $display = isset($form_content['horizontalvertical']) ? $form_content['horizontalvertical'] : '';
1149
1150
                    $params = [
1151
                        'c_id' => $course_id,
1152
                        'survey_id' => $form_content['survey_id'],
1153
                        'survey_question' => $form_content['question'],
1154
                        'survey_question_comment' => $questionComment,
1155
                        'type' => $form_content['type'],
1156
                        'display' => $display,
1157
                        'sort' => $max_sort + 1,
1158
                        'shared_question_id' => $form_content['shared_question_id'],
1159
                        'max_value' => $maxScore,
1160
                    ];
1161
1162
                    if (api_get_configuration_value('allow_required_survey_questions')) {
1163
                        $params['is_required'] = isset($form_content['is_required']);
1164
                    }
1165
1166
                    $params = array_merge($params, $extraParams);
1167
                    $question_id = Database::insert($tbl_survey_question, $params);
1168
                    if ($question_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $question_id 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...
1169
                        $sql = "UPDATE $tbl_survey_question SET question_id = $question_id
1170
                                WHERE iid = $question_id";
1171
                        Database::query($sql);
1172
1173
                        $form_content['question_id'] = $question_id;
1174
                        $return_message = 'QuestionAdded';
1175
                    }
1176
                } else {
1177
                    // Updating an existing question
1178
                    $extraParams = [];
1179
                    if (isset($_POST['choose'])) {
1180
                        if ($_POST['choose'] == 1) {
1181
                            $extraParams['survey_group_pri'] = $_POST['assigned'];
1182
                            $extraParams['survey_group_sec1'] = 0;
1183
                            $extraParams['survey_group_sec2'] = 0;
1184
                        } elseif ($_POST['choose'] == 2) {
1185
                            $extraParams['survey_group_pri'] = 0;
1186
                            $extraParams['survey_group_sec1'] = $_POST['assigned1'];
1187
                            $extraParams['survey_group_sec2'] = $_POST['assigned2'];
1188
                        }
1189
                    }
1190
1191
                    $maxScore = isset($form_content['maximum_score']) ? $form_content['maximum_score'] : null;
1192
                    $questionComment = isset($form_content['question_comment'])
1193
                        ? $form_content['question_comment']
1194
                        : null;
1195
1196
                    // Adding the question to the survey_question table
1197
                    $params = [
1198
                        'survey_question' => $form_content['question'],
1199
                        'survey_question_comment' => $questionComment,
1200
                        'display' => $form_content['horizontalvertical'],
1201
                    ];
1202
1203
                    if (api_get_configuration_value('allow_required_survey_questions')) {
1204
                        $params['is_required'] = isset($form_content['is_required']);
1205
                    }
1206
1207
                    $params = array_merge($params, $extraParams);
1208
1209
                    Database::update(
1210
                        $tbl_survey_question,
1211
                        $params,
1212
                        [
1213
                            'c_id = ? AND question_id = ?' => [
1214
                                $course_id,
1215
                                $form_content['question_id'],
1216
                            ],
1217
                        ]
1218
                    );
1219
1220
                    $return_message = 'QuestionUpdated';
1221
                }
1222
1223
                if (!empty($form_content['survey_id'])) {
1224
                    //Updating survey
1225
                    api_item_property_update(
1226
                        api_get_course_info(),
1227
                        TOOL_SURVEY,
1228
                        $form_content['survey_id'],
1229
                        'SurveyUpdated',
1230
                        api_get_user_id()
1231
                    );
1232
                }
1233
1234
                // Storing the options of the question
1235
                self::save_question_options($form_content, $survey_data);
1236
            } else {
1237
                $return_message = 'PleasFillAllAnswer';
1238
            }
1239
        } else {
1240
            $return_message = 'PleaseEnterAQuestion';
1241
        }
1242
1243
        if (!empty($return_message)) {
1244
            Display::addFlash(Display::return_message(get_lang($return_message)));
1245
        }
1246
1247
        return $return_message;
1248
    }
1249
1250
    /**
1251
     * This function saves the question in the shared database
1252
     *
1253
     * @param array $form_content all the information of the form
1254
     * @param array $survey_data all the information of the survey
1255
     *
1256
     * @author Patrick Cool <[email protected]>, Ghent University
1257
     * @version February 2007
1258
     * @return int
1259
     *
1260
     * @todo editing of a shared question
1261
     */
1262
    public function save_shared_question($form_content, $survey_data)
1263
    {
1264
        $_course = api_get_course_info();
1265
1266
        // Table definitions
1267
        $tbl_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1268
1269
        // Storing a new question
1270
        if ($form_content['shared_question_id'] == '' ||
1271
            !is_numeric($form_content['shared_question_id'])
1272
        ) {
1273
            // Finding the max sort order of the questions in the given survey
1274
            $sql = "SELECT max(sort) AS max_sort FROM $tbl_survey_question
1275
                    WHERE survey_id='".intval($survey_data['survey_share'])."'
1276
                    AND code='".Database::escape_string($_course['id'])."'";
1277
            $result = Database::query($sql);
1278
            $row = Database::fetch_array($result, 'ASSOC');
1279
            $max_sort = $row['max_sort'];
1280
1281
            // Adding the question to the survey_question table
1282
            $sql = "INSERT INTO $tbl_survey_question (survey_id, survey_question, survey_question_comment, type, display, sort, code) VALUES (
1283
                    '".Database::escape_string($survey_data['survey_share'])."',
1284
                    '".Database::escape_string($form_content['question'])."',
1285
                    '".Database::escape_string($form_content['question_comment'])."',
1286
                    '".Database::escape_string($form_content['type'])."',
1287
                    '".Database::escape_string($form_content['horizontalvertical'])."',
1288
                    '".Database::escape_string($max_sort + 1)."',
1289
                    '".Database::escape_string($_course['id'])."')";
1290
            Database::query($sql);
1291
            $shared_question_id = Database::insert_id();
1292
        } else {
1293
            // Updating an existing question
1294
            // adding the question to the survey_question table
1295
            $sql = "UPDATE $tbl_survey_question SET
1296
                        survey_question = '".Database::escape_string($form_content['question'])."',
1297
                        survey_question_comment = '".Database::escape_string($form_content['question_comment'])."',
1298
                        display = '".Database::escape_string($form_content['horizontalvertical'])."'
1299
                    WHERE
1300
                        question_id = '".intval($form_content['shared_question_id'])."' AND
1301
                        code = '".Database::escape_string($_course['id'])."'";
1302
            Database::query($sql);
1303
            $shared_question_id = $form_content['shared_question_id'];
1304
        }
1305
1306
        return $shared_question_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $shared_question_id also could return the type string which is incompatible with the documented return type integer.
Loading history...
1307
    }
1308
1309
    /**
1310
     * This functions moves a question of a survey up or down
1311
     *
1312
     * @param string $direction
1313
     * @param integer $survey_question_id
1314
     * @param integer $survey_id
1315
     *
1316
     * @author Patrick Cool <[email protected]>, Ghent University
1317
     * @version January 2007
1318
     */
1319
    public static function move_survey_question(
1320
        $direction,
1321
        $survey_question_id,
1322
        $survey_id
1323
    ) {
1324
        // Table definition
1325
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1326
        $course_id = api_get_course_int_id();
1327
1328
        if ($direction == 'moveup') {
1329
            $sort = 'DESC';
1330
        }
1331
        if ($direction == 'movedown') {
1332
            $sort = 'ASC';
1333
        }
1334
1335
        // Finding the two questions that needs to be swapped
1336
        $sql = "SELECT * FROM $table_survey_question
1337
		        WHERE c_id = $course_id AND survey_id='".Database::escape_string($survey_id)."'
1338
		        ORDER BY sort $sort";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sort does not seem to be defined for all execution paths leading up to this point.
Loading history...
1339
        $result = Database::query($sql);
1340
        $found = false;
1341
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1342
            if ($found) {
1343
                $question_id_two = $row['question_id'];
1344
                $question_sort_two = $row['sort'];
1345
                $found = false;
1346
            }
1347
            if ($row['question_id'] == $survey_question_id) {
1348
                $found = true;
1349
                $question_id_one = $row['question_id'];
1350
                $question_sort_one = $row['sort'];
1351
            }
1352
        }
1353
1354
        $sql1 = "UPDATE $table_survey_question 
1355
                SET sort = '".Database::escape_string($question_sort_two)."'
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_sort_two does not seem to be defined for all execution paths leading up to this point.
Loading history...
1356
		        WHERE c_id = $course_id AND  question_id='".intval($question_id_one)."'";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_id_one does not seem to be defined for all execution paths leading up to this point.
Loading history...
1357
        Database::query($sql1);
1358
        $sql2 = "UPDATE $table_survey_question 
1359
                SET sort = '".Database::escape_string($question_sort_one)."'
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_sort_one does not seem to be defined for all execution paths leading up to this point.
Loading history...
1360
		        WHERE c_id = $course_id AND question_id='".intval($question_id_two)."'";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_id_two does not seem to be defined for all execution paths leading up to this point.
Loading history...
1361
        Database::query($sql2);
1362
    }
1363
1364
    /**
1365
     * This function deletes all the questions of a given survey
1366
     * This function is normally only called when a survey is deleted
1367
     *
1368
     * @param int $survey_id the id of the survey that has to be deleted
1369
     * @return true
1370
     *
1371
     * @author Patrick Cool <[email protected]>, Ghent University
1372
     * @version January 2007
1373
     */
1374
    public static function delete_all_survey_questions($survey_id, $shared = false)
1375
    {
1376
        $course_id = api_get_course_int_id();
1377
1378
        // Table definitions
1379
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1380
        $course_condition = " c_id = $course_id AND ";
1381
        if ($shared) {
1382
            $course_condition = '';
1383
            $table_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1384
        }
1385
1386
        $sql = "DELETE FROM $table_survey_question
1387
		        WHERE $course_condition survey_id='".intval($survey_id)."'";
1388
1389
        // Deleting the survey questions
1390
        Database::query($sql);
1391
1392
        // Deleting all the options of the questions of the survey
1393
        self::delete_all_survey_questions_options($survey_id, $shared);
1394
1395
        // Deleting all the answers on this survey
1396
        self::delete_all_survey_answers($survey_id);
1397
    }
1398
1399
    /**
1400
     * This function deletes a survey question and all its options
1401
     *
1402
     * @param int $survey_id the id of the survey
1403
     * @param int $question_id the id of the question
1404
     * @param bool $shared
1405
     *
1406
     * @todo also delete the answers to this question
1407
     *
1408
     * @author Patrick Cool <[email protected]>, Ghent University
1409
     * @version March 2007
1410
     */
1411
    public static function delete_survey_question($survey_id, $question_id, $shared = false)
1412
    {
1413
        $course_id = api_get_course_int_id();
1414
        // Table definitions
1415
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1416
        if ($shared) {
1417
            self::delete_shared_survey_question($survey_id, $question_id);
1418
        }
1419
1420
        // Deleting the survey questions
1421
        $sql = "DELETE FROM $table_survey_question
1422
		        WHERE
1423
		            c_id = $course_id AND
1424
		            survey_id='".intval($survey_id)."' AND
1425
		            question_id='".intval($question_id)."'";
1426
        Database::query($sql);
1427
1428
        // Deleting the options of the question of the survey
1429
        self::delete_survey_question_option($survey_id, $question_id, $shared);
1430
    }
1431
1432
    /**
1433
     * This function deletes a shared survey question from the main database and all its options
1434
     *
1435
     * @param int $question_id the id of the question
1436
     *
1437
     * @todo delete all the options of this question
1438
     *
1439
     * @author Patrick Cool <[email protected]>, Ghent University
1440
     * @version March 2007
1441
     */
1442
    public static function delete_shared_survey_question($survey_id, $question_id)
1443
    {
1444
        // Table definitions
1445
        $table_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1446
        $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1447
1448
        // First we have to get the shared_question_id
1449
        $question_data = self::get_question($question_id);
1450
1451
        // Deleting the survey questions
1452
        $sql = "DELETE FROM $table_survey_question
1453
		        WHERE question_id='".intval($question_data['shared_question_id'])."'";
1454
        Database::query($sql);
1455
1456
        // Deleting the options of the question of the survey question
1457
        $sql = "DELETE FROM $table_survey_question_option
1458
		        WHERE question_id='".intval($question_data['shared_question_id'])."'";
1459
        Database::query($sql);
1460
    }
1461
1462
    /**
1463
     * This function stores the options of the questions in the table
1464
     *
1465
     * @param array $form_content
1466
     * @author Patrick Cool <[email protected]>, Ghent University
1467
     * @version January 2007
1468
     *
1469
     * @todo writing the update statement when editing a question
1470
     */
1471
    public static function save_question_options($form_content, $survey_data)
1472
    {
1473
        $course_id = api_get_course_int_id();
1474
        // A percentage question type has options 1 -> 100
1475
        if ($form_content['type'] == 'percentage') {
1476
            for ($i = 1; $i < 101; $i++) {
1477
                $form_content['answers'][] = $i;
1478
            }
1479
        }
1480
1481
        if (is_numeric($survey_data['survey_share']) && $survey_data['survey_share'] != 0) {
1482
            self::save_shared_question_options($form_content, $survey_data);
0 ignored issues
show
Bug Best Practice introduced by
The method SurveyManager::save_shared_question_options() is not static, but was called statically. ( Ignorable by Annotation )

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

1482
            self::/** @scrutinizer ignore-call */ 
1483
                  save_shared_question_options($form_content, $survey_data);
Loading history...
1483
        }
1484
1485
        // Table definition
1486
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1487
1488
        // We are editing a question so we first have to remove all the existing options from the database
1489
        if (is_numeric($form_content['question_id'])) {
1490
            $sql = "DELETE FROM $table_survey_question_option
1491
			        WHERE c_id = $course_id AND question_id = '".intval($form_content['question_id'])."'";
1492
            Database::query($sql);
1493
        }
1494
1495
        $counter = 1;
1496
        if (isset($form_content['answers']) && is_array($form_content['answers'])) {
1497
            for ($i = 0; $i < count($form_content['answers']); $i++) {
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...
1498
                $values = isset($form_content['values']) ? $form_content['values'][$i] : '';
1499
1500
                $params = [
1501
                    'c_id' => $course_id,
1502
                    'question_id' => $form_content['question_id'],
1503
                    'survey_id' => $form_content['survey_id'],
1504
                    'option_text' => $form_content['answers'][$i],
1505
                    'value' => $values,
1506
                    'sort' => $counter,
1507
                ];
1508
                $insertId = Database::insert($table_survey_question_option, $params);
1509
                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...
1510
                    $sql = "UPDATE $table_survey_question_option
1511
                            SET question_option_id = $insertId
1512
                            WHERE iid = $insertId";
1513
                    Database::query($sql);
1514
1515
                    $counter++;
1516
                }
1517
            }
1518
        }
1519
    }
1520
1521
    /**
1522
     * This function stores the options of the questions in the shared table
1523
     *
1524
     * @param array $form_content
1525
     *
1526
     * @author Patrick Cool <[email protected]>, Ghent University
1527
     * @version February 2007
1528
     *
1529
     * @todo writing the update statement when editing a question
1530
     */
1531
    public function save_shared_question_options($form_content, $survey_data)
1532
    {
1533
        if (is_array($form_content) && is_array($form_content['answers'])) {
1534
            // Table definition
1535
            $table = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1536
1537
            // We are editing a question so we first have to remove all the existing options from the database
1538
            $sql = "DELETE FROM $table
1539
                    WHERE question_id = '".Database::escape_string($form_content['shared_question_id'])."'";
0 ignored issues
show
Bug introduced by
It seems like $form_content['shared_question_id'] can also be of type array; however, parameter $string of Database::escape_string() does only seem to accept string, 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

1539
                    WHERE question_id = '".Database::escape_string(/** @scrutinizer ignore-type */ $form_content['shared_question_id'])."'";
Loading history...
1540
            Database::query($sql);
1541
1542
            $counter = 1;
1543
            foreach ($form_content['answers'] as & $answer) {
1544
                $params = [
1545
                    'question_id' => $form_content['shared_question_id'],
1546
                    'survey_id' => $survey_data['is_shared'],
1547
                    'option_text' => $answer,
1548
                    'sort' => $counter,
1549
                ];
1550
                Database::insert($table, $params);
1551
1552
                $counter++;
1553
            }
1554
        }
1555
    }
1556
1557
    /**
1558
     * This function deletes all the options of the questions of a given survey
1559
     * This function is normally only called when a survey is deleted
1560
     *
1561
     * @param $survey_id the id of the survey that has to be deleted
1562
     * @return true
1563
     *
1564
     * @author Patrick Cool <[email protected]>, Ghent University
1565
     * @version January 2007
1566
     */
1567
    public static function delete_all_survey_questions_options($survey_id, $shared = false)
1568
    {
1569
        // Table definitions
1570
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1571
        $course_id = api_get_course_int_id();
1572
        $course_condition = " c_id = $course_id AND ";
1573
        if ($shared) {
1574
            $course_condition = '';
1575
            $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1576
        }
1577
1578
        $sql = "DELETE FROM $table_survey_question_option
1579
                WHERE $course_condition survey_id='".intval($survey_id)."'";
1580
1581
        // Deleting the options of the survey questions
1582
        Database::query($sql);
1583
1584
        return true;
1585
    }
1586
1587
    /**
1588
     * This function deletes the options of a given question
1589
     *
1590
     * @param int $survey_id
1591
     * @param int $question_id
1592
     * @param bool $shared
1593
     *
1594
     * @return bool
1595
     *
1596
     * @author Patrick Cool <[email protected]>, Ghent University
1597
     * @author Julio Montoya
1598
     * @version March 2007
1599
     */
1600
    public static function delete_survey_question_option(
1601
        $survey_id,
1602
        $question_id,
1603
        $shared = false
1604
    ) {
1605
        $course_id = api_get_course_int_id();
1606
        $course_condition = " c_id = $course_id AND ";
1607
1608
        // Table definitions
1609
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1610
        if ($shared) {
1611
            $course_condition = '';
1612
            $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1613
        }
1614
1615
        // Deleting the options of the survey questions
1616
        $sql = "DELETE from $table_survey_question_option
1617
		        WHERE
1618
		            $course_condition survey_id='".intval($survey_id)."' AND
1619
		            question_id='".intval($question_id)."'";
1620
        Database::query($sql);
1621
1622
        return true;
1623
    }
1624
1625
    /**
1626
     * SURVEY ANSWERS FUNCTIONS
1627
     */
1628
1629
    /**
1630
     * This function deletes all the answers anyone has given on this survey
1631
     * This function is normally only called when a survey is deleted
1632
     *
1633
     * @param $survey_id the id of the survey that has to be deleted
1634
     * @return true
1635
     *
1636
     * @todo write the function
1637
     *
1638
     * @author Patrick Cool <[email protected]>, Ghent University
1639
     * @version January 2007,december 2008
1640
     */
1641
    public static function delete_all_survey_answers($survey_id)
1642
    {
1643
        $course_id = api_get_course_int_id();
1644
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1645
        $survey_id = intval($survey_id);
1646
        $sql = "DELETE FROM $table_survey_answer 
1647
                WHERE c_id = $course_id AND survey_id=$survey_id";
1648
        Database::query($sql);
1649
1650
        return true;
1651
    }
1652
1653
    /**
1654
     * @param int $user_id
1655
     * @param int $survey_id
1656
     * @param int $course_id
1657
     * @return bool
1658
     */
1659
    public static function is_user_filled_survey($user_id, $survey_id, $course_id)
1660
    {
1661
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1662
        $user_id = intval($user_id);
1663
        $course_id = intval($course_id);
1664
        $survey_id = intval($survey_id);
1665
1666
        $sql = "SELECT DISTINCT user 
1667
                FROM $table_survey_answer
1668
                WHERE
1669
                    c_id		= $course_id AND
1670
                    user		= $user_id AND
1671
                    survey_id	= $survey_id";
1672
        $result = Database::query($sql);
1673
        if (Database::num_rows($result)) {
1674
            return true;
1675
        }
1676
1677
        return false;
1678
    }
1679
1680
    /**
1681
     * This function gets all the persons who have filled the survey
1682
     *
1683
     * @param integer $survey_id
1684
     * @return array
1685
     *
1686
     * @author Patrick Cool <[email protected]>, Ghent University
1687
     * @version February 2007
1688
     */
1689
    public static function get_people_who_filled_survey(
1690
        $survey_id,
1691
        $all_user_info = false,
1692
        $course_id = null
1693
    ) {
1694
        // Database table definition
1695
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1696
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1697
1698
        // Variable initialisation
1699
        $return = [];
1700
1701
        if (empty($course_id)) {
1702
            $course_id = api_get_course_int_id();
1703
        } else {
1704
            $course_id = intval($course_id);
1705
        }
1706
1707
        if ($all_user_info) {
1708
            $order_clause = api_sort_by_first_name()
1709
                ? ' ORDER BY user.firstname, user.lastname'
1710
                : ' ORDER BY user.lastname, user.firstname';
1711
            $sql = "SELECT DISTINCT
1712
			            answered_user.user as invited_user, 
1713
			            user.firstname, 
1714
			            user.lastname, 
1715
			            user.user_id
1716
                    FROM $table_survey_answer answered_user
1717
                    LEFT JOIN $table_user as user ON answered_user.user = user.user_id
1718
                    WHERE
1719
                        answered_user.c_id = $course_id AND
1720
                        survey_id= '".Database::escape_string($survey_id)."' ".
1721
                $order_clause;
1722
        } else {
1723
            $sql = "SELECT DISTINCT user FROM $table_survey_answer
1724
			        WHERE c_id = $course_id AND survey_id= '".Database::escape_string($survey_id)."'  ";
1725
        }
1726
1727
        $res = Database::query($sql);
1728
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1729
            if ($all_user_info) {
1730
                $userInfo = api_get_user_info($row['user_id']);
1731
                $row['user_info'] = $userInfo;
1732
                $return[] = $row;
1733
            } else {
1734
                $return[] = $row['user'];
1735
            }
1736
        }
1737
1738
        return $return;
1739
    }
1740
1741
    /**
1742
     * @return bool
1743
     */
1744
    public static function survey_generation_hash_available()
1745
    {
1746
        if (extension_loaded('mcrypt')) {
1747
            return true;
1748
        }
1749
1750
        return false;
1751
    }
1752
1753
    /**
1754
     * @param int $survey_id
1755
     * @param int $course_id
1756
     * @param int $session_id
1757
     * @param int $group_id
1758
     * @return string
1759
     */
1760
    public static function generate_survey_hash($survey_id, $course_id, $session_id, $group_id)
1761
    {
1762
        $hash = hash('sha512', api_get_security_key().'_'.$course_id.'_'.$session_id.'_'.$group_id.'_'.$survey_id);
1763
1764
        return $hash;
1765
    }
1766
1767
    /**
1768
     * @param int $survey_id
1769
     * @param int $course_id
1770
     * @param int $session_id
1771
     * @param int $group_id
1772
     * @param string $hash
1773
     *
1774
     * @return bool
1775
     */
1776
    public static function validate_survey_hash($survey_id, $course_id, $session_id, $group_id, $hash)
1777
    {
1778
        $survey_generated_hash = self::generate_survey_hash($survey_id, $course_id, $session_id, $group_id);
1779
        if ($survey_generated_hash == $hash) {
1780
            return true;
1781
        }
1782
1783
        return false;
1784
    }
1785
1786
    /**
1787
     * @param int $survey_id
1788
     * @param int $course_id
1789
     * @param int $session_id
1790
     * @param int $group_id
1791
     *
1792
     * @return string
1793
     */
1794
    public static function generate_survey_link(
1795
        $survey_id,
1796
        $course_id,
1797
        $session_id,
1798
        $group_id
1799
    ) {
1800
        $code = self::generate_survey_hash(
1801
            $survey_id,
1802
            $course_id,
1803
            $session_id,
1804
            $group_id
1805
        );
1806
1807
        return api_get_path(WEB_CODE_PATH).'survey/link.php?h='.$code.'&i='.$survey_id.'&c='.intval($course_id).'&s='
1808
            .intval($session_id).'&g='.$group_id;
1809
    }
1810
1811
    /**
1812
     * Check if the current user has mandatory surveys no-answered
1813
     * and redirect to fill the first found survey
1814
     */
1815
    public static function protectByMandatory()
1816
    {
1817
        if (strpos($_SERVER['SCRIPT_NAME'], 'fillsurvey.php') !== false) {
1818
            return;
1819
        }
1820
1821
        $userId = api_get_user_id();
1822
        $courseId = api_get_course_int_id();
1823
        $sessionId = api_get_session_id();
1824
1825
        if (!$userId) {
1826
            return;
1827
        }
1828
1829
        if (!$courseId) {
1830
            return;
1831
        }
1832
1833
        try {
1834
            /** @var CSurveyInvitation $invitation */
1835
            $invitation = Database::getManager()
1836
                ->createQuery("
1837
                    SELECT i FROM ChamiloCourseBundle:CSurveyInvitation i
1838
                    INNER JOIN ChamiloCourseBundle:CSurvey s WITH s.code = i.surveyCode
1839
                    INNER JOIN ChamiloCoreBundle:ExtraFieldValues efv WITH efv.itemId = s.iid
1840
                    INNER JOIN ChamiloCoreBundle:ExtraField ef WITH efv.field = ef.id
1841
                    WHERE i.answered = 0
1842
                        AND i.cId = :course
1843
                        AND i.user = :user
1844
                        AND i.sessionId = :session
1845
                        AND :now BETWEEN s.availFrom AND s.availTill
1846
                        AND ef.variable = :variable
1847
                        AND efv.value = 1
1848
                    ORDER BY s.availTill ASC
1849
                ")
1850
                ->setMaxResults(1)
1851
                ->setParameters([
1852
                    'course' => $courseId,
1853
                    'user' => $userId,
1854
                    'session' => $sessionId,
1855
                    'now' => new DateTime('UTC', new DateTimeZone('UTC')),
1856
                    'variable' => 'is_mandatory'
1857
                ])
1858
                ->getSingleResult();
1859
        } catch (Exception $e) {
1860
            $invitation = null;
1861
        }
1862
1863
        if (!$invitation) {
1864
            return;
1865
        }
1866
1867
        $urlParams = http_build_query([
1868
            'course' => api_get_course_id(),
1869
            'invitationcode' => $invitation->getInvitationCode()
1870
        ]);
1871
1872
        Display::addFlash(
1873
            Display::return_message(get_lang('MandatorySurveyNoAnswered'), 'warning')
1874
        );
1875
1876
        header('Location: '.api_get_path(WEB_CODE_PATH).'survey/fillsurvey.php?'.$urlParams.'&'.api_get_cidreq());
1877
        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...
1878
    }
1879
1880
    /**
1881
     * This function empty surveys (invitations and answers)
1882
     *
1883
     * @param int $surveyId id of the survey to empty
1884
     * @return bool
1885
     */
1886
    public static function emptySurveyFromId($surveyId)
1887
    {
1888
        // Database table definitions
1889
        $surveyInvitationTable = Database:: get_course_table(TABLE_SURVEY_INVITATION);
1890
        $surveyAnswerTable = Database:: get_course_table(TABLE_SURVEY_ANSWER);
1891
        $surveyTable = Database:: get_course_table(TABLE_SURVEY);
1892
        $surveyId = (int) $surveyId;
1893
        $surveyData = self::get_survey($surveyId);
1894
        if (empty($surveyData)) {
1895
            return false;
1896
        }
1897
1898
        $surveyCode = $surveyData['survey_code'];
1899
        $courseId = (int) $surveyData['c_id'];
1900
        $sessionId = (int) $surveyData['session_id'];
1901
1902
        $sql = "DELETE FROM $surveyInvitationTable 
1903
                WHERE session_id = $sessionId AND c_id = $courseId AND survey_code = '$surveyCode' ";
1904
        Database::query($sql);
1905
1906
        $sql = "DELETE FROM $surveyAnswerTable 
1907
               WHERE survey_id = $surveyId AND c_id = $courseId ";
1908
        Database::query($sql);
1909
1910
        $sql = "UPDATE $surveyTable 
1911
                SET invited = 0, answered = 0 
1912
                WHERE survey_id = $surveyId AND c_id = $courseId AND session_id = $sessionId ";
1913
        Database::query($sql);
1914
1915
        return true;
1916
    }
1917
1918
    /**
1919
     * This function copy survey specifying course id and session id where will be copied
1920
     *
1921
     * @param int $surveyId
1922
     * @param int $courseId target course id
1923
     * @param int $sessionId target session id
1924
     *
1925
     * @return bool|int when fails or return the new survey id
1926
     */
1927
    public static function copySurveySession($surveyId, $targetCourseId, $targetSessionId)
1928
    {
1929
        // Database table definitions
1930
        $surveyTable = Database::get_course_table(TABLE_SURVEY);
1931
        $surveyQuestionGroupTable = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
1932
        $surveyQuestionTable = Database::get_course_table(TABLE_SURVEY_QUESTION);
1933
        $surveyOptionsTable = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1934
        $surveyId = (int)$surveyId;
1935
        $targetCourseId = (int)$targetCourseId;
1936
        $targetSessionId = (int)$targetSessionId;
1937
1938
        $surveyData = self::get_survey($surveyId, 0, '', true);
1939
        if (empty($surveyData) || empty($targetCourseId)) {
1940
            return false;
1941
        }
1942
1943
        $originalCourseId = $surveyData['c_id'];
1944
        $originalSessionId = $surveyData['session_id'];
1945
1946
        $surveyData['code'] = self::generate_unique_code($surveyData['code']);
1947
        $surveyData['c_id'] = $targetCourseId;
1948
        $surveyData['session_id'] = $targetSessionId;
1949
        // Add a "Copy" suffix if copied inside the same course
1950
        if ($targetCourseId == $originalCourseId) {
1951
            $surveyData['title'] = $surveyData['title'].' '.get_lang('Copy');
1952
        }
1953
        unset($surveyData['iid']);
1954
        unset($surveyData['id']);
1955
1956
        $newSurveyId = Database::insert($surveyTable, $surveyData);
1957
1958
        if ($newSurveyId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $newSurveyId 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...
1959
            $sql = "UPDATE $surveyTable SET survey_id = $newSurveyId 
1960
                    WHERE iid = $newSurveyId";
1961
            Database::query($sql);
1962
1963
            $sql = "SELECT * FROM $surveyQuestionGroupTable 
1964
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId ";
1965
            $res = Database::query($sql);
1966
            while ($row = Database::fetch_array($res, 'ASSOC')) {
1967
                $params = [
1968
                    'c_id' => $targetCourseId,
1969
                    'name' => $row['name'],
1970
                    'description' => $row['description'],
1971
                    'survey_id' => $newSurveyId
1972
                ];
1973
                $insertId = Database::insert($surveyQuestionGroupTable, $params);
1974
                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...
1975
                    $sql = "UPDATE $surveyQuestionGroupTable SET id = iid WHERE iid = $insertId";
1976
                    Database::query($sql);
1977
                    $group_id[$row['id']] = $insertId;
1978
                }
1979
            }
1980
1981
            // Get questions
1982
            $sql = "SELECT * FROM $surveyQuestionTable 
1983
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId";
1984
            $res = Database::query($sql);
1985
            while ($row = Database::fetch_array($res, 'ASSOC')) {
1986
                $params = [
1987
                    'c_id' => $targetCourseId,
1988
                    'survey_id' => $newSurveyId,
1989
                    'survey_question' => $row['survey_question'],
1990
                    'survey_question_comment' => $row['survey_question_comment'],
1991
                    'type' => $row['type'],
1992
                    'display' => $row['display'],
1993
                    'sort' => $row['sort'],
1994
                    'shared_question_id' => $row['shared_question_id'],
1995
                    'max_value' => $row['max_value'],
1996
                    'survey_group_pri' => $row['survey_group_pri'],
1997
                    'survey_group_sec1' => $row['survey_group_sec1'],
1998
                    'survey_group_sec2' => $row['survey_group_sec2']
1999
                ];
2000
                $insertId = Database::insert($surveyQuestionTable, $params);
2001
                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...
2002
                    $sql = "UPDATE $surveyQuestionTable 
2003
                            SET question_id = iid
2004
                            WHERE iid = $insertId";
2005
                    Database::query($sql);
2006
2007
                    $question_id[$row['question_id']] = $insertId;
2008
                }
2009
            }
2010
2011
            // Get questions options
2012
            $sql = "SELECT * FROM $surveyOptionsTable 
2013
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId";
2014
2015
            $res = Database::query($sql);
2016
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2017
                $params = [
2018
                    'c_id' => $targetCourseId,
2019
                    'question_id' => $question_id[$row['question_id']],
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_id does not seem to be defined for all execution paths leading up to this point.
Loading history...
2020
                    'survey_id' => $newSurveyId,
2021
                    'option_text' => $row['option_text'],
2022
                    'sort' => $row['sort'],
2023
                    'value' => $row['value']
2024
                ];
2025
                $insertId = Database::insert($surveyOptionsTable, $params);
2026
                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...
2027
                    $sql = "UPDATE $surveyOptionsTable SET question_option_id = $insertId WHERE iid = $insertId";
2028
                    Database::query($sql);
2029
                }
2030
            }
2031
2032
            return $newSurveyId;
2033
        }
2034
2035
        return false;
2036
    }
2037
}
2038