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

SurveyManager::copySurveySession()   C

Complexity

Conditions 11
Paths 57

Size

Total Lines 109
Code Lines 78

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 11
eloc 78
c 2
b 0
f 0
nc 57
nop 3
dl 0
loc 109
rs 5.2653

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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

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

364
                    /** @scrutinizer ignore-type */ $survey_id,
Loading history...
365
                    'SurveyAdded',
366
                    api_get_user_id()
367
                );
368
            }
369
370
            if ($values['survey_type'] == 1 && !empty($values['parent_id'])) {
371
                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

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

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

1511
            self::/** @scrutinizer ignore-call */ 
1512
                  save_shared_question_options($form_content, $survey_data);
Loading history...
1512
        }
1513
1514
        // Table definition
1515
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1516
1517
        // We are editing a question so we first have to remove all the existing options from the database
1518
        if (is_numeric($form_content['question_id'])) {
1519
            $sql = "DELETE FROM $table_survey_question_option
1520
			        WHERE c_id = $course_id AND question_id = '".intval($form_content['question_id'])."'";
1521
            Database::query($sql);
1522
        }
1523
1524
        $counter = 1;
1525
        if (isset($form_content['answers']) && is_array($form_content['answers'])) {
1526
            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...
1527
                $values = isset($form_content['values']) ? $form_content['values'][$i] : '';
1528
1529
                $params = [
1530
                    'c_id' => $course_id,
1531
                    'question_id' => $form_content['question_id'],
1532
                    'survey_id' => $form_content['survey_id'],
1533
                    'option_text' => $form_content['answers'][$i],
1534
                    'value' => $values,
1535
                    'sort' => $counter,
1536
                ];
1537
                $insertId = Database::insert($table_survey_question_option, $params);
1538
                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...
1539
                    $sql = "UPDATE $table_survey_question_option
1540
                            SET question_option_id = $insertId
1541
                            WHERE iid = $insertId";
1542
                    Database::query($sql);
1543
1544
                    $counter++;
1545
                }
1546
            }
1547
        }
1548
    }
1549
1550
    /**
1551
     * This function stores the options of the questions in the shared table.
1552
     *
1553
     * @param array $form_content
1554
     *
1555
     * @author Patrick Cool <[email protected]>, Ghent University
1556
     *
1557
     * @version February 2007
1558
     *
1559
     * @todo writing the update statement when editing a question
1560
     */
1561
    public function save_shared_question_options($form_content, $survey_data)
1562
    {
1563
        if (is_array($form_content) && is_array($form_content['answers'])) {
1564
            // Table definition
1565
            $table = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1566
1567
            // We are editing a question so we first have to remove all the existing options from the database
1568
            $sql = "DELETE FROM $table
1569
                    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

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