Passed
Push — 1.11.x ( e32905...d27111 )
by Julito
12:46 queued 10s
created

SurveyManager::generate_survey_hash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 4
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CourseBundle\Entity\CSurveyInvitation;
6
7
/**
8
 * Class SurveyManager.
9
 *
10
 * @author Patrick Cool <[email protected]>, Ghent University:
11
 * cleanup, refactoring and rewriting large parts (if not all) of the code
12
 * @author Julio Montoya <[email protected]>, Personality Test modification
13
 * and rewriting large parts of the code
14
 * @author cfasanando
15
 *
16
 * @todo move this file to inc/lib
17
 * @todo use consistent naming for the functions (save vs store for instance)
18
 */
19
class SurveyManager
20
{
21
    /**
22
     * @param $code
23
     *
24
     * @return string
25
     */
26
    public static function generate_unique_code($code)
27
    {
28
        if (empty($code)) {
29
            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...
30
        }
31
        $course_id = api_get_course_int_id();
32
        $table = Database::get_course_table(TABLE_SURVEY);
33
        $code = Database::escape_string($code);
34
        $num = 0;
35
        $new_code = $code;
36
        while (true) {
37
            $sql = "SELECT * FROM $table
38
                    WHERE code = '$new_code' AND c_id = $course_id";
39
            $result = Database::query($sql);
40
            if (Database::num_rows($result)) {
41
                $num++;
42
                $new_code = $code.$num;
43
            } else {
44
                break;
45
            }
46
        }
47
48
        return $code.$num;
49
    }
50
51
    /**
52
     * Deletes all survey invitations of a user.
53
     *
54
     * @param int $user_id
55
     *
56
     * @return bool
57
     * @assert ('') === false
58
     */
59
    public static function delete_all_survey_invitations_by_user($user_id)
60
    {
61
        $user_id = (int) $user_id;
62
        if (empty($user_id)) {
63
            return false;
64
        }
65
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
66
        $table_survey = Database::get_course_table(TABLE_SURVEY);
67
68
        $sql = "SELECT survey_invitation_id, survey_code
69
                FROM $table_survey_invitation WHERE user = '$user_id' AND c_id <> 0 ";
70
        $result = Database::query($sql);
71
        while ($row = Database::fetch_array($result, 'ASSOC')) {
72
            $survey_invitation_id = $row['survey_invitation_id'];
73
            $survey_code = $row['survey_code'];
74
            $sql2 = "DELETE FROM $table_survey_invitation
75
                    WHERE survey_invitation_id = '$survey_invitation_id' AND c_id <> 0";
76
            if (Database::query($sql2)) {
77
                $sql3 = "UPDATE $table_survey SET
78
                            invited = invited-1
79
                        WHERE c_id <> 0 AND code ='$survey_code'";
80
                Database::query($sql3);
81
            }
82
        }
83
    }
84
85
    /**
86
     * @param string $course_code
87
     * @param int    $session_id
88
     *
89
     * @return array
90
     * @assert ('') === false
91
     */
92
    public static function get_surveys($course_code, $session_id = 0)
93
    {
94
        if (empty($course_code)) {
95
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
96
        }
97
        $course_info = api_get_course_info($course_code);
98
99
        if (empty($course_info)) {
100
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
101
        }
102
103
        $sessionCondition = api_get_session_condition($session_id, true, true);
104
105
        $table = Database::get_course_table(TABLE_SURVEY);
106
        $sql = "SELECT * FROM $table
107
                WHERE c_id = {$course_info['real_id']} $sessionCondition ";
108
        $result = Database::query($sql);
109
110
        return Database::store_result($result, 'ASSOC');
111
    }
112
113
    /**
114
     * Retrieves all the survey information.
115
     *
116
     * @param int  $survey_id the id of the survey
117
     * @param bool $shared    this parameter determines if
118
     *                        we have to get the information of a survey from the central (shared) database or from the
119
     *                        course database
120
     * @param string course code optional
121
     *
122
     * @author Patrick Cool <[email protected]>, Ghent University
123
     *
124
     * @version February 2007
125
     * @assert ('') === false
126
     *
127
     * @return array
128
     *
129
     * @todo this is the same function as in create_new_survey.php
130
     */
131
    public static function get_survey(
132
        $survey_id,
133
        $shared = 0,
134
        $course_code = '',
135
        $simple_return = false
136
    ) {
137
        $my_course_id = api_get_course_id();
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
        }
145
146
        $courseInfo = api_get_course_info($my_course_id);
147
        $survey_id = (int) $survey_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='".$survey_id."' ";
154
        } else {
155
            if (empty($courseInfo)) {
156
                return [];
157
            }
158
            $sql = "SELECT * FROM $table_survey
159
		            WHERE
160
		                survey_id='".$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
        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
222
        $_user = api_get_user_info();
223
        $course_id = api_get_course_int_id();
224
        $session_id = api_get_session_id();
225
        $courseCode = api_get_course_id();
226
        $table_survey = Database::get_course_table(TABLE_SURVEY);
227
        $shared_survey_id = 0;
228
229
        if (!isset($values['survey_id'])) {
230
            // Check if the code doesn't soon exists in this language
231
            $sql = 'SELECT 1 FROM '.$table_survey.'
232
			        WHERE
233
			            c_id = '.$course_id.' AND
234
			            code = "'.Database::escape_string($values['survey_code']).'" AND
235
			            lang = "'.Database::escape_string($values['survey_language']).'"';
236
            $rs = Database::query($sql);
237
            if (Database::num_rows($rs) > 0) {
238
                Display::addFlash(
239
                    Display::return_message(
240
                        get_lang('ThisSurveyCodeSoonExistsInThisLanguage'),
241
                        'error'
242
                    )
243
                );
244
                $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...
245
                $return['id'] = isset($values['survey_id']) ? $values['survey_id'] : 0;
246
247
                return $return;
248
            }
249
250
            if (!isset($values['anonymous'])) {
251
                $values['anonymous'] = 0;
252
            }
253
254
            $values['anonymous'] = (int) $values['anonymous'];
255
            $extraParams = [];
256
            if ($values['anonymous'] == 0) {
257
                // Input_name_list
258
                $values['show_form_profile'] = isset($values['show_form_profile']) ? $values['show_form_profile'] : 0;
259
                $extraParams['show_form_profile'] = $values['show_form_profile'];
260
261
                if ($values['show_form_profile'] == 1) {
262
                    // Input_name_list
263
                    $fields = explode(',', $values['input_name_list']);
264
                    $field_values = '';
265
                    foreach ($fields as &$field) {
266
                        if ($field != '') {
267
                            if ($values[$field] == '') {
268
                                $values[$field] = 0;
269
                            }
270
                            $field_values .= $field.':'.$values[$field].'@';
271
                        }
272
                    }
273
                    $extraParams['form_fields'] = $field_values;
274
                } else {
275
                    $extraParams['form_fields'] = '';
276
                }
277
            } else {
278
                // Input_name_list
279
                $extraParams['show_form_profile'] = 0;
280
                $extraParams['form_fields'] = '';
281
            }
282
283
            $extraParams['one_question_per_page'] = isset($values['one_question_per_page']) ? $values['one_question_per_page'] : 0;
284
            $extraParams['shuffle'] = isset($values['shuffle']) ? $values['shuffle'] : 0;
285
286
            if ($values['survey_type'] == 1) {
287
                $extraParams['survey_type'] = 1;
288
                $extraParams['parent_id'] = $values['parent_id'];
289
290
                // Logic for versioning surveys
291
                if (!empty($values['parent_id'])) {
292
                    $versionValue = '';
293
                    $sql = 'SELECT survey_version
294
                            FROM '.$table_survey.'
295
					        WHERE
296
					            c_id = '.$course_id.' AND
297
					            parent_id = '.intval($values['parent_id']).'
298
                            ORDER BY survey_version DESC
299
                            LIMIT 1';
300
                    $rs = Database::query($sql);
301
                    if (Database::num_rows($rs) === 0) {
302
                        $sql = 'SELECT survey_version FROM '.$table_survey.'
303
						        WHERE
304
						            c_id = '.$course_id.' AND
305
						            survey_id = '.intval($values['parent_id']);
306
                        $rs = Database::query($sql);
307
                        $getversion = Database::fetch_array($rs, 'ASSOC');
308
                        if (empty($getversion['survey_version'])) {
309
                            $versionValue = ++$getversion['survey_version'];
310
                        } else {
311
                            $versionValue = $getversion['survey_version'];
312
                        }
313
                    } else {
314
                        $row = Database::fetch_array($rs, 'ASSOC');
315
                        $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

315
                        $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...
316
                        if ($pos === false) {
317
                            $row['survey_version'] = $row['survey_version'] + 1;
318
                            $versionValue = $row['survey_version'];
319
                        } else {
320
                            $getlast = explode('\.', $row['survey_version']);
321
                            $lastversion = array_pop($getlast);
322
                            $lastversion = $lastversion + 1;
323
                            $add = implode('.', $getlast);
324
                            if ($add != '') {
325
                                $insertnewversion = $add.'.'.$lastversion;
326
                            } else {
327
                                $insertnewversion = $lastversion;
328
                            }
329
                            $versionValue = $insertnewversion;
330
                        }
331
                    }
332
                    $extraParams['survey_version'] = $versionValue;
333
                }
334
            }
335
336
            $params = [
337
                'c_id' => $course_id,
338
                'code' => self::generateSurveyCode($values['survey_code']),
339
                'title' => $values['survey_title'],
340
                'subtitle' => $values['survey_subtitle'],
341
                'author' => $_user['user_id'],
342
                'lang' => $values['survey_language'],
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
            if (!empty($values['start_date'])) {
354
                if ($allowSurveyAvailabilityDatetime) {
355
                    $params['avail_from'] = api_get_utc_datetime($values['start_date'].':00');
356
                } else {
357
                    $params['avail_from'] = $values['start_date'];
358
                }
359
            }
360
361
            if (!empty($values['end_date'])) {
362
                if ($allowSurveyAvailabilityDatetime) {
363
                    $params['avail_till'] = api_get_utc_datetime($values['end_date'].':00');
364
                } else {
365
                    $params['avail_till'] = $values['end_date'];
366
                }
367
            }
368
369
            if (isset($values['survey_type']) && !empty($values['survey_type'])) {
370
                $params['survey_type'] = $values['survey_type'];
371
            }
372
373
            $params = array_merge($params, $extraParams);
374
375
            $survey_id = Database::insert($table_survey, $params);
376
            if ($survey_id > 0) {
377
                $sql = "UPDATE $table_survey SET survey_id = $survey_id
378
                        WHERE iid = $survey_id";
379
                Database::query($sql);
380
381
                // Insert into item_property
382
                api_item_property_update(
383
                    api_get_course_info(),
384
                    TOOL_SURVEY,
385
                    $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

385
                    /** @scrutinizer ignore-type */ $survey_id,
Loading history...
386
                    'SurveyAdded',
387
                    api_get_user_id()
388
                );
389
            }
390
391
            if ($values['survey_type'] == 1 && !empty($values['parent_id'])) {
392
                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

392
                self::copy_survey($values['parent_id'], /** @scrutinizer ignore-type */ $survey_id);
Loading history...
393
            }
394
395
            Display::addFlash(
396
                Display::return_message(
397
                    get_lang('SurveyCreatedSuccesfully'),
398
                    'success'
399
                )
400
            );
401
            $return['id'] = $survey_id;
402
        } else {
403
            // Check whether the code doesn't soon exists in this language
404
            $sql = 'SELECT 1 FROM '.$table_survey.'
405
			        WHERE
406
			            c_id = '.$course_id.' AND
407
			            code = "'.Database::escape_string($values['survey_code']).'" AND
408
			            lang = "'.Database::escape_string($values['survey_language']).'" AND
409
			            survey_id !='.intval($values['survey_id']);
410
            $rs = Database::query($sql);
411
            if (Database::num_rows($rs) > 0) {
412
                Display::addFlash(
413
                    Display::return_message(
414
                        get_lang('ThisSurveyCodeSoonExistsInThisLanguage'),
415
                        'error'
416
                    )
417
                );
418
                $return['type'] = 'error';
419
                $return['id'] = isset($values['survey_id']) ? $values['survey_id'] : 0;
420
421
                return $return;
422
            }
423
424
            if (!isset($values['anonymous'])
425
                || (isset($values['anonymous']) && $values['anonymous'] == '')
426
            ) {
427
                $values['anonymous'] = 0;
428
            }
429
430
            $extraParams = [];
431
            $extraParams['one_question_per_page'] = isset($values['one_question_per_page']) ? $values['one_question_per_page'] : 0;
432
            $extraParams['shuffle'] = isset($values['shuffle']) ? $values['shuffle'] : 0;
433
434
            if ($values['anonymous'] == 0) {
435
                $extraParams['show_form_profile'] = isset($values['show_form_profile']) ? $values['show_form_profile'] : 0;
436
                if ($extraParams['show_form_profile'] == 1) {
437
                    $fields = explode(',', $values['input_name_list']);
438
                    $field_values = '';
439
                    foreach ($fields as &$field) {
440
                        if ($field != '') {
441
                            if (!isset($values[$field]) ||
442
                                (isset($values[$field]) && $values[$field] == '')
443
                            ) {
444
                                $values[$field] = 0;
445
                            }
446
                            $field_values .= $field.':'.$values[$field].'@';
447
                        }
448
                    }
449
                    $extraParams['form_fields'] = $field_values;
450
                } else {
451
                    $extraParams['form_fields'] = '';
452
                }
453
            } else {
454
                $extraParams['show_form_profile'] = 0;
455
                $extraParams['form_fields'] = '';
456
            }
457
458
            $params = [
459
                'title' => $values['survey_title'],
460
                'subtitle' => $values['survey_subtitle'],
461
                'author' => $_user['user_id'],
462
                'lang' => $values['survey_language'],
463
                'avail_from' => $allowSurveyAvailabilityDatetime
464
                    ? api_get_utc_datetime($values['start_date'].':00')
465
                    : $values['start_date'],
466
                'avail_till' => $allowSurveyAvailabilityDatetime
467
                    ? api_get_utc_datetime($values['end_date'].':59')
468
                    : $values['end_date'],
469
                'is_shared' => $shared_survey_id,
470
                'template' => 'template',
471
                'intro' => $values['survey_introduction'],
472
                'surveythanks' => $values['survey_thanks'],
473
                'anonymous' => $values['anonymous'],
474
                'session_id' => api_get_session_id(),
475
                'visible_results' => $values['visible_results'],
476
            ];
477
478
            $params = array_merge($params, $extraParams);
479
            Database::update(
480
                $table_survey,
481
                $params,
482
                [
483
                    'c_id = ? AND survey_id = ?' => [
484
                        $course_id,
485
                        $values['survey_id'],
486
                    ],
487
                ]
488
            );
489
490
            // Update into item_property (update)
491
            api_item_property_update(
492
                api_get_course_info(),
493
                TOOL_SURVEY,
494
                $values['survey_id'],
495
                'SurveyUpdated',
496
                api_get_user_id()
497
            );
498
499
            Display::addFlash(
500
                Display::return_message(
501
                    get_lang('SurveyUpdatedSuccesfully'),
502
                    'confirmation'
503
                )
504
            );
505
506
            $return['id'] = $values['survey_id'];
507
        }
508
509
        $survey_id = (int) $return['id'];
510
511
        // Gradebook
512
        $gradebook_option = false;
513
        if (isset($values['survey_qualify_gradebook'])) {
514
            $gradebook_option = $values['survey_qualify_gradebook'] > 0;
515
        }
516
517
        $gradebook_link_type = 8;
518
        $link_info = GradebookUtils::isResourceInCourseGradebook(
519
            $courseCode,
520
            $gradebook_link_type,
521
            $survey_id,
522
            $session_id
523
        );
524
525
        $gradebook_link_id = isset($link_info['id']) ? $link_info['id'] : false;
526
527
        if ($gradebook_option) {
528
            if ($survey_id > 0) {
529
                $title_gradebook = ''; // Not needed here.
530
                $description_gradebook = ''; // Not needed here.
531
                $survey_weight = floatval($_POST['survey_weight']);
532
                $max_score = 1;
533
534
                if (!$gradebook_link_id) {
535
                    GradebookUtils::add_resource_to_course_gradebook(
536
                        $values['category_id'],
537
                        $courseCode,
538
                        $gradebook_link_type,
539
                        $survey_id,
540
                        $title_gradebook,
541
                        $survey_weight,
542
                        $max_score,
543
                        $description_gradebook,
544
                        1,
545
                        $session_id
546
                    );
547
                } else {
548
                    GradebookUtils::updateResourceFromCourseGradebook(
549
                        $gradebook_link_id,
550
                        $courseCode,
551
                        $survey_weight
552
                    );
553
                }
554
            }
555
        } else {
556
            // Delete everything of the gradebook for this $linkId
557
            GradebookUtils::remove_resource_from_course_gradebook($gradebook_link_id);
558
        }
559
560
        return $return;
561
    }
562
563
    /**
564
     * This function stores a shared survey in the central database.
565
     *
566
     * @param array $values
567
     *
568
     * @return array $return the type of return message that has to be displayed and the message in it
569
     *
570
     * @author Patrick Cool <[email protected]>, Ghent University
571
     *
572
     * @version February 2007
573
     */
574
    public function store_shared_survey($values)
575
    {
576
        $_user = api_get_user_info();
577
        $_course = api_get_course_info();
578
579
        // Table definitions
580
        $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
581
582
        if (!$values['survey_id'] ||
583
            !is_numeric($values['survey_id']) ||
584
            $values['survey_share']['survey_share'] == 'true'
585
        ) {
586
            $sql = "INSERT INTO $table_survey (code, title, subtitle, author, lang, template, intro, surveythanks, creation_date, course_code) VALUES (
587
                    '".Database::escape_string($values['survey_code'])."',
588
                    '".Database::escape_string($values['survey_title'])."',
589
                    '".Database::escape_string($values['survey_subtitle'])."',
590
                    '".intval($_user['user_id'])."',
591
                    '".Database::escape_string($values['survey_language'])."',
592
                    '".Database::escape_string('template')."',
593
                    '".Database::escape_string($values['survey_introduction'])."',
594
                    '".Database::escape_string($values['survey_thanks'])."',
595
                    '".api_get_utc_datetime()."',
596
                    '".$_course['id']."')";
597
            Database::query($sql);
598
            $return = Database::insert_id();
599
600
            $sql = "UPDATE $table_survey SET survey_id = $return WHERE iid = $return";
601
            Database::query($sql);
602
        } else {
603
            $sql = "UPDATE $table_survey SET
604
                        code 			= '".Database::escape_string($values['survey_code'])."',
605
                        title 			= '".Database::escape_string($values['survey_title'])."',
606
                        subtitle 		= '".Database::escape_string($values['survey_subtitle'])."',
607
                        author 			= '".intval($_user['user_id'])."',
608
                        lang 			= '".Database::escape_string($values['survey_language'])."',
609
                        template 		= '".Database::escape_string('template')."',
610
                        intro			= '".Database::escape_string($values['survey_introduction'])."',
611
                        surveythanks	= '".Database::escape_string($values['survey_thanks'])."'
612
					WHERE survey_id = '".Database::escape_string($values['survey_share']['survey_share'])."'";
613
            Database::query($sql);
614
            $return = $values['survey_share']['survey_share'];
615
        }
616
617
        return $return;
618
    }
619
620
    /**
621
     * This function deletes a survey (and also all the question in that survey.
622
     *
623
     * @param int  $survey_id id of the survey that has to be deleted
624
     * @param bool $shared
625
     * @param int  $course_id
626
     *
627
     * @return true
628
     *
629
     * @author Patrick Cool <[email protected]>, Ghent University
630
     *
631
     * @version January 2007
632
     */
633
    public static function delete_survey($survey_id, $shared = false, $course_id = 0)
634
    {
635
        // Database table definitions
636
        if (empty($course_id)) {
637
            $course_id = api_get_course_int_id();
638
        }
639
640
        $survey_id = (int) $survey_id;
641
642
        if (empty($survey_id)) {
643
            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...
644
        }
645
646
        $course_info = api_get_course_info_by_id($course_id);
647
        $course_id = $course_info['real_id'];
648
649
        $table_survey = Database::get_course_table(TABLE_SURVEY);
650
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
651
652
        if ($shared) {
653
            $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
654
            // Deleting the survey
655
            $sql = "DELETE FROM $table_survey
656
                    WHERE survey_id='".$survey_id."'";
657
            Database::query($sql);
658
        } else {
659
            $sql = "DELETE FROM $table_survey
660
                    WHERE c_id = $course_id AND survey_id='".$survey_id."'";
661
            Database::query($sql);
662
        }
663
664
        // Deleting groups of this survey
665
        $sql = "DELETE FROM $table_survey_question_group
666
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
667
        Database::query($sql);
668
669
        // Deleting the questions of the survey
670
        self::delete_all_survey_questions($survey_id, $shared);
671
672
        // Update into item_property (delete)
673
        api_item_property_update(
674
            $course_info,
675
            TOOL_SURVEY,
676
            $survey_id,
677
            'SurveyDeleted',
678
            api_get_user_id()
679
        );
680
681
        Skill::deleteSkillsFromItem($survey_id, ITEM_TYPE_SURVEY);
682
683
        return true;
684
    }
685
686
    /**
687
     * @param int $survey_id
688
     * @param int $new_survey_id
689
     * @param int $targetCourseId
690
     *
691
     * @return bool
692
     */
693
    public static function copy_survey(
694
        $survey_id,
695
        $new_survey_id = null,
696
        $targetCourseId = null
697
    ) {
698
        $course_id = api_get_course_int_id();
699
        if (!$targetCourseId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $targetCourseId of type integer|null 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...
700
            $targetCourseId = $course_id;
701
        }
702
703
        // Database table definitions
704
        $table_survey = Database::get_course_table(TABLE_SURVEY);
705
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
706
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
707
        $table_survey_options = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
708
        $survey_id = (int) $survey_id;
709
710
        // Get groups
711
        $survey_data = self::get_survey($survey_id, 0, null, true);
712
        if (empty($survey_data)) {
713
            return true;
714
        }
715
716
        if (empty($new_survey_id)) {
717
            $params = $survey_data;
718
            $params['code'] = self::generate_unique_code($params['code']);
719
            $params['c_id'] = $targetCourseId;
720
            unset($params['survey_id']);
721
            $params['session_id'] = api_get_session_id();
722
            $params['title'] = $params['title'].' '.get_lang('Copy');
723
            unset($params['iid']);
724
            $params['invited'] = 0;
725
            $params['answered'] = 0;
726
            $new_survey_id = Database::insert($table_survey, $params);
727
728
            if ($new_survey_id) {
729
                $sql = "UPDATE $table_survey SET survey_id = $new_survey_id
730
                        WHERE iid = $new_survey_id";
731
                Database::query($sql);
732
733
                // Insert into item_property
734
                api_item_property_update(
735
                    api_get_course_info(),
736
                    TOOL_SURVEY,
737
                    $new_survey_id,
738
                    'SurveyAdded',
739
                    api_get_user_id()
740
                );
741
            }
742
        } else {
743
            $new_survey_id = (int) $new_survey_id;
744
        }
745
746
        $sql = "SELECT * FROM $table_survey_question_group
747
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
748
        $res = Database::query($sql);
749
        while ($row = Database::fetch_array($res, 'ASSOC')) {
750
            $params = [
751
                'c_id' => $targetCourseId,
752
                'name' => $row['name'],
753
                'description' => $row['description'],
754
                'survey_id' => $new_survey_id,
755
            ];
756
            $insertId = Database::insert($table_survey_question_group, $params);
757
758
            $sql = "UPDATE $table_survey_question_group SET id = iid
759
                    WHERE iid = $insertId";
760
            Database::query($sql);
761
762
            $group_id[$row['id']] = $insertId;
763
        }
764
765
        // Get questions
766
        $sql = "SELECT * FROM $table_survey_question
767
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
768
        $res = Database::query($sql);
769
        while ($row = Database::fetch_array($res, 'ASSOC')) {
770
            $params = [
771
                'c_id' => $targetCourseId,
772
                'survey_id' => $new_survey_id,
773
                'survey_question' => $row['survey_question'],
774
                'survey_question_comment' => $row['survey_question_comment'],
775
                'type' => $row['type'],
776
                'display' => $row['display'],
777
                'sort' => $row['sort'],
778
                'shared_question_id' => $row['shared_question_id'],
779
                'max_value' => $row['max_value'],
780
                'survey_group_pri' => $row['survey_group_pri'],
781
                'survey_group_sec1' => $row['survey_group_sec1'],
782
                'survey_group_sec2' => $row['survey_group_sec2'],
783
            ];
784
785
            if (api_get_configuration_value('allow_required_survey_questions')) {
786
                if (isset($row['is_required'])) {
787
                    $params['is_required'] = $row['is_required'];
788
                }
789
            }
790
791
            $insertId = Database::insert($table_survey_question, $params);
792
            if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
793
                $sql = "UPDATE $table_survey_question SET question_id = iid WHERE iid = $insertId";
794
                Database::query($sql);
795
                $question_id[$row['question_id']] = $insertId;
796
            }
797
        }
798
799
        // Get questions options
800
        $sql = "SELECT * FROM $table_survey_options
801
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
802
803
        $res = Database::query($sql);
804
        while ($row = Database::fetch_array($res, 'ASSOC')) {
805
            $params = [
806
                'c_id' => $targetCourseId,
807
                '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...
808
                'survey_id' => $new_survey_id,
809
                'option_text' => $row['option_text'],
810
                'sort' => $row['sort'],
811
                'value' => $row['value'],
812
            ];
813
            $insertId = Database::insert($table_survey_options, $params);
814
            if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
815
                $sql = "UPDATE $table_survey_options SET question_option_id = $insertId
816
                        WHERE iid = $insertId";
817
                Database::query($sql);
818
            }
819
        }
820
821
        return $new_survey_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $new_survey_id also could return the type integer which is incompatible with the documented return type boolean.
Loading history...
822
    }
823
824
    /**
825
     * This function duplicates a survey (and also all the question in that survey.
826
     *
827
     * @param int $surveyId id of the survey that has to be duplicated
828
     * @param int $courseId id of the course which survey has to be duplicated
829
     *
830
     * @return true
831
     *
832
     * @author Eric Marguin <[email protected]>, Elixir Interactive
833
     *
834
     * @version October 2007
835
     */
836
    public static function empty_survey($surveyId, $courseId = 0)
837
    {
838
        // Database table definitions
839
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
840
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
841
        $table_survey = Database::get_course_table(TABLE_SURVEY);
842
843
        $courseId = (int) $courseId;
844
        $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
845
        $surveyId = (int) $surveyId;
846
847
        $datas = self::get_survey($surveyId);
848
        $session_where = '';
849
        if (api_get_session_id() != 0) {
850
            $session_where = ' AND session_id = "'.api_get_session_id().'" ';
851
        }
852
853
        $sql = 'DELETE FROM '.$table_survey_invitation.'
854
		        WHERE
855
		            c_id = '.$courseId.' AND
856
		            survey_code = "'.Database::escape_string($datas['code']).'" '.$session_where.' ';
857
        Database::query($sql);
858
859
        $sql = 'DELETE FROM '.$table_survey_answer.'
860
		        WHERE c_id = '.$courseId.' AND survey_id='.$surveyId;
861
        Database::query($sql);
862
863
        $sql = 'UPDATE '.$table_survey.' SET invited=0, answered=0
864
		        WHERE c_id = '.$courseId.' AND survey_id='.$surveyId;
865
        Database::query($sql);
866
867
        return true;
868
    }
869
870
    /**
871
     * This function recalculates the number of people who have taken the survey (=filled at least one question).
872
     *
873
     * @param array  $survey_data
874
     * @param array  $user
875
     * @param string $survey_code
876
     *
877
     * @return bool
878
     *
879
     * @author Patrick Cool <[email protected]>, Ghent University
880
     *
881
     * @version February 2007
882
     */
883
    public static function update_survey_answered($survey_data, $user, $survey_code)
884
    {
885
        if (empty($survey_data)) {
886
            return false;
887
        }
888
889
        // Database table definitions
890
        $table_survey = Database::get_course_table(TABLE_SURVEY);
891
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
892
893
        $survey_id = (int) $survey_data['survey_id'];
894
        $course_id = (int) $survey_data['c_id'];
895
        $session_id = $survey_data['session_id'];
896
897
        // Getting a list with all the people who have filled the survey
898
        /*$people_filled = self::get_people_who_filled_survey($survey_id, false, $course_id);
899
        $number = count($people_filled);*/
900
901
        // Storing this value in the survey table
902
        $sql = "UPDATE $table_survey
903
		        SET answered = answered + 1
904
		        WHERE
905
                    c_id = $course_id AND
906
		            survey_id = ".$survey_id;
907
        Database::query($sql);
908
909
        $allow = api_get_configuration_value('survey_answered_at_field');
910
        // Requires DB change:
911
        // ALTER TABLE c_survey_invitation ADD answered_at DATETIME DEFAULT NULL;
912
        $answeredAt = '';
913
        if ($allow) {
914
            $answeredAt = "answered_at = '".api_get_utc_datetime()."',";
915
        }
916
917
        // Storing that the user has finished the survey.
918
        $sql = "UPDATE $table_survey_invitation
919
                SET $answeredAt answered = 1
920
                WHERE
921
                    c_id = $course_id AND
922
                    session_id = $session_id AND
923
                    user ='".Database::escape_string($user)."' AND
924
                    survey_code='".Database::escape_string($survey_code)."'";
925
        Database::query($sql);
926
    }
927
928
    /**
929
     * This function return the "icon" of the question type.
930
     *
931
     * @param string $type
932
     *
933
     * @author Patrick Cool <[email protected]>, Ghent University
934
     *
935
     * @version February 2007
936
     */
937
    public static function icon_question($type)
938
    {
939
        // the possible question types
940
        $possible_types = [
941
            'personality',
942
            'yesno',
943
            'multiplechoice',
944
            'multipleresponse',
945
            'open',
946
            'dropdown',
947
            'comment',
948
            'pagebreak',
949
            'percentage',
950
            'score',
951
        ];
952
953
        // the images array
954
        $icon_question = [
955
            'yesno' => 'yesno.png',
956
            'personality' => 'yesno.png',
957
            'multiplechoice' => 'mcua.png',
958
            'multipleresponse' => 'mcma.png',
959
            'open' => 'open_answer.png',
960
            'dropdown' => 'dropdown.png',
961
            'percentage' => 'percentagequestion.png',
962
            'score' => 'scorequestion.png',
963
            'comment' => 'commentquestion.png',
964
            'pagebreak' => 'page_end.png',
965
        ];
966
967
        if (in_array($type, $possible_types)) {
968
            return $icon_question[$type];
969
        } else {
970
            return false;
971
        }
972
    }
973
974
    /**
975
     * This function retrieves all the information of a question.
976
     *
977
     * @param int  $question_id the id of the question
978
     * @param bool $shared
979
     *
980
     * @return array
981
     *
982
     * @author Patrick Cool <[email protected]>, Ghent University
983
     *
984
     * @version January 2007
985
     *
986
     * @todo one sql call should do the trick
987
     */
988
    public static function get_question($question_id, $shared = false)
989
    {
990
        // Table definitions
991
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
992
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
993
        $course_id = api_get_course_int_id();
994
        $question_id = (int) $question_id;
995
996
        $sql = "SELECT * FROM $tbl_survey_question
997
                WHERE c_id = $course_id AND question_id='".$question_id."'
998
                ORDER BY `sort` ";
999
1000
        $sqlOption = "  SELECT * FROM $table_survey_question_option
1001
                        WHERE c_id = $course_id AND question_id='".$question_id."'
1002
                        ORDER BY `sort` ";
1003
1004
        if ($shared) {
1005
            $tbl_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1006
            $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1007
1008
            $sql = "SELECT * FROM $tbl_survey_question
1009
                    WHERE question_id='".$question_id."'
1010
                    ORDER BY `sort` ";
1011
            $sqlOption = "SELECT * FROM $table_survey_question_option
1012
                          WHERE question_id='".$question_id."'
1013
                          ORDER BY `sort` ";
1014
        }
1015
1016
        // Getting the information of the question
1017
        $result = Database::query($sql);
1018
        $row = Database::fetch_array($result, 'ASSOC');
1019
1020
        $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...
1021
        $return['question_id'] = $row['question_id'];
1022
        $return['type'] = $row['type'];
1023
        $return['question'] = $row['survey_question'];
1024
        $return['horizontalvertical'] = $row['display'];
1025
        $return['shared_question_id'] = $row['shared_question_id'];
1026
        $return['maximum_score'] = $row['max_value'];
1027
        $return['is_required'] = api_get_configuration_value('allow_required_survey_questions')
1028
            ? $row['is_required']
1029
            : false;
1030
1031
        if ($row['survey_group_pri'] != 0) {
1032
            $return['assigned'] = $row['survey_group_pri'];
1033
            $return['choose'] = 1;
1034
        } else {
1035
            $return['assigned1'] = $row['survey_group_sec1'];
1036
            $return['assigned2'] = $row['survey_group_sec2'];
1037
            $return['choose'] = 2;
1038
        }
1039
1040
        // Getting the information of the question options
1041
        $result = Database::query($sqlOption);
1042
        $counter = 0;
1043
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1044
            /** @todo this should be renamed to options instead of answers */
1045
            $return['answers'][] = $row['option_text'];
1046
            $return['values'][] = $row['value'];
1047
1048
            $return['answer_data'][$counter]['data'] = $row['option_text'];
1049
            $return['answer_data'][$counter]['iid'] = $row['iid'];
1050
1051
            /** @todo this can be done more elegantly (used in reporting) */
1052
            $return['answersid'][] = $row['question_option_id'];
1053
            $counter++;
1054
        }
1055
1056
        return $return;
1057
    }
1058
1059
    /**
1060
     * This function gets all the question of any given survey.
1061
     *
1062
     * @param int $surveyId the id of the survey
1063
     * @param int $courseId
1064
     *
1065
     * @return array containing all the questions of the survey
1066
     *
1067
     * @author Patrick Cool <[email protected]>, Ghent University
1068
     *
1069
     * @version February 2007
1070
     *
1071
     * @todo one sql call should do the trick
1072
     */
1073
    public static function get_questions($surveyId, $courseId = 0)
1074
    {
1075
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1076
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1077
1078
        $courseId = (int) $courseId;
1079
        $surveyId = (int) $surveyId;
1080
1081
        if (empty($courseId)) {
1082
            $courseId = api_get_course_int_id();
1083
        }
1084
1085
        // Getting the information of the question
1086
        $sql = "SELECT * FROM $tbl_survey_question
1087
		        WHERE c_id = $courseId AND survey_id= $surveyId ";
1088
        $result = Database::query($sql);
1089
        $questions = [];
1090
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1091
            $questionId = $row['question_id'];
1092
            $questions[$questionId]['survey_id'] = $surveyId;
1093
            $questions[$questionId]['question_id'] = $questionId;
1094
            $questions[$questionId]['type'] = $row['type'];
1095
            $questions[$questionId]['question'] = $row['survey_question'];
1096
            $questions[$questionId]['horizontalvertical'] = $row['display'];
1097
            $questions[$questionId]['maximum_score'] = $row['max_value'];
1098
            $questions[$questionId]['sort'] = $row['sort'];
1099
            $questions[$questionId]['survey_question_comment'] = $row['survey_question_comment'];
1100
1101
            // Getting the information of the question options
1102
            $sql = "SELECT * FROM $table_survey_question_option
1103
		             WHERE c_id = $courseId AND survey_id= $surveyId  AND question_id = $questionId";
1104
            $resultOptions = Database::query($sql);
1105
            while ($rowOption = Database::fetch_array($resultOptions, 'ASSOC')) {
1106
                $questions[$questionId]['answers'][] = $rowOption['option_text'];
1107
            }
1108
        }
1109
1110
        return $questions;
1111
    }
1112
1113
    /**
1114
     * This function saves a question in the database.
1115
     * This can be either an update of an existing survey or storing a new survey.
1116
     *
1117
     * @param array $survey_data
1118
     * @param array $form_content all the information of the form
1119
     *
1120
     * @return string
1121
     *
1122
     * @author Patrick Cool <[email protected]>, Ghent University
1123
     *
1124
     * @version January 2007
1125
     */
1126
    public static function save_question($survey_data, $form_content, $showMessage = true, $dataFromDatabase = [])
1127
    {
1128
        $return_message = '';
1129
        if (strlen($form_content['question']) > 1) {
1130
            // Checks length of the question
1131
            $empty_answer = false;
1132
            if ($survey_data['survey_type'] == 1) {
1133
                if (empty($form_content['choose'])) {
1134
                    return 'PleaseChooseACondition';
1135
                }
1136
1137
                if (($form_content['choose'] == 2) &&
1138
                    ($form_content['assigned1'] == $form_content['assigned2'])
1139
                ) {
1140
                    return 'ChooseDifferentCategories';
1141
                }
1142
            }
1143
1144
            if ($form_content['type'] !== 'percentage') {
1145
                if (isset($form_content['answers'])) {
1146
                    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...
1147
                        if (strlen($form_content['answers'][$i]) < 1) {
1148
                            $empty_answer = true;
1149
                            break;
1150
                        }
1151
                    }
1152
                }
1153
            }
1154
1155
            if ($form_content['type'] === 'score') {
1156
                if (strlen($form_content['maximum_score']) < 1) {
1157
                    $empty_answer = true;
1158
                }
1159
            }
1160
1161
            $course_id = api_get_course_int_id();
1162
1163
            if (!$empty_answer) {
1164
                // Table definitions
1165
                $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1166
1167
                // Getting all the information of the survey
1168
                $survey_data = self::get_survey($form_content['survey_id']);
1169
1170
                // Storing the question in the shared database
1171
                if (is_numeric($survey_data['survey_share']) && $survey_data['survey_share'] != 0) {
1172
                    $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

1172
                    /** @scrutinizer ignore-call */ 
1173
                    $shared_question_id = self::save_shared_question($form_content, $survey_data);
Loading history...
1173
                    $form_content['shared_question_id'] = $shared_question_id;
1174
                }
1175
1176
                // Storing a new question
1177
                if ($form_content['question_id'] == '' || !is_numeric($form_content['question_id'])) {
1178
                    // Finding the max sort order of the questions in the given survey
1179
                    $sql = "SELECT max(sort) AS max_sort
1180
					        FROM $tbl_survey_question
1181
                            WHERE c_id = $course_id AND survey_id='".intval($form_content['survey_id'])."'";
1182
                    $result = Database::query($sql);
1183
                    $row = Database::fetch_array($result, 'ASSOC');
1184
                    $max_sort = $row['max_sort'];
1185
1186
                    // Some variables defined for survey-test type
1187
                    $extraParams = [];
1188
                    if (isset($_POST['choose'])) {
1189
                        if ($_POST['choose'] == 1) {
1190
                            $extraParams['survey_group_pri'] = $_POST['assigned'];
1191
                        } elseif ($_POST['choose'] == 2) {
1192
                            $extraParams['survey_group_sec1'] = $_POST['assigned1'];
1193
                            $extraParams['survey_group_sec2'] = $_POST['assigned2'];
1194
                        }
1195
                    }
1196
1197
                    $questionComment = isset($form_content['question_comment']) ? $form_content['question_comment'] : '';
1198
                    $maxScore = isset($form_content['maximum_score']) ? $form_content['maximum_score'] : '';
1199
                    $display = isset($form_content['horizontalvertical']) ? $form_content['horizontalvertical'] : '';
1200
1201
                    $params = [
1202
                        'c_id' => $course_id,
1203
                        'survey_id' => $form_content['survey_id'],
1204
                        'survey_question' => $form_content['question'],
1205
                        'survey_question_comment' => $questionComment,
1206
                        'type' => $form_content['type'],
1207
                        'display' => $display,
1208
                        'sort' => $max_sort + 1,
1209
                        'shared_question_id' => $form_content['shared_question_id'],
1210
                        'max_value' => $maxScore,
1211
                    ];
1212
1213
                    if (api_get_configuration_value('allow_required_survey_questions')) {
1214
                        $params['is_required'] = isset($form_content['is_required']);
1215
                    }
1216
1217
                    $params = array_merge($params, $extraParams);
1218
                    $question_id = Database::insert($tbl_survey_question, $params);
1219
                    if ($question_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $question_id of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1220
                        $sql = "UPDATE $tbl_survey_question SET question_id = $question_id
1221
                                WHERE iid = $question_id";
1222
                        Database::query($sql);
1223
1224
                        $form_content['question_id'] = $question_id;
1225
                        $return_message = 'QuestionAdded';
1226
                    }
1227
                } else {
1228
                    // Updating an existing question
1229
                    $extraParams = [];
1230
                    if (isset($_POST['choose'])) {
1231
                        if ($_POST['choose'] == 1) {
1232
                            $extraParams['survey_group_pri'] = $_POST['assigned'];
1233
                            $extraParams['survey_group_sec1'] = 0;
1234
                            $extraParams['survey_group_sec2'] = 0;
1235
                        } elseif ($_POST['choose'] == 2) {
1236
                            $extraParams['survey_group_pri'] = 0;
1237
                            $extraParams['survey_group_sec1'] = $_POST['assigned1'];
1238
                            $extraParams['survey_group_sec2'] = $_POST['assigned2'];
1239
                        }
1240
                    }
1241
1242
                    $maxScore = isset($form_content['maximum_score']) ? $form_content['maximum_score'] : null;
1243
                    $questionComment = isset($form_content['question_comment'])
1244
                        ? $form_content['question_comment']
1245
                        : null;
1246
1247
                    // Adding the question to the survey_question table
1248
                    $params = [
1249
                        'survey_question' => $form_content['question'],
1250
                        'survey_question_comment' => $questionComment,
1251
                        'display' => $form_content['horizontalvertical'],
1252
                    ];
1253
1254
                    if (api_get_configuration_value('allow_required_survey_questions')) {
1255
                        $params['is_required'] = isset($form_content['is_required']);
1256
                    }
1257
1258
                    $params = array_merge($params, $extraParams);
1259
                    Database::update(
1260
                        $tbl_survey_question,
1261
                        $params,
1262
                        [
1263
                            'c_id = ? AND question_id = ?' => [
1264
                                $course_id,
1265
                                $form_content['question_id'],
1266
                            ],
1267
                        ]
1268
                    );
1269
                    $return_message = 'QuestionUpdated';
1270
                }
1271
1272
                if (!empty($form_content['survey_id'])) {
1273
                    // Updating survey
1274
                    api_item_property_update(
1275
                        api_get_course_info(),
1276
                        TOOL_SURVEY,
1277
                        $form_content['survey_id'],
1278
                        'SurveyUpdated',
1279
                        api_get_user_id()
1280
                    );
1281
                }
1282
1283
                // Storing the options of the question
1284
                self::save_question_options($form_content, $survey_data, $dataFromDatabase);
1285
            } else {
1286
                $return_message = 'PleasFillAllAnswer';
1287
            }
1288
        } else {
1289
            $return_message = 'PleaseEnterAQuestion';
1290
        }
1291
1292
        if ($showMessage) {
1293
            if (!empty($return_message)) {
1294
                Display::addFlash(Display::return_message(get_lang($return_message)));
1295
            }
1296
        }
1297
1298
        return $return_message;
1299
    }
1300
1301
    /**
1302
     * This function saves the question in the shared database.
1303
     *
1304
     * @param array $form_content all the information of the form
1305
     * @param array $survey_data  all the information of the survey
1306
     *
1307
     * @author Patrick Cool <[email protected]>, Ghent University
1308
     *
1309
     * @version February 2007
1310
     *
1311
     * @return int
1312
     *
1313
     * @todo editing of a shared question
1314
     */
1315
    public function save_shared_question($form_content, $survey_data)
1316
    {
1317
        $_course = api_get_course_info();
1318
1319
        // Table definitions
1320
        $tbl_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1321
1322
        // Storing a new question
1323
        if ($form_content['shared_question_id'] == '' ||
1324
            !is_numeric($form_content['shared_question_id'])
1325
        ) {
1326
            // Finding the max sort order of the questions in the given survey
1327
            $sql = "SELECT max(sort) AS max_sort FROM $tbl_survey_question
1328
                    WHERE survey_id='".intval($survey_data['survey_share'])."'
1329
                    AND code='".Database::escape_string($_course['id'])."'";
1330
            $result = Database::query($sql);
1331
            $row = Database::fetch_array($result, 'ASSOC');
1332
            $max_sort = $row['max_sort'];
1333
1334
            // Adding the question to the survey_question table
1335
            $sql = "INSERT INTO $tbl_survey_question (survey_id, survey_question, survey_question_comment, type, display, sort, code) VALUES (
1336
                    '".Database::escape_string($survey_data['survey_share'])."',
1337
                    '".Database::escape_string($form_content['question'])."',
1338
                    '".Database::escape_string($form_content['question_comment'])."',
1339
                    '".Database::escape_string($form_content['type'])."',
1340
                    '".Database::escape_string($form_content['horizontalvertical'])."',
1341
                    '".Database::escape_string($max_sort + 1)."',
1342
                    '".Database::escape_string($_course['id'])."')";
1343
            Database::query($sql);
1344
            $shared_question_id = Database::insert_id();
1345
        } else {
1346
            // Updating an existing question
1347
            // adding the question to the survey_question table
1348
            $sql = "UPDATE $tbl_survey_question SET
1349
                        survey_question = '".Database::escape_string($form_content['question'])."',
1350
                        survey_question_comment = '".Database::escape_string($form_content['question_comment'])."',
1351
                        display = '".Database::escape_string($form_content['horizontalvertical'])."'
1352
                    WHERE
1353
                        question_id = '".intval($form_content['shared_question_id'])."' AND
1354
                        code = '".Database::escape_string($_course['id'])."'";
1355
            Database::query($sql);
1356
            $shared_question_id = $form_content['shared_question_id'];
1357
        }
1358
1359
        return $shared_question_id;
1360
    }
1361
1362
    /**
1363
     * This functions moves a question of a survey up or down.
1364
     *
1365
     * @param string $direction
1366
     * @param int    $survey_question_id
1367
     * @param int    $survey_id
1368
     *
1369
     * @author Patrick Cool <[email protected]>, Ghent University
1370
     *
1371
     * @version January 2007
1372
     */
1373
    public static function move_survey_question(
1374
        $direction,
1375
        $survey_question_id,
1376
        $survey_id
1377
    ) {
1378
        // Table definition
1379
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1380
        $course_id = api_get_course_int_id();
1381
1382
        if ($direction == 'moveup') {
1383
            $sort = 'DESC';
1384
        }
1385
        if ($direction == 'movedown') {
1386
            $sort = 'ASC';
1387
        }
1388
1389
        $survey_id = (int) $survey_id;
1390
1391
        // Finding the two questions that needs to be swapped
1392
        $sql = "SELECT * FROM $table_survey_question
1393
		        WHERE c_id = $course_id AND survey_id='".$survey_id."'
1394
		        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...
1395
        $result = Database::query($sql);
1396
        $found = false;
1397
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1398
            if ($found) {
1399
                $question_id_two = $row['question_id'];
1400
                $question_sort_two = $row['sort'];
1401
                $found = false;
1402
            }
1403
            if ($row['question_id'] == $survey_question_id) {
1404
                $found = true;
1405
                $question_id_one = $row['question_id'];
1406
                $question_sort_one = $row['sort'];
1407
            }
1408
        }
1409
1410
        $sql = "UPDATE $table_survey_question
1411
                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...
1412
		        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...
1413
        Database::query($sql);
1414
1415
        $sql = "UPDATE $table_survey_question
1416
                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...
1417
		        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...
1418
        Database::query($sql);
1419
    }
1420
1421
    /**
1422
     * This function deletes all the questions of a given survey
1423
     * This function is normally only called when a survey is deleted.
1424
     *
1425
     * @param int $survey_id the id of the survey that has to be deleted
1426
     *
1427
     * @return bool
1428
     *
1429
     * @author Patrick Cool <[email protected]>, Ghent University
1430
     *
1431
     * @version January 2007
1432
     */
1433
    public static function delete_all_survey_questions($survey_id, $shared = false)
1434
    {
1435
        $course_id = api_get_course_int_id();
1436
        $survey_id = (int) $survey_id;
1437
1438
        // Table definitions
1439
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1440
        $course_condition = " c_id = $course_id AND ";
1441
        if ($shared) {
1442
            $course_condition = '';
1443
            $table_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1444
        }
1445
1446
        $sql = "DELETE FROM $table_survey_question
1447
		        WHERE $course_condition survey_id = '".$survey_id."'";
1448
1449
        // Deleting the survey questions
1450
        Database::query($sql);
1451
1452
        // Deleting all the options of the questions of the survey
1453
        self::delete_all_survey_questions_options($survey_id, $shared);
1454
1455
        // Deleting all the answers on this survey
1456
        self::delete_all_survey_answers($survey_id);
1457
1458
        return true;
1459
    }
1460
1461
    /**
1462
     * This function deletes a survey question and all its options.
1463
     *
1464
     * @param int  $survey_id   the id of the survey
1465
     * @param int  $question_id the id of the question
1466
     * @param bool $shared
1467
     *
1468
     * @todo also delete the answers to this question
1469
     *
1470
     * @author Patrick Cool <[email protected]>, Ghent University
1471
     *
1472
     * @version March 2007
1473
     */
1474
    public static function delete_survey_question($survey_id, $question_id, $shared = false)
1475
    {
1476
        $survey_id = (int) $survey_id;
1477
        $question_id = (int) $question_id;
1478
        $course_id = api_get_course_int_id();
1479
1480
        if ($shared) {
1481
            self::delete_shared_survey_question($survey_id, $question_id);
1482
        }
1483
1484
        // Table definitions
1485
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
1486
        // Deleting the survey questions
1487
        $sql = "DELETE FROM $table
1488
		        WHERE
1489
		            c_id = $course_id AND
1490
		            survey_id='".$survey_id."' AND
1491
		            question_id='".$question_id."'";
1492
        Database::query($sql);
1493
1494
        // Deleting the options of the question of the survey
1495
        self::delete_survey_question_option($survey_id, $question_id, $shared);
1496
    }
1497
1498
    /**
1499
     * This function deletes a shared survey question from the main database and all its options.
1500
     *
1501
     * @param int $question_id the id of the question
1502
     *
1503
     * @todo delete all the options of this question
1504
     *
1505
     * @author Patrick Cool <[email protected]>, Ghent University
1506
     *
1507
     * @version March 2007
1508
     */
1509
    public static function delete_shared_survey_question($survey_id, $question_id)
0 ignored issues
show
Unused Code introduced by
The parameter $survey_id is not used and could be removed. ( Ignorable by Annotation )

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

1509
    public static function delete_shared_survey_question(/** @scrutinizer ignore-unused */ $survey_id, $question_id)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1510
    {
1511
        // Table definitions
1512
        $table_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1513
        $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1514
1515
        // First we have to get the shared_question_id
1516
        $question_data = self::get_question($question_id);
1517
1518
        // Deleting the survey questions
1519
        $sql = "DELETE FROM $table_survey_question
1520
		        WHERE question_id='".intval($question_data['shared_question_id'])."'";
1521
        Database::query($sql);
1522
1523
        // Deleting the options of the question of the survey question
1524
        $sql = "DELETE FROM $table_survey_question_option
1525
		        WHERE question_id='".intval($question_data['shared_question_id'])."'";
1526
        Database::query($sql);
1527
    }
1528
1529
    /**
1530
     * This function stores the options of the questions in the table.
1531
     *
1532
     * @param array $form_content
1533
     *
1534
     * @author Patrick Cool <[email protected]>, Ghent University
1535
     *
1536
     * @version January 2007
1537
     *
1538
     * @todo writing the update statement when editing a question
1539
     */
1540
    public static function save_question_options($form_content, $survey_data, $dataFromDatabase = [])
1541
    {
1542
        $course_id = api_get_course_int_id();
1543
        $type = $form_content['type'];
1544
1545
        // A percentage question type has options 1 -> 100
1546
        if ($type === 'percentage') {
1547
            for ($i = 1; $i < 101; $i++) {
1548
                $form_content['answers'][] = $i;
1549
            }
1550
        }
1551
1552
        if (is_numeric($survey_data['survey_share']) && $survey_data['survey_share'] != 0) {
1553
            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

1553
            self::/** @scrutinizer ignore-call */ 
1554
                  save_shared_question_options($form_content, $survey_data);
Loading history...
1554
        }
1555
1556
        // Table definition
1557
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1558
1559
        // We are editing a question so we first have to remove all the existing options from the database
1560
        $optionsToDelete = [];
1561
        if (isset($dataFromDatabase['answer_data'])) {
1562
            foreach ($dataFromDatabase['answer_data'] as $data) {
1563
                if ('other' === $data['data'] && 'multiplechoiceother' === $type) {
1564
                    continue;
1565
                }
1566
1567
                if (!in_array($data['iid'], $form_content['answersid'])) {
1568
                    $optionsToDelete[] = $data['iid'];
1569
                }
1570
            }
1571
        }
1572
1573
        if (!empty($optionsToDelete)) {
1574
            foreach ($optionsToDelete as $iid) {
1575
                $iid = (int) $iid;
1576
                $sql = "DELETE FROM $table
1577
			            WHERE
1578
			                iid = $iid AND
1579
			                c_id = $course_id AND
1580
                            question_id = '".intval($form_content['question_id'])."'
1581
                            ";
1582
                Database::query($sql);
1583
            }
1584
        }
1585
1586
        $counter = 1;
1587
        if (isset($form_content['answers']) && is_array($form_content['answers'])) {
1588
            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...
1589
                $values = isset($form_content['values']) ? $form_content['values'][$i] : '';
1590
                $answerId = 0;
1591
                if (isset($form_content['answersid']) && isset($form_content['answersid'][$i])) {
1592
                    $answerId = $form_content['answersid'][$i];
1593
                }
1594
                if (empty($answerId)) {
1595
                    $params = [
1596
                        'c_id' => $course_id,
1597
                        'question_id' => $form_content['question_id'],
1598
                        'survey_id' => $form_content['survey_id'],
1599
                        'option_text' => $form_content['answers'][$i],
1600
                        'value' => $values,
1601
                        'sort' => $counter,
1602
                    ];
1603
                    $insertId = Database::insert($table, $params);
1604
                    if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1605
                        $sql = "UPDATE $table
1606
                                SET question_option_id = $insertId
1607
                                WHERE iid = $insertId";
1608
                        Database::query($sql);
1609
                        $counter++;
1610
                    }
1611
                } else {
1612
                    $params = [
1613
                        'option_text' => $form_content['answers'][$i],
1614
                        'value' => $values,
1615
                        'sort' => $counter,
1616
                    ];
1617
                    Database::update($table, $params, ['iid = ?' => [$answerId]]);
1618
                    $counter++;
1619
                }
1620
            }
1621
        }
1622
1623
        if ('multiplechoiceother' === $type) {
1624
            // First time creation
1625
            if (empty($dataFromDatabase['answer_data'])) {
1626
                $params = [
1627
                    'c_id' => $course_id,
1628
                    'question_id' => $form_content['question_id'],
1629
                    'survey_id' => $form_content['survey_id'],
1630
                    'option_text' => 'other',
1631
                    'value' => 0,
1632
                    'sort' => $counter,
1633
                ];
1634
                $insertId = Database::insert($table, $params);
1635
                if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1636
                    $sql = "UPDATE $table
1637
                            SET question_option_id = $insertId
1638
                            WHERE iid = $insertId";
1639
                    Database::query($sql);
1640
                }
1641
            } else {
1642
                $params = [
1643
                    'option_text' => 'other',
1644
                    'value' => 0,
1645
                    'sort' => $counter,
1646
                ];
1647
                Database::update(
1648
                    $table,
1649
                    $params,
1650
                    [
1651
                        'c_id = ? AND question_id = ? AND survey_id = ? AND option_text = ?' => [
1652
                            $course_id,
1653
                            $form_content['question_id'],
1654
                            $form_content['survey_id'],
1655
                            'other',
1656
                        ],
1657
                    ]
1658
                );
1659
            }
1660
        }
1661
    }
1662
1663
    /**
1664
     * This function stores the options of the questions in the shared table.
1665
     *
1666
     * @param array $form_content
1667
     *
1668
     * @author Patrick Cool <[email protected]>, Ghent University
1669
     *
1670
     * @version February 2007
1671
     *
1672
     * @todo writing the update statement when editing a question
1673
     */
1674
    public function save_shared_question_options($form_content, $survey_data)
1675
    {
1676
        if (is_array($form_content) && is_array($form_content['answers'])) {
1677
            // Table definition
1678
            $table = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1679
1680
            // We are editing a question so we first have to remove all the existing options from the database
1681
            $sql = "DELETE FROM $table
1682
                    WHERE question_id = '".Database::escape_string($form_content['shared_question_id'])."'";
1683
            Database::query($sql);
1684
1685
            $counter = 1;
1686
            foreach ($form_content['answers'] as &$answer) {
1687
                $params = [
1688
                    'question_id' => $form_content['shared_question_id'],
1689
                    'survey_id' => $survey_data['is_shared'],
1690
                    'option_text' => $answer,
1691
                    'sort' => $counter,
1692
                ];
1693
                Database::insert($table, $params);
1694
1695
                $counter++;
1696
            }
1697
        }
1698
    }
1699
1700
    /**
1701
     * This function deletes all the options of the questions of a given survey
1702
     * This function is normally only called when a survey is deleted.
1703
     *
1704
     * @param int $survey_id the id of the survey that has to be deleted
1705
     *
1706
     * @return true
1707
     *
1708
     * @author Patrick Cool <[email protected]>, Ghent University
1709
     *
1710
     * @version January 2007
1711
     */
1712
    public static function delete_all_survey_questions_options($survey_id, $shared = false)
1713
    {
1714
        // Table definitions
1715
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1716
        $course_id = api_get_course_int_id();
1717
        $course_condition = " c_id = $course_id AND ";
1718
        if ($shared) {
1719
            $course_condition = '';
1720
            $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1721
        }
1722
1723
        $sql = "DELETE FROM $table_survey_question_option
1724
                WHERE $course_condition survey_id='".intval($survey_id)."'";
1725
1726
        // Deleting the options of the survey questions
1727
        Database::query($sql);
1728
1729
        return true;
1730
    }
1731
1732
    /**
1733
     * This function deletes the options of a given question.
1734
     *
1735
     * @param int  $survey_id
1736
     * @param int  $question_id
1737
     * @param bool $shared
1738
     *
1739
     * @return bool
1740
     *
1741
     * @author Patrick Cool <[email protected]>, Ghent University
1742
     * @author Julio Montoya
1743
     *
1744
     * @version March 2007
1745
     */
1746
    public static function delete_survey_question_option(
1747
        $survey_id,
1748
        $question_id,
1749
        $shared = false
1750
    ) {
1751
        $course_id = api_get_course_int_id();
1752
        $course_condition = " c_id = $course_id AND ";
1753
1754
        // Table definitions
1755
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1756
        if ($shared) {
1757
            $course_condition = '';
1758
            $table = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1759
        }
1760
1761
        // Deleting the options of the survey questions
1762
        $sql = "DELETE FROM $table
1763
		        WHERE
1764
		            $course_condition survey_id='".intval($survey_id)."' AND
1765
		            question_id='".intval($question_id)."'";
1766
        Database::query($sql);
1767
1768
        return true;
1769
    }
1770
1771
    /**
1772
     * SURVEY ANSWERS FUNCTIONS.
1773
     */
1774
1775
    /**
1776
     * This function deletes all the answers anyone has given on this survey
1777
     * This function is normally only called when a survey is deleted.
1778
     *
1779
     * @param $survey_id the id of the survey that has to be deleted
1780
     *
1781
     * @return true
1782
     *
1783
     * @todo write the function
1784
     *
1785
     * @author Patrick Cool <[email protected]>, Ghent University
1786
     *
1787
     * @version January 2007,december 2008
1788
     */
1789
    public static function delete_all_survey_answers($survey_id)
1790
    {
1791
        $course_id = api_get_course_int_id();
1792
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
1793
        $survey_id = (int) $survey_id;
1794
        $sql = "DELETE FROM $table
1795
                WHERE c_id = $course_id AND survey_id = $survey_id";
1796
        Database::query($sql);
1797
1798
        return true;
1799
    }
1800
1801
    /**
1802
     * @param int $user_id
1803
     * @param int $survey_id
1804
     * @param int $course_id
1805
     *
1806
     * @return bool
1807
     */
1808
    public static function is_user_filled_survey($user_id, $survey_id, $course_id)
1809
    {
1810
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
1811
        $user_id = (int) $user_id;
1812
        $course_id = (int) $course_id;
1813
        $survey_id = (int) $survey_id;
1814
1815
        $sql = "SELECT DISTINCT user
1816
                FROM $table
1817
                WHERE
1818
                    c_id		= $course_id AND
1819
                    user		= $user_id AND
1820
                    survey_id	= $survey_id";
1821
        $result = Database::query($sql);
1822
        if (Database::num_rows($result)) {
1823
            return true;
1824
        }
1825
1826
        return false;
1827
    }
1828
1829
    /**
1830
     * This function gets all the persons who have filled the survey.
1831
     *
1832
     * @param int $survey_id
1833
     *
1834
     * @return array
1835
     *
1836
     * @author Patrick Cool <[email protected]>, Ghent University
1837
     *
1838
     * @version February 2007
1839
     */
1840
    public static function get_people_who_filled_survey(
1841
        $survey_id,
1842
        $all_user_info = false,
1843
        $course_id = null
1844
    ) {
1845
        // Database table definition
1846
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1847
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1848
1849
        // Variable initialisation
1850
        $return = [];
1851
1852
        if (empty($course_id)) {
1853
            $course_id = api_get_course_int_id();
1854
        } else {
1855
            $course_id = (int) $course_id;
1856
        }
1857
1858
        $survey_id = (int) $survey_id;
1859
1860
        if ($all_user_info) {
1861
            $order_clause = api_sort_by_first_name()
1862
                ? ' ORDER BY user.firstname, user.lastname'
1863
                : ' ORDER BY user.lastname, user.firstname';
1864
            $sql = "SELECT DISTINCT
1865
			            answered_user.user as invited_user,
1866
			            user.firstname,
1867
			            user.lastname,
1868
			            user.user_id
1869
                    FROM $table_survey_answer answered_user
1870
                    LEFT JOIN $table_user as user ON answered_user.user = user.user_id
1871
                    WHERE
1872
                        answered_user.c_id = $course_id AND
1873
                        survey_id= '".$survey_id."' ".
1874
                $order_clause;
1875
        } else {
1876
            $sql = "SELECT DISTINCT user FROM $table_survey_answer
1877
			        WHERE c_id = $course_id AND survey_id= '".$survey_id."'  ";
1878
1879
            if (api_get_configuration_value('survey_anonymous_show_answered')) {
1880
                $tblInvitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
1881
                $tblSurvey = Database::get_course_table(TABLE_SURVEY);
1882
1883
                $sql = "SELECT i.user FROM $tblInvitation i
1884
                    INNER JOIN $tblSurvey s
1885
                    ON i.survey_code = s.code
1886
                        AND i.c_id = s.c_id
1887
                        AND i.session_id = s.session_id
1888
                    WHERE i.answered IS TRUE AND s.iid = $survey_id";
1889
            }
1890
        }
1891
1892
        $res = Database::query($sql);
1893
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1894
            if ($all_user_info) {
1895
                $userInfo = api_get_user_info($row['user_id']);
1896
                $row['user_info'] = $userInfo;
1897
                $return[] = $row;
1898
            } else {
1899
                $return[] = $row['user'];
1900
            }
1901
        }
1902
1903
        return $return;
1904
    }
1905
1906
    /**
1907
     * @return bool
1908
     */
1909
    public static function survey_generation_hash_available()
1910
    {
1911
        if (extension_loaded('mcrypt')) {
1912
            return true;
1913
        }
1914
1915
        return false;
1916
    }
1917
1918
    /**
1919
     * @param int $survey_id
1920
     * @param int $course_id
1921
     * @param int $session_id
1922
     * @param int $group_id
1923
     *
1924
     * @return string
1925
     */
1926
    public static function generate_survey_hash($survey_id, $course_id, $session_id, $group_id)
1927
    {
1928
        return hash('sha512', api_get_security_key().'_'.$course_id.'_'.$session_id.'_'.$group_id.'_'.$survey_id);
1929
    }
1930
1931
    /**
1932
     * @param int    $survey_id
1933
     * @param int    $course_id
1934
     * @param int    $session_id
1935
     * @param int    $group_id
1936
     * @param string $hash
1937
     *
1938
     * @return bool
1939
     */
1940
    public static function validate_survey_hash($survey_id, $course_id, $session_id, $group_id, $hash)
1941
    {
1942
        $generatedHash = self::generate_survey_hash($survey_id, $course_id, $session_id, $group_id);
1943
        if ($generatedHash == $hash) {
1944
            return true;
1945
        }
1946
1947
        return false;
1948
    }
1949
1950
    /**
1951
     * @param int $survey_id
1952
     * @param int $course_id
1953
     * @param int $session_id
1954
     * @param int $group_id
1955
     *
1956
     * @return string
1957
     */
1958
    public static function generate_survey_link(
1959
        $survey_id,
1960
        $course_id,
1961
        $session_id,
1962
        $group_id
1963
    ) {
1964
        $code = self::generate_survey_hash(
1965
            $survey_id,
1966
            $course_id,
1967
            $session_id,
1968
            $group_id
1969
        );
1970
1971
        return api_get_path(WEB_CODE_PATH).'survey/link.php?h='.$code.'&i='.$survey_id.'&c='.intval($course_id).'&s='
1972
            .intval($session_id).'&g='.$group_id;
1973
    }
1974
1975
    /**
1976
     * Check if the current user has mandatory surveys no-answered
1977
     * and redirect to fill the first found survey.
1978
     */
1979
    public static function protectByMandatory()
1980
    {
1981
        if (strpos($_SERVER['SCRIPT_NAME'], 'fillsurvey.php') !== false) {
1982
            return;
1983
        }
1984
1985
        $userId = api_get_user_id();
1986
        $courseId = api_get_course_int_id();
1987
        $sessionId = api_get_session_id();
1988
1989
        if (!$userId) {
1990
            return;
1991
        }
1992
1993
        if (!$courseId) {
1994
            return;
1995
        }
1996
1997
        try {
1998
            /** @var CSurveyInvitation $invitation */
1999
            $invitation = Database::getManager()
2000
                ->createQuery("
2001
                    SELECT i FROM ChamiloCourseBundle:CSurveyInvitation i
2002
                    INNER JOIN ChamiloCourseBundle:CSurvey s
2003
                        WITH (s.code = i.surveyCode AND s.cId = i.cId AND s.sessionId = i.sessionId)
2004
                    INNER JOIN ChamiloCoreBundle:ExtraFieldValues efv WITH efv.itemId = s.iid
2005
                    INNER JOIN ChamiloCoreBundle:ExtraField ef WITH efv.field = ef.id
2006
                    WHERE
2007
                        i.answered = 0 AND
2008
                        i.cId = :course AND
2009
                        i.user = :user AND
2010
                        i.sessionId = :session AND
2011
                        :now BETWEEN s.availFrom AND s.availTill AND
2012
                        ef.variable = :variable AND
2013
                        efv.value = 1 AND
2014
                        s.surveyType != 3
2015
                    ORDER BY s.availTill ASC
2016
                ")
2017
                ->setMaxResults(1)
2018
                ->setParameters([
2019
                    'course' => $courseId,
2020
                    'user' => $userId,
2021
                    'session' => $sessionId,
2022
                    'now' => new DateTime('UTC', new DateTimeZone('UTC')),
2023
                    'variable' => 'is_mandatory',
2024
                ])
2025
                ->getSingleResult();
2026
        } catch (Exception $e) {
2027
            $invitation = null;
2028
        }
2029
2030
        if (!$invitation) {
2031
            return;
2032
        }
2033
2034
        Display::addFlash(
2035
            Display::return_message(get_lang('MandatorySurveyNoAnswered'), 'warning')
2036
        );
2037
2038
        $url = SurveyUtil::generateFillSurveyLink(
2039
            $invitation->getInvitationCode(),
2040
            api_get_course_info(),
2041
            api_get_session_id()
2042
        );
2043
2044
        header('Location: '.$url);
2045
        exit;
2046
    }
2047
2048
    /**
2049
     * This function empty surveys (invitations and answers).
2050
     *
2051
     * @param int $surveyId id of the survey to empty
2052
     *
2053
     * @return bool
2054
     */
2055
    public static function emptySurveyFromId($surveyId)
2056
    {
2057
        // Database table definitions
2058
        $surveyInvitationTable = Database:: get_course_table(TABLE_SURVEY_INVITATION);
2059
        $surveyAnswerTable = Database:: get_course_table(TABLE_SURVEY_ANSWER);
2060
        $surveyTable = Database:: get_course_table(TABLE_SURVEY);
2061
        $surveyId = (int) $surveyId;
2062
        $surveyData = self::get_survey($surveyId);
2063
        if (empty($surveyData)) {
2064
            return false;
2065
        }
2066
2067
        $surveyCode = $surveyData['survey_code'];
2068
        $courseId = (int) $surveyData['c_id'];
2069
        $sessionId = (int) $surveyData['session_id'];
2070
2071
        $sql = "DELETE FROM $surveyInvitationTable
2072
                WHERE session_id = $sessionId AND c_id = $courseId AND survey_code = '$surveyCode' ";
2073
        Database::query($sql);
2074
2075
        $sql = "DELETE FROM $surveyAnswerTable
2076
               WHERE survey_id = $surveyId AND c_id = $courseId ";
2077
        Database::query($sql);
2078
2079
        $sql = "UPDATE $surveyTable
2080
                SET invited = 0, answered = 0
2081
                WHERE survey_id = $surveyId AND c_id = $courseId AND session_id = $sessionId ";
2082
        Database::query($sql);
2083
2084
        return true;
2085
    }
2086
2087
    /**
2088
     * This function copy survey specifying course id and session id where will be copied.
2089
     *
2090
     * @param int $surveyId
2091
     * @param int $targetCourseId  target course id
2092
     * @param int $targetSessionId target session id
2093
     *
2094
     * @return bool|int when fails or return the new survey id
2095
     */
2096
    public static function copySurveySession($surveyId, $targetCourseId, $targetSessionId)
2097
    {
2098
        // Database table definitions
2099
        $surveyTable = Database::get_course_table(TABLE_SURVEY);
2100
        $surveyQuestionGroupTable = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
2101
        $surveyQuestionTable = Database::get_course_table(TABLE_SURVEY_QUESTION);
2102
        $surveyOptionsTable = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2103
        $surveyId = (int) $surveyId;
2104
        $targetCourseId = (int) $targetCourseId;
2105
        $targetSessionId = (int) $targetSessionId;
2106
2107
        $surveyData = self::get_survey($surveyId, 0, '', true);
2108
        if (empty($surveyData) || empty($targetCourseId)) {
2109
            return false;
2110
        }
2111
2112
        $originalCourseId = $surveyData['c_id'];
2113
        $originalSessionId = $surveyData['session_id'];
2114
2115
        $surveyData['code'] = self::generate_unique_code($surveyData['code']);
2116
        $surveyData['c_id'] = $targetCourseId;
2117
        $surveyData['session_id'] = $targetSessionId;
2118
        // Add a "Copy" suffix if copied inside the same course
2119
        if ($targetCourseId == $originalCourseId) {
2120
            $surveyData['title'] = $surveyData['title'].' '.get_lang('Copy');
2121
        }
2122
        unset($surveyData['iid']);
2123
        unset($surveyData['id']);
2124
2125
        $newSurveyId = Database::insert($surveyTable, $surveyData);
2126
2127
        if ($newSurveyId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $newSurveyId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2128
            $sql = "UPDATE $surveyTable SET survey_id = $newSurveyId
2129
                    WHERE iid = $newSurveyId";
2130
            Database::query($sql);
2131
2132
            $sql = "SELECT * FROM $surveyQuestionGroupTable
2133
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId ";
2134
            $res = Database::query($sql);
2135
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2136
                $params = [
2137
                    'c_id' => $targetCourseId,
2138
                    'name' => $row['name'],
2139
                    'description' => $row['description'],
2140
                    'survey_id' => $newSurveyId,
2141
                ];
2142
                $insertId = Database::insert($surveyQuestionGroupTable, $params);
2143
                if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2144
                    $sql = "UPDATE $surveyQuestionGroupTable SET id = iid WHERE iid = $insertId";
2145
                    Database::query($sql);
2146
                    $group_id[$row['id']] = $insertId;
2147
                }
2148
            }
2149
2150
            // Get questions
2151
            $sql = "SELECT * FROM $surveyQuestionTable
2152
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId";
2153
            $res = Database::query($sql);
2154
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2155
                $params = [
2156
                    'c_id' => $targetCourseId,
2157
                    'survey_id' => $newSurveyId,
2158
                    'survey_question' => $row['survey_question'],
2159
                    'survey_question_comment' => $row['survey_question_comment'],
2160
                    'type' => $row['type'],
2161
                    'display' => $row['display'],
2162
                    'sort' => $row['sort'],
2163
                    'shared_question_id' => $row['shared_question_id'],
2164
                    'max_value' => $row['max_value'],
2165
                    'survey_group_pri' => $row['survey_group_pri'],
2166
                    'survey_group_sec1' => $row['survey_group_sec1'],
2167
                    'survey_group_sec2' => $row['survey_group_sec2'],
2168
                ];
2169
2170
                if (api_get_configuration_value('allow_required_survey_questions')) {
2171
                    if (isset($row['is_required'])) {
2172
                        $params['is_required'] = $row['is_required'];
2173
                    }
2174
                }
2175
2176
                $insertId = Database::insert($surveyQuestionTable, $params);
2177
                if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2178
                    $sql = "UPDATE $surveyQuestionTable
2179
                            SET question_id = iid
2180
                            WHERE iid = $insertId";
2181
                    Database::query($sql);
2182
2183
                    $question_id[$row['question_id']] = $insertId;
2184
                }
2185
            }
2186
2187
            // Get questions options
2188
            $sql = "SELECT * FROM $surveyOptionsTable
2189
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId";
2190
2191
            $res = Database::query($sql);
2192
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2193
                $params = [
2194
                    'c_id' => $targetCourseId,
2195
                    '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...
2196
                    'survey_id' => $newSurveyId,
2197
                    'option_text' => $row['option_text'],
2198
                    'sort' => $row['sort'],
2199
                    'value' => $row['value'],
2200
                ];
2201
                $insertId = Database::insert($surveyOptionsTable, $params);
2202
                if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2203
                    $sql = "UPDATE $surveyOptionsTable SET question_option_id = $insertId WHERE iid = $insertId";
2204
                    Database::query($sql);
2205
                }
2206
            }
2207
2208
            return $newSurveyId;
2209
        }
2210
2211
        return false;
2212
    }
2213
2214
    /**
2215
     * @param array $surveyData
2216
     *
2217
     * @return bool
2218
     */
2219
    public static function removeMultiplicateQuestions($surveyData)
2220
    {
2221
        if (empty($surveyData)) {
2222
            return false;
2223
        }
2224
        $surveyId = $surveyData['survey_id'];
2225
        $courseId = $surveyData['c_id'];
2226
2227
        if (empty($surveyId) || empty($courseId)) {
2228
            return false;
2229
        }
2230
2231
        $questions = self::get_questions($surveyId);
2232
        foreach ($questions as $question) {
2233
            // Questions marked with "geneated" were created using the "multiplicate" feature.
2234
            if ($question['survey_question_comment'] === 'generated') {
2235
                self::delete_survey_question($surveyId, $question['question_id']);
2236
            }
2237
        }
2238
    }
2239
2240
    /**
2241
     * @param array $surveyData
2242
     *
2243
     * @return bool
2244
     */
2245
    public static function multiplicateQuestions($surveyData)
2246
    {
2247
        if (empty($surveyData)) {
2248
            return false;
2249
        }
2250
        $surveyId = $surveyData['survey_id'];
2251
        $courseId = $surveyData['c_id'];
2252
2253
        if (empty($surveyId) || empty($courseId)) {
2254
            return false;
2255
        }
2256
2257
        $questions = self::get_questions($surveyId);
2258
2259
        if (empty($questions)) {
2260
            return false;
2261
        }
2262
2263
        $obj = new UserGroup();
2264
        $options['where'] = [' usergroup.course_id = ? ' => $courseId];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.
Loading history...
2265
        $classList = $obj->getUserGroupInCourse($options);
2266
2267
        $classToParse = [];
2268
        foreach ($classList as $class) {
2269
            $users = $obj->get_users_by_usergroup($class['id']);
2270
            if (empty($users)) {
2271
                continue;
2272
            }
2273
            $classToParse[] = [
2274
                'name' => $class['name'],
2275
                'users' => $users,
2276
            ];
2277
        }
2278
2279
        self::parseMultiplicateUserList($classToParse, $questions, $courseId, $surveyData);
2280
2281
        $extraFieldValue = new ExtraFieldValue('survey');
2282
        $groupData = $extraFieldValue->get_values_by_handler_and_field_variable($surveyId, 'group_id');
2283
        if ($groupData && !empty($groupData['value'])) {
2284
            $groupInfo = GroupManager::get_group_properties($groupData['value']);
2285
            if (!empty($groupInfo)) {
2286
                $users = GroupManager::getStudents($groupInfo['iid'], true);
2287
                if (!empty($users)) {
2288
                    $users = array_column($users, 'id');
2289
                    $classToParse = [
2290
                        [
2291
                            'name' => $groupInfo['name'],
2292
                            'users' => $users,
2293
                        ],
2294
                    ];
2295
                    self::parseMultiplicateUserList($classToParse, $questions, $courseId, $surveyData);
2296
                }
2297
            }
2298
        }
2299
2300
        return true;
2301
    }
2302
2303
    public static function parseMultiplicateUserList($itemList, $questions, $courseId, $surveyData)
2304
    {
2305
        if (empty($itemList) || empty($questions)) {
2306
            return false;
2307
        }
2308
2309
        $surveyId = $surveyData['survey_id'];
2310
        $classTag = '{{class_name}}';
2311
        $studentTag = '{{student_full_name}}';
2312
        $classCounter = 0;
2313
2314
        $newQuestionList = [];
2315
        foreach ($questions as $question) {
2316
            $newQuestionList[$question['sort']] = $question;
2317
        }
2318
        ksort($newQuestionList);
2319
2320
        foreach ($itemList as $class) {
2321
            $className = $class['name'];
2322
            $users = $class['users'];
2323
2324
            foreach ($newQuestionList as $question) {
2325
                $text = $question['question'];
2326
                if (strpos($text, $classTag) !== false) {
2327
                    $replacedText = str_replace($classTag, $className, $text);
2328
                    $values = [
2329
                        'c_id' => $courseId,
2330
                        'question_comment' => 'generated',
2331
                        'type' => $question['type'],
2332
                        'display' => $question['horizontalvertical'],
2333
                        'question' => $replacedText,
2334
                        'survey_id' => $surveyId,
2335
                        'question_id' => 0,
2336
                        'shared_question_id' => 0,
2337
                    ];
2338
                    self::save_question($surveyData, $values, false);
2339
                    $classCounter++;
2340
                    continue;
2341
                }
2342
2343
                foreach ($users as $userId) {
2344
                    $userInfo = api_get_user_info($userId);
2345
                    if (strpos($text, $studentTag) !== false) {
2346
                        $replacedText = str_replace($studentTag, $userInfo['complete_name'], $text);
2347
                        $values = [
2348
                            'c_id' => $courseId,
2349
                            'question_comment' => 'generated',
2350
                            'type' => $question['type'],
2351
                            'display' => $question['horizontalvertical'],
2352
                            'maximum_score' => $question['maximum_score'],
2353
                            'question' => $replacedText,
2354
                            'survey_id' => $surveyId,
2355
                            'question_id' => 0,
2356
                            'shared_question_id' => 0,
2357
                        ];
2358
2359
                        $answers = [];
2360
                        if (!empty($question['answers'])) {
2361
                            foreach ($question['answers'] as $answer) {
2362
                                $replacedText = str_replace($studentTag, $userInfo['complete_name'], $answer);
2363
                                $answers[] = $replacedText;
2364
                            }
2365
                        }
2366
                        $values['answers'] = $answers;
2367
                        self::save_question($surveyData, $values, false);
2368
                    }
2369
                }
2370
2371
                if ($classCounter < count($itemList)) {
2372
                    // Add end page
2373
                    $values = [
2374
                        'c_id' => $courseId,
2375
                        'question_comment' => 'generated',
2376
                        'type' => 'pagebreak',
2377
                        'display' => 'horizontal',
2378
                        'question' => get_lang('QuestionForNextClass'),
2379
                        'survey_id' => $surveyId,
2380
                        'question_id' => 0,
2381
                        'shared_question_id' => 0,
2382
                    ];
2383
                    self::save_question($surveyData, $values, false);
2384
                }
2385
            }
2386
        }
2387
2388
        return true;
2389
    }
2390
2391
    /**
2392
     * @param array $survey
2393
     *
2394
     * @return int
2395
     */
2396
    public static function getCountPages($survey)
2397
    {
2398
        if (empty($survey) || !isset($survey['iid'])) {
2399
            return 0;
2400
        }
2401
2402
        $courseId = $survey['c_id'];
2403
        $surveyId = $survey['survey_id'];
2404
2405
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
2406
2407
        // pagebreak
2408
        $sql = "SELECT COUNT(iid) FROM $table
2409
                WHERE
2410
                    survey_question NOT LIKE '%{{%' AND
2411
                    type = 'pagebreak' AND
2412
                    c_id = $courseId AND
2413
                    survey_id = $surveyId";
2414
        $result = Database::query($sql);
2415
        $numberPageBreaks = Database::result($result, 0, 0);
2416
2417
        // No pagebreak
2418
        $sql = "SELECT COUNT(iid) FROM $table
2419
                WHERE
2420
                    survey_question NOT LIKE '%{{%' AND
2421
                    type != 'pagebreak' AND
2422
                    c_id = $courseId AND
2423
                    survey_id = $surveyId";
2424
        $result = Database::query($sql);
2425
        $countOfQuestions = Database::result($result, 0, 0);
2426
2427
        if ($survey['one_question_per_page'] == 1) {
2428
            if (!empty($countOfQuestions)) {
2429
                return $countOfQuestions;
2430
            }
2431
2432
            return 1;
2433
        }
2434
2435
        if (empty($numberPageBreaks)) {
2436
            return 1;
2437
        }
2438
2439
        return $numberPageBreaks + 1;
2440
    }
2441
2442
    /**
2443
     * Check whether this survey has ended. If so, display message and exit rhis script.
2444
     *
2445
     * @param array $surveyData Survey data
2446
     */
2447
    public static function checkTimeAvailability($surveyData)
2448
    {
2449
        if (empty($surveyData)) {
2450
            api_not_allowed(true);
2451
        }
2452
2453
        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
2454
        $utcZone = new DateTimeZone('UTC');
2455
        $startDate = new DateTime($surveyData['start_date'], $utcZone);
2456
        $endDate = new DateTime($surveyData['end_date'], $utcZone);
2457
        $currentDate = new DateTime('now', $utcZone);
2458
        if (!$allowSurveyAvailabilityDatetime) {
2459
            $currentDate->modify('today');
2460
        }
2461
        if ($currentDate < $startDate) {
2462
            api_not_allowed(
2463
                true,
2464
                Display:: return_message(
2465
                    get_lang('SurveyNotAvailableYet'),
2466
                    'warning',
2467
                    false
2468
                )
2469
            );
2470
        }
2471
2472
        if ($currentDate > $endDate) {
2473
            api_not_allowed(
2474
                true,
2475
                Display:: return_message(
2476
                    get_lang('SurveyNotAvailableAnymore'),
2477
                    'warning',
2478
                    false
2479
                )
2480
            );
2481
        }
2482
    }
2483
2484
    /**
2485
     * @param int    $userId
2486
     * @param string $surveyCode
2487
     * @param int    $courseId
2488
     * @param int    $sessionId
2489
     * @param int    $groupId
2490
     *
2491
     * @return array|CSurveyInvitation[]
2492
     */
2493
    public static function getUserInvitationsForSurveyInCourse(
2494
        $userId,
2495
        $surveyCode,
2496
        $courseId,
2497
        $sessionId = 0,
2498
        $groupId = 0
2499
    ) {
2500
        $invitationRepo = Database::getManager()->getRepository('ChamiloCourseBundle:CSurveyInvitation');
2501
        $invitations = $invitationRepo->findBy(
2502
            [
2503
                'user' => $userId,
2504
                'cId' => $courseId,
2505
                'sessionId' => $sessionId,
2506
                'groupId' => $groupId,
2507
                'surveyCode' => $surveyCode,
2508
            ],
2509
            ['invitationDate' => 'DESC']
2510
        );
2511
2512
        return $invitations;
2513
    }
2514
2515
    /**
2516
     * @param array $userInfo
2517
     * @param int   $answered (1 = answered 0 = not answered)
2518
     *
2519
     * @return string
2520
     */
2521
    public static function surveyReport($userInfo, $answered = 0)
2522
    {
2523
        $userId = isset($userInfo['user_id']) ? (int) $userInfo['user_id'] : 0;
2524
        $answered = (int) $answered;
2525
2526
        if (empty($userId)) {
2527
            return '';
2528
        }
2529
2530
        $em = Database::getManager();
2531
        $repo = $em->getRepository('ChamiloCourseBundle:CSurveyInvitation');
2532
        $repoSurvey = $em->getRepository('ChamiloCourseBundle:CSurvey');
2533
        $invitations = $repo->findBy(['user' => $userId, 'answered' => $answered]);
2534
        $mainUrl = api_get_path(WEB_CODE_PATH).'survey/survey.php?';
2535
        $content = '';
2536
2537
        if (empty($answered)) {
2538
            $content .= Display::page_subheader(get_lang('Unanswered'));
2539
        } else {
2540
            $content .= Display::page_subheader(get_lang('Answered'));
2541
        }
2542
2543
        if (!empty($invitations)) {
2544
            $table = new HTML_Table(['class' => 'table']);
2545
            $table->setHeaderContents(0, 0, get_lang('SurveyName'));
2546
            $table->setHeaderContents(0, 1, get_lang('Course'));
2547
2548
            if (empty($answered)) {
2549
                $table->setHeaderContents(0, 2, get_lang('Survey').' - '.get_lang('EndDate'));
2550
            }
2551
2552
            // Not answered
2553
            /** @var CSurveyInvitation $invitation */
2554
            $row = 1;
2555
            foreach ($invitations as $invitation) {
2556
                $courseId = $invitation->getCId();
2557
                $courseInfo = api_get_course_info_by_id($courseId);
2558
2559
                $courseCode = $courseInfo['code'];
2560
                if (empty($courseInfo)) {
2561
                    continue;
2562
                }
2563
                $sessionId = $invitation->getSessionId();
2564
2565
                if (!empty($answered)) {
2566
                    // check if user is subscribed to the course/session
2567
                    if (empty($sessionId)) {
2568
                        $subscribe = CourseManager::is_user_subscribed_in_course($userId, $courseCode);
2569
                    } else {
2570
                        $subscribe = CourseManager::is_user_subscribed_in_course($userId, $courseCode, true, $sessionId);
2571
                    }
2572
2573
                    // User is not subscribe skip!
2574
                    if (empty($subscribe)) {
2575
                        continue;
2576
                    }
2577
                }
2578
2579
                $surveyCode = $invitation->getSurveyCode();
2580
2581
                $survey = $repoSurvey->findOneBy([
2582
                    'cId' => $courseId,
2583
                    'sessionId' => $sessionId,
2584
                    'code' => $surveyCode,
2585
                ]);
2586
2587
                if (empty($survey)) {
2588
                    continue;
2589
                }
2590
2591
                $url = $mainUrl.'survey_id='.$survey->getSurveyId().'&cidReq='.$courseCode.'&id_session='.$sessionId;
2592
                $title = $survey->getTitle();
2593
                $title = Display::url($title, $url);
2594
2595
                if (!empty($sessionId)) {
2596
                    $sessionInfo = api_get_session_info($sessionId);
2597
                    $courseInfo['name'] .= ' ('.$sessionInfo['name'].')';
2598
                }
2599
2600
                $surveyData = self::get_survey($survey->getSurveyId(), 0, $courseCode);
2601
                $table->setCellContents($row, 0, $title);
2602
                $table->setCellContents($row, 1, $courseInfo['name']);
2603
2604
                if (empty($answered)) {
2605
                    $table->setHeaderContents(
2606
                        $row,
2607
                        2,
2608
                        api_get_local_time(
2609
                            $survey->getAvailTill(),
2610
                            null,
2611
                            null,
2612
                            true,
2613
                            false
2614
                        )
2615
                    );
2616
                }
2617
2618
                if (!empty($answered) && $surveyData['anonymous'] == 0) {
2619
                    $answers = SurveyUtil::displayCompleteReport(
2620
                        $surveyData,
2621
                        $userId,
2622
                        false,
2623
                        false,
2624
                        false
2625
                    );
2626
                    $table->setCellContents(++$row, 0, $answers);
2627
                    $table->setCellContents(++$row, 1, '');
2628
                }
2629
2630
                $row++;
2631
            }
2632
            $content .= $table->toHtml();
2633
        } else {
2634
            $content .= Display::return_message(get_lang('NoData'));
2635
        }
2636
2637
        return $content;
2638
    }
2639
2640
    public static function sendToTutors($surveyId)
2641
    {
2642
        $survey = Database::getManager()->getRepository('ChamiloCourseBundle:CSurvey')->find($surveyId);
2643
        if (null === $survey) {
2644
            return false;
2645
        }
2646
2647
        $extraFieldValue = new ExtraFieldValue('survey');
2648
        $groupData = $extraFieldValue->get_values_by_handler_and_field_variable($surveyId, 'group_id');
2649
        if ($groupData && !empty($groupData['value'])) {
2650
            $groupInfo = GroupManager::get_group_properties($groupData['value']);
2651
            if ($groupInfo) {
2652
                $tutors = GroupManager::getTutors($groupInfo);
2653
                if (!empty($tutors)) {
2654
                    SurveyUtil::saveInviteMail(
2655
                        $survey,
2656
                        ' ',
2657
                        ' ',
2658
                        false
2659
                    );
2660
2661
                    foreach ($tutors as $tutor) {
2662
                        $subject = sprintf(get_lang('GroupSurveyX'), $tutor['complete_name']);
2663
                        $content = sprintf(
2664
                            get_lang('HelloXGroupX'),
2665
                            $tutor['complete_name'],
2666
                            $groupInfo['name']
2667
                        );
2668
2669
                        SurveyUtil::saveInvitations(
2670
                            ['users' => $tutor['user_id']],
2671
                            $subject,
2672
                            $content,
2673
                            false,
2674
                            true,
2675
                            false,
2676
                            true
2677
                        );
2678
                    }
2679
                    Display::addFlash(Display::return_message(get_lang('Updated'), 'confirmation', false));
2680
                }
2681
                SurveyUtil::update_count_invited($survey->getCode());
2682
2683
                return true;
2684
            }
2685
        }
2686
2687
        return false;
2688
    }
2689
}
2690