Passed
Push — webservicelpcreate ( d8cb35 )
by
unknown
13:48
created

SurveyManager::delete_shared_survey_question()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 2
dl 0
loc 18
rs 9.9666
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;
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;
96
        }
97
        $course_info = api_get_course_info($course_code);
98
99
        if (empty($course_info)) {
100
            return false;
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 (0 != $shared) {
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,
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);
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
            'true' == $values['survey_share']['survey_share']
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;
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
     * Copy given survey to a new (optional) given survey ID.
688
     *
689
     * @param int $survey_id
690
     * @param int $new_survey_id
691
     * @param int $targetCourseId
692
     *
693
     * @return bool
694
     */
695
    public static function copy_survey(
696
        $survey_id,
697
        $new_survey_id = null,
698
        $targetCourseId = null
699
    ) {
700
        $course_id = api_get_course_int_id();
701
        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...
702
            $targetCourseId = $course_id;
703
        }
704
705
        // Database table definitions
706
        $table_survey = Database::get_course_table(TABLE_SURVEY);
707
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
708
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
709
        $table_survey_options = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
710
        $survey_id = (int) $survey_id;
711
712
        // Get groups
713
        $survey_data = self::get_survey($survey_id, 0, null, true);
714
        if (empty($survey_data)) {
715
            return true;
716
        }
717
718
        if (empty($new_survey_id)) {
719
            $params = $survey_data;
720
            $params['code'] = self::generate_unique_code($params['code']);
721
            $params['c_id'] = $targetCourseId;
722
            unset($params['survey_id']);
723
            $params['session_id'] = api_get_session_id();
724
            $params['title'] = $params['title'].' '.get_lang('Copy');
725
            unset($params['iid']);
726
            $params['invited'] = 0;
727
            $params['answered'] = 0;
728
            $new_survey_id = Database::insert($table_survey, $params);
729
730
            if ($new_survey_id) {
731
                $sql = "UPDATE $table_survey SET survey_id = $new_survey_id
732
                        WHERE iid = $new_survey_id";
733
                Database::query($sql);
734
735
                // Insert into item_property
736
                api_item_property_update(
737
                    api_get_course_info(),
738
                    TOOL_SURVEY,
739
                    $new_survey_id,
740
                    'SurveyAdded',
741
                    api_get_user_id()
742
                );
743
            }
744
        } else {
745
            $new_survey_id = (int) $new_survey_id;
746
        }
747
748
        $sql = "SELECT * FROM $table_survey_question_group
749
                WHERE c_id = $course_id AND survey_id = $survey_id";
750
        $res = Database::query($sql);
751
        while ($row = Database::fetch_array($res, 'ASSOC')) {
752
            $params = [
753
                'c_id' => $targetCourseId,
754
                'name' => $row['name'],
755
                'description' => $row['description'],
756
                'survey_id' => $new_survey_id,
757
            ];
758
            $insertId = Database::insert($table_survey_question_group, $params);
759
760
            $sql = "UPDATE $table_survey_question_group SET id = iid
761
                    WHERE iid = $insertId";
762
            Database::query($sql);
763
764
            $group_id[$row['id']] = $insertId;
765
        }
766
767
        // Get questions
768
        $sql = "SELECT * FROM $table_survey_question
769
                WHERE c_id = $course_id AND survey_id = $survey_id";
770
        $res = Database::query($sql);
771
        while ($row = Database::fetch_array($res, 'ASSOC')) {
772
            $params = [
773
                'c_id' => $targetCourseId,
774
                'survey_id' => $new_survey_id,
775
                'survey_question' => $row['survey_question'],
776
                'survey_question_comment' => $row['survey_question_comment'],
777
                'type' => $row['type'],
778
                'display' => $row['display'],
779
                'sort' => $row['sort'],
780
                'shared_question_id' => $row['shared_question_id'],
781
                'max_value' => $row['max_value'],
782
                'survey_group_pri' => $row['survey_group_pri'],
783
                'survey_group_sec1' => $row['survey_group_sec1'],
784
                'survey_group_sec2' => $row['survey_group_sec2'],
785
            ];
786
787
            if (api_get_configuration_value('allow_required_survey_questions')) {
788
                if (isset($row['is_required'])) {
789
                    $params['is_required'] = $row['is_required'];
790
                }
791
            }
792
793
            $insertId = Database::insert($table_survey_question, $params);
794
            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...
795
                $sql = "UPDATE $table_survey_question SET question_id = iid WHERE iid = $insertId";
796
                Database::query($sql);
797
                $question_id[$row['question_id']] = $insertId;
798
            }
799
        }
800
801
        // Get questions options
802
        $sql = "SELECT * FROM $table_survey_options
803
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
804
805
        $res = Database::query($sql);
806
        while ($row = Database::fetch_array($res, 'ASSOC')) {
807
            $params = [
808
                'c_id' => $targetCourseId,
809
                '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...
810
                'survey_id' => $new_survey_id,
811
                'option_text' => $row['option_text'],
812
                'sort' => $row['sort'],
813
                'value' => $row['value'],
814
            ];
815
            $insertId = Database::insert($table_survey_options, $params);
816
            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...
817
                $sql = "UPDATE $table_survey_options SET question_option_id = $insertId
818
                        WHERE iid = $insertId";
819
                Database::query($sql);
820
            }
821
        }
822
823
        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...
824
    }
825
826
    /**
827
     * This function duplicates a survey (and also all the question in that survey.
828
     *
829
     * @param int $surveyId id of the survey that has to be duplicated
830
     * @param int $courseId id of the course which survey has to be duplicated
831
     *
832
     * @return true
833
     *
834
     * @author Eric Marguin <[email protected]>, Elixir Interactive
835
     *
836
     * @version October 2007
837
     */
838
    public static function empty_survey($surveyId, $courseId = 0)
839
    {
840
        // Database table definitions
841
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
842
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
843
        $table_survey = Database::get_course_table(TABLE_SURVEY);
844
845
        $courseId = (int) $courseId;
846
        $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
847
        $surveyId = (int) $surveyId;
848
849
        $datas = self::get_survey($surveyId);
850
        $session_where = '';
851
        if (0 != api_get_session_id()) {
852
            $session_where = ' AND session_id = "'.api_get_session_id().'" ';
853
        }
854
855
        $sql = 'DELETE FROM '.$table_survey_invitation.'
856
		        WHERE
857
		            c_id = '.$courseId.' AND
858
		            survey_code = "'.Database::escape_string($datas['code']).'" '.$session_where.' ';
859
        Database::query($sql);
860
861
        $sql = 'DELETE FROM '.$table_survey_answer.'
862
		        WHERE c_id = '.$courseId.' AND survey_id='.$surveyId;
863
        Database::query($sql);
864
865
        $sql = 'UPDATE '.$table_survey.' SET invited=0, answered=0
866
		        WHERE c_id = '.$courseId.' AND survey_id='.$surveyId;
867
        Database::query($sql);
868
869
        return true;
870
    }
871
872
    /**
873
     * This function recalculates the number of people who have taken the survey (=filled at least one question).
874
     *
875
     * @param array  $survey_data
876
     * @param array  $user
877
     * @param string $survey_code
878
     *
879
     * @return bool
880
     *
881
     * @author Patrick Cool <[email protected]>, Ghent University
882
     *
883
     * @version February 2007
884
     */
885
    public static function update_survey_answered($survey_data, $user, $survey_code)
886
    {
887
        if (empty($survey_data)) {
888
            return false;
889
        }
890
891
        // Database table definitions
892
        $table_survey = Database::get_course_table(TABLE_SURVEY);
893
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
894
895
        $survey_id = (int) $survey_data['survey_id'];
896
        $course_id = (int) $survey_data['c_id'];
897
        $session_id = $survey_data['session_id'];
898
899
        // Getting a list with all the people who have filled the survey
900
        /*$people_filled = self::get_people_who_filled_survey($survey_id, false, $course_id);
901
        $number = count($people_filled);*/
902
903
        // Storing this value in the survey table
904
        $sql = "UPDATE $table_survey
905
		        SET answered = answered + 1
906
		        WHERE
907
                    c_id = $course_id AND
908
		            survey_id = ".$survey_id;
909
        Database::query($sql);
910
911
        $allow = api_get_configuration_value('survey_answered_at_field');
912
        // Requires DB change:
913
        // ALTER TABLE c_survey_invitation ADD answered_at DATETIME DEFAULT NULL;
914
        $answeredAt = '';
915
        if ($allow) {
916
            $answeredAt = "answered_at = '".api_get_utc_datetime()."',";
917
        }
918
919
        // Storing that the user has finished the survey.
920
        $sql = "UPDATE $table_survey_invitation
921
                SET $answeredAt answered = 1
922
                WHERE
923
                    c_id = $course_id AND
924
                    session_id = $session_id AND
925
                    user ='".Database::escape_string($user)."' AND
926
                    survey_code='".Database::escape_string($survey_code)."'";
927
        Database::query($sql);
928
    }
929
930
    /**
931
     * This function return the "icon" of the question type.
932
     *
933
     * @param string $type
934
     *
935
     * @author Patrick Cool <[email protected]>, Ghent University
936
     *
937
     * @version February 2007
938
     */
939
    public static function icon_question($type)
940
    {
941
        // the possible question types
942
        $possible_types = [
943
            'personality',
944
            'yesno',
945
            'multiplechoice',
946
            'multipleresponse',
947
            'open',
948
            'dropdown',
949
            'comment',
950
            'pagebreak',
951
            'percentage',
952
            'score',
953
        ];
954
955
        // the images array
956
        $icon_question = [
957
            'yesno' => 'yesno.png',
958
            'personality' => 'yesno.png',
959
            'multiplechoice' => 'mcua.png',
960
            'multipleresponse' => 'mcma.png',
961
            'open' => 'open_answer.png',
962
            'dropdown' => 'dropdown.png',
963
            'percentage' => 'percentagequestion.png',
964
            'score' => 'scorequestion.png',
965
            'comment' => 'commentquestion.png',
966
            'pagebreak' => 'page_end.png',
967
        ];
968
969
        if (in_array($type, $possible_types)) {
970
            return $icon_question[$type];
971
        }
972
973
        return false;
974
    }
975
976
    /**
977
     * This function retrieves all the information of a question.
978
     *
979
     * @param int  $question_id the id of the question
980
     * @param bool $shared
981
     *
982
     * @return array
983
     *
984
     * @author Patrick Cool <[email protected]>, Ghent University
985
     *
986
     * @version January 2007
987
     *
988
     * @todo one sql call should do the trick
989
     */
990
    public static function get_question($question_id, $shared = false)
991
    {
992
        // Table definitions
993
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
994
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
995
        $course_id = api_get_course_int_id();
996
        $question_id = (int) $question_id;
997
998
        if (empty($question_id)) {
999
            return [];
1000
        }
1001
1002
        $sql = "SELECT * FROM $tbl_survey_question
1003
                WHERE c_id = $course_id AND question_id = $question_id
1004
                ORDER BY `sort` ";
1005
1006
        $sqlOption = "  SELECT * FROM $table_survey_question_option
1007
                        WHERE c_id = $course_id AND question_id='".$question_id."'
1008
                        ORDER BY `sort` ";
1009
1010
        if ($shared) {
1011
            $tbl_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1012
            $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1013
1014
            $sql = "SELECT * FROM $tbl_survey_question
1015
                    WHERE question_id = $question_id
1016
                    ORDER BY `sort` ";
1017
            $sqlOption = "SELECT * FROM $table_survey_question_option
1018
                          WHERE question_id = $question_id
1019
                          ORDER BY `sort` ";
1020
        }
1021
1022
        // Getting the information of the question
1023
        $result = Database::query($sql);
1024
        $row = Database::fetch_array($result, 'ASSOC');
1025
1026
        $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...
1027
        $return['parent_id'] = isset($row['parent_id']) ? $row['parent_id'] : 0;
1028
        $return['parent_option_id'] = isset($row['parent_option_id']) ? $row['parent_option_id'] : 0;
1029
        $return['question_id'] = $row['question_id'];
1030
        $return['type'] = $row['type'];
1031
        $return['question'] = $row['survey_question'];
1032
        $return['horizontalvertical'] = $row['display'];
1033
        $return['shared_question_id'] = $row['shared_question_id'];
1034
        $return['maximum_score'] = $row['max_value'];
1035
        $return['is_required'] = api_get_configuration_value('allow_required_survey_questions')
1036
            ? $row['is_required']
1037
            : false;
1038
1039
        if (0 != $row['survey_group_pri']) {
1040
            $return['assigned'] = $row['survey_group_pri'];
1041
            $return['choose'] = 1;
1042
        } else {
1043
            $return['assigned1'] = $row['survey_group_sec1'];
1044
            $return['assigned2'] = $row['survey_group_sec2'];
1045
            $return['choose'] = 2;
1046
        }
1047
1048
        // Getting the information of the question options
1049
        $result = Database::query($sqlOption);
1050
        $counter = 0;
1051
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1052
            /** @todo this should be renamed to options instead of answers */
1053
            $return['answers'][] = $row['option_text'];
1054
            $return['values'][] = $row['value'];
1055
            $return['answer_data'][$counter]['data'] = $row['option_text'];
1056
            $return['answer_data'][$counter]['iid'] = $row['iid'];
1057
            /** @todo this can be done more elegantly (used in reporting) */
1058
            $return['answersid'][] = $row['question_option_id'];
1059
            $counter++;
1060
        }
1061
1062
        return $return;
1063
    }
1064
1065
    /**
1066
     * This function gets all the question of any given survey.
1067
     *
1068
     * @param int $surveyId the id of the survey
1069
     * @param int $courseId
1070
     *
1071
     * @return array containing all the questions of the survey
1072
     *
1073
     * @author Patrick Cool <[email protected]>, Ghent University
1074
     *
1075
     * @version February 2007
1076
     *
1077
     * @todo one sql call should do the trick
1078
     */
1079
    public static function get_questions($surveyId, $courseId = 0)
1080
    {
1081
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1082
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1083
1084
        $courseId = (int) $courseId;
1085
        $surveyId = (int) $surveyId;
1086
1087
        if (empty($courseId)) {
1088
            $courseId = api_get_course_int_id();
1089
        }
1090
1091
        // Getting the information of the question
1092
        $sql = "SELECT * FROM $tbl_survey_question
1093
		        WHERE c_id = $courseId AND survey_id= $surveyId ";
1094
        $result = Database::query($sql);
1095
        $questions = [];
1096
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1097
            $questionId = $row['question_id'];
1098
            $questions[$questionId]['survey_id'] = $surveyId;
1099
            $questions[$questionId]['question_id'] = $questionId;
1100
            $questions[$questionId]['type'] = $row['type'];
1101
            $questions[$questionId]['question'] = $row['survey_question'];
1102
            $questions[$questionId]['horizontalvertical'] = $row['display'];
1103
            $questions[$questionId]['maximum_score'] = $row['max_value'];
1104
            $questions[$questionId]['sort'] = $row['sort'];
1105
            $questions[$questionId]['survey_question_comment'] = $row['survey_question_comment'];
1106
1107
            // Getting the information of the question options
1108
            $sql = "SELECT * FROM $table_survey_question_option
1109
		             WHERE c_id = $courseId AND survey_id= $surveyId  AND question_id = $questionId";
1110
            $resultOptions = Database::query($sql);
1111
            while ($rowOption = Database::fetch_array($resultOptions, 'ASSOC')) {
1112
                $questions[$questionId]['answers'][] = $rowOption['option_text'];
1113
            }
1114
        }
1115
1116
        return $questions;
1117
    }
1118
1119
    /**
1120
     * This function saves a question in the database.
1121
     * This can be either an update of an existing survey or storing a new survey.
1122
     *
1123
     * @param array $survey_data
1124
     * @param array $form_content all the information of the form
1125
     *
1126
     * @return string
1127
     *
1128
     * @author Patrick Cool <[email protected]>, Ghent University
1129
     *
1130
     * @version January 2007
1131
     */
1132
    public static function save_question($survey_data, $form_content, $showMessage = true, $dataFromDatabase = [])
1133
    {
1134
        $return_message = '';
1135
        if (strlen($form_content['question']) > 1) {
1136
            // Checks length of the question
1137
            $empty_answer = false;
1138
            if ($survey_data['survey_type'] == 1) {
1139
                if (empty($form_content['choose'])) {
1140
                    return 'PleaseChooseACondition';
1141
                }
1142
1143
                if (($form_content['choose'] == 2) &&
1144
                    ($form_content['assigned1'] == $form_content['assigned2'])
1145
                ) {
1146
                    return 'ChooseDifferentCategories';
1147
                }
1148
            }
1149
1150
            if ($form_content['type'] !== 'percentage') {
1151
                if (isset($form_content['answers'])) {
1152
                    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...
1153
                        if (strlen($form_content['answers'][$i]) < 1) {
1154
                            $empty_answer = true;
1155
                            break;
1156
                        }
1157
                    }
1158
                }
1159
            }
1160
1161
            if ('score' == $form_content['type']) {
1162
                if (strlen($form_content['maximum_score']) < 1) {
1163
                    $empty_answer = true;
1164
                }
1165
            }
1166
1167
            $course_id = api_get_course_int_id();
1168
1169
            if (!$empty_answer) {
1170
                // Table definitions
1171
                $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1172
                $surveyId = (int) $form_content['survey_id'];
1173
1174
                // Getting all the information of the survey
1175
                $survey_data = self::get_survey($surveyId);
1176
1177
                // Storing the question in the shared database
1178
                if (is_numeric($survey_data['survey_share']) && $survey_data['survey_share'] != 0) {
1179
                    $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

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

1592
            self::/** @scrutinizer ignore-call */ 
1593
                  save_shared_question_options($form_content, $survey_data);
Loading history...
1593
        }
1594
1595
        // Table definition
1596
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1597
1598
        // We are editing a question so we first have to remove all the existing options from the database
1599
        $optionsToDelete = [];
1600
        if (isset($dataFromDatabase['answer_data'])) {
1601
            foreach ($dataFromDatabase['answer_data'] as $data) {
1602
                if ('other' === $data['data'] && 'multiplechoiceother' === $type) {
1603
                    continue;
1604
                }
1605
1606
                if (!in_array($data['iid'], $form_content['answersid'])) {
1607
                    $optionsToDelete[] = $data['iid'];
1608
                }
1609
            }
1610
        }
1611
1612
        if (!empty($optionsToDelete)) {
1613
            foreach ($optionsToDelete as $iid) {
1614
                $iid = (int) $iid;
1615
                $sql = "DELETE FROM $table
1616
			            WHERE
1617
			                iid = $iid AND
1618
			                c_id = $course_id AND
1619
                            question_id = '".intval($form_content['question_id'])."'
1620
                            ";
1621
                Database::query($sql);
1622
            }
1623
        }
1624
1625
        $counter = 1;
1626
        if (isset($form_content['answers']) && is_array($form_content['answers'])) {
1627
            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...
1628
                $values = isset($form_content['values']) ? $form_content['values'][$i] : '';
1629
                $answerId = 0;
1630
                if (isset($form_content['answersid']) && isset($form_content['answersid'][$i])) {
1631
                    $answerId = $form_content['answersid'][$i];
1632
                }
1633
                if (empty($answerId)) {
1634
                    $params = [
1635
                        'c_id' => $course_id,
1636
                        'question_id' => $form_content['question_id'],
1637
                        'survey_id' => $form_content['survey_id'],
1638
                        'option_text' => $form_content['answers'][$i],
1639
                        'value' => $values,
1640
                        'sort' => $counter,
1641
                    ];
1642
                    $insertId = Database::insert($table, $params);
1643
                    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...
1644
                        $sql = "UPDATE $table
1645
                                SET question_option_id = $insertId
1646
                                WHERE iid = $insertId";
1647
                        Database::query($sql);
1648
                        $counter++;
1649
                    }
1650
                } else {
1651
                    $params = [
1652
                        'option_text' => $form_content['answers'][$i],
1653
                        'value' => $values,
1654
                        'sort' => $counter,
1655
                    ];
1656
                    Database::update($table, $params, ['iid = ?' => [$answerId]]);
1657
                    $counter++;
1658
                }
1659
            }
1660
        }
1661
1662
        if ('multiplechoiceother' === $type) {
1663
            // First time creation
1664
            if (empty($dataFromDatabase['answer_data'])) {
1665
                $params = [
1666
                    'c_id' => $course_id,
1667
                    'question_id' => $form_content['question_id'],
1668
                    'survey_id' => $form_content['survey_id'],
1669
                    'option_text' => 'other',
1670
                    'value' => 0,
1671
                    'sort' => $counter,
1672
                ];
1673
                $insertId = Database::insert($table, $params);
1674
                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...
1675
                    $sql = "UPDATE $table
1676
                            SET question_option_id = $insertId
1677
                            WHERE iid = $insertId";
1678
                    Database::query($sql);
1679
                }
1680
            } else {
1681
                $params = [
1682
                    'option_text' => 'other',
1683
                    'value' => 0,
1684
                    'sort' => $counter,
1685
                ];
1686
                Database::update(
1687
                    $table,
1688
                    $params,
1689
                    [
1690
                        'c_id = ? AND question_id = ? AND survey_id = ? AND option_text = ?' => [
1691
                            $course_id,
1692
                            $form_content['question_id'],
1693
                            $form_content['survey_id'],
1694
                            'other',
1695
                        ],
1696
                    ]
1697
                );
1698
            }
1699
        }
1700
    }
1701
1702
    /**
1703
     * This function stores the options of the questions in the shared table.
1704
     *
1705
     * @param array $form_content
1706
     *
1707
     * @author Patrick Cool <[email protected]>, Ghent University
1708
     *
1709
     * @version February 2007
1710
     *
1711
     * @todo writing the update statement when editing a question
1712
     */
1713
    public function save_shared_question_options($form_content, $survey_data)
1714
    {
1715
        if (is_array($form_content) && is_array($form_content['answers'])) {
1716
            // Table definition
1717
            $table = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1718
1719
            // We are editing a question so we first have to remove all the existing options from the database
1720
            $sql = "DELETE FROM $table
1721
                    WHERE question_id = '".Database::escape_string($form_content['shared_question_id'])."'";
1722
            Database::query($sql);
1723
1724
            $counter = 1;
1725
            foreach ($form_content['answers'] as &$answer) {
1726
                $params = [
1727
                    'question_id' => $form_content['shared_question_id'],
1728
                    'survey_id' => $survey_data['is_shared'],
1729
                    'option_text' => $answer,
1730
                    'sort' => $counter,
1731
                ];
1732
                Database::insert($table, $params);
1733
1734
                $counter++;
1735
            }
1736
        }
1737
    }
1738
1739
    /**
1740
     * This function deletes all the options of the questions of a given survey
1741
     * This function is normally only called when a survey is deleted.
1742
     *
1743
     * @param int $survey_id the id of the survey that has to be deleted
1744
     *
1745
     * @return true
1746
     *
1747
     * @author Patrick Cool <[email protected]>, Ghent University
1748
     *
1749
     * @version January 2007
1750
     */
1751
    public static function delete_all_survey_questions_options($survey_id, $shared = false)
1752
    {
1753
        // Table definitions
1754
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1755
        $course_id = api_get_course_int_id();
1756
        $course_condition = " c_id = $course_id AND ";
1757
        if ($shared) {
1758
            $course_condition = '';
1759
            $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1760
        }
1761
1762
        $sql = "DELETE FROM $table_survey_question_option
1763
                WHERE $course_condition survey_id='".intval($survey_id)."'";
1764
1765
        // Deleting the options of the survey questions
1766
        Database::query($sql);
1767
1768
        return true;
1769
    }
1770
1771
    /**
1772
     * This function deletes the options of a given question.
1773
     *
1774
     * @param int  $survey_id
1775
     * @param int  $question_id
1776
     * @param bool $shared
1777
     *
1778
     * @return bool
1779
     *
1780
     * @author Patrick Cool <[email protected]>, Ghent University
1781
     * @author Julio Montoya
1782
     *
1783
     * @version March 2007
1784
     */
1785
    public static function delete_survey_question_option(
1786
        $survey_id,
1787
        $question_id,
1788
        $shared = false
1789
    ) {
1790
        $course_id = api_get_course_int_id();
1791
        $course_condition = " c_id = $course_id AND ";
1792
1793
        // Table definitions
1794
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1795
        if ($shared) {
1796
            $course_condition = '';
1797
            $table = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1798
        }
1799
1800
        // Deleting the options of the survey questions
1801
        $sql = "DELETE FROM $table
1802
		        WHERE
1803
		            $course_condition survey_id='".intval($survey_id)."' AND
1804
		            question_id='".intval($question_id)."'";
1805
        Database::query($sql);
1806
1807
        return true;
1808
    }
1809
1810
    /**
1811
     * SURVEY ANSWERS FUNCTIONS.
1812
     */
1813
1814
    /**
1815
     * This function deletes all the answers anyone has given on this survey
1816
     * This function is normally only called when a survey is deleted.
1817
     *
1818
     * @param $survey_id the id of the survey that has to be deleted
1819
     *
1820
     * @return true
1821
     *
1822
     * @todo write the function
1823
     *
1824
     * @author Patrick Cool <[email protected]>, Ghent University
1825
     *
1826
     * @version January 2007,december 2008
1827
     */
1828
    public static function delete_all_survey_answers($survey_id)
1829
    {
1830
        $course_id = api_get_course_int_id();
1831
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
1832
        $survey_id = (int) $survey_id;
1833
        $sql = "DELETE FROM $table
1834
                WHERE c_id = $course_id AND survey_id = $survey_id";
1835
        Database::query($sql);
1836
1837
        return true;
1838
    }
1839
1840
    /**
1841
     * @param int $user_id
1842
     * @param int $survey_id
1843
     * @param int $course_id
1844
     *
1845
     * @return bool
1846
     */
1847
    public static function is_user_filled_survey($user_id, $survey_id, $course_id)
1848
    {
1849
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
1850
        $user_id = (int) $user_id;
1851
        $course_id = (int) $course_id;
1852
        $survey_id = (int) $survey_id;
1853
1854
        $sql = "SELECT DISTINCT user
1855
                FROM $table
1856
                WHERE
1857
                    c_id		= $course_id AND
1858
                    user		= $user_id AND
1859
                    survey_id	= $survey_id";
1860
        $result = Database::query($sql);
1861
        if (Database::num_rows($result)) {
1862
            return true;
1863
        }
1864
1865
        return false;
1866
    }
1867
1868
    /**
1869
     * This function gets all the persons who have filled the survey.
1870
     *
1871
     * @param int $survey_id
1872
     *
1873
     * @return array
1874
     *
1875
     * @author Patrick Cool <[email protected]>, Ghent University
1876
     *
1877
     * @version February 2007
1878
     */
1879
    public static function get_people_who_filled_survey(
1880
        $survey_id,
1881
        $all_user_info = false,
1882
        $course_id = null
1883
    ) {
1884
        // Database table definition
1885
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1886
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1887
1888
        // Variable initialisation
1889
        $return = [];
1890
1891
        if (empty($course_id)) {
1892
            $course_id = api_get_course_int_id();
1893
        } else {
1894
            $course_id = (int) $course_id;
1895
        }
1896
1897
        $survey_id = (int) $survey_id;
1898
1899
        if ($all_user_info) {
1900
            $order_clause = api_sort_by_first_name()
1901
                ? ' ORDER BY user.firstname, user.lastname'
1902
                : ' ORDER BY user.lastname, user.firstname';
1903
            $sql = "SELECT DISTINCT
1904
			            answered_user.user as invited_user,
1905
			            user.firstname,
1906
			            user.lastname,
1907
			            user.user_id
1908
                    FROM $table_survey_answer answered_user
1909
                    LEFT JOIN $table_user as user ON answered_user.user = user.user_id
1910
                    WHERE
1911
                        answered_user.c_id = $course_id AND
1912
                        survey_id= '".$survey_id."' ".
1913
                $order_clause;
1914
        } else {
1915
            $sql = "SELECT DISTINCT user FROM $table_survey_answer
1916
			        WHERE c_id = $course_id AND survey_id= '".$survey_id."'  ";
1917
1918
            if (api_get_configuration_value('survey_anonymous_show_answered')) {
1919
                $tblInvitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
1920
                $tblSurvey = Database::get_course_table(TABLE_SURVEY);
1921
1922
                $sql = "SELECT i.user FROM $tblInvitation i
1923
                    INNER JOIN $tblSurvey s
1924
                    ON i.survey_code = s.code
1925
                        AND i.c_id = s.c_id
1926
                        AND i.session_id = s.session_id
1927
                    WHERE i.answered IS TRUE AND s.iid = $survey_id";
1928
            }
1929
        }
1930
1931
        $res = Database::query($sql);
1932
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1933
            if ($all_user_info) {
1934
                $userInfo = api_get_user_info($row['user_id']);
1935
                $row['user_info'] = $userInfo;
1936
                $return[] = $row;
1937
            } else {
1938
                $return[] = $row['user'];
1939
            }
1940
        }
1941
1942
        return $return;
1943
    }
1944
1945
    /**
1946
     * @return bool
1947
     */
1948
    public static function survey_generation_hash_available()
1949
    {
1950
        if (extension_loaded('mcrypt')) {
1951
            return true;
1952
        }
1953
1954
        return false;
1955
    }
1956
1957
    /**
1958
     * @param int $survey_id
1959
     * @param int $course_id
1960
     * @param int $session_id
1961
     * @param int $group_id
1962
     *
1963
     * @return string
1964
     */
1965
    public static function generate_survey_hash($survey_id, $course_id, $session_id, $group_id)
1966
    {
1967
        return hash('sha512', api_get_security_key().'_'.$course_id.'_'.$session_id.'_'.$group_id.'_'.$survey_id);
1968
    }
1969
1970
    /**
1971
     * @param int    $survey_id
1972
     * @param int    $course_id
1973
     * @param int    $session_id
1974
     * @param int    $group_id
1975
     * @param string $hash
1976
     *
1977
     * @return bool
1978
     */
1979
    public static function validate_survey_hash($survey_id, $course_id, $session_id, $group_id, $hash)
1980
    {
1981
        $generatedHash = self::generate_survey_hash($survey_id, $course_id, $session_id, $group_id);
1982
        if ($generatedHash == $hash) {
1983
            return true;
1984
        }
1985
1986
        return false;
1987
    }
1988
1989
    /**
1990
     * @param int $survey_id
1991
     * @param int $course_id
1992
     * @param int $session_id
1993
     * @param int $group_id
1994
     *
1995
     * @return string
1996
     */
1997
    public static function generate_survey_link(
1998
        $survey_id,
1999
        $course_id,
2000
        $session_id,
2001
        $group_id
2002
    ) {
2003
        $code = self::generate_survey_hash(
2004
            $survey_id,
2005
            $course_id,
2006
            $session_id,
2007
            $group_id
2008
        );
2009
2010
        return api_get_path(WEB_CODE_PATH).'survey/link.php?h='.$code.'&i='.$survey_id.'&c='.intval($course_id).'&s='
2011
            .intval($session_id).'&g='.$group_id;
2012
    }
2013
2014
    /**
2015
     * Check if the current user has mandatory surveys no-answered
2016
     * and redirect to fill the first found survey.
2017
     */
2018
    public static function protectByMandatory()
2019
    {
2020
        if (false !== strpos($_SERVER['SCRIPT_NAME'], 'fillsurvey.php')) {
2021
            return;
2022
        }
2023
2024
        $userId = api_get_user_id();
2025
        $courseId = api_get_course_int_id();
2026
        $sessionId = api_get_session_id();
2027
2028
        if (!$userId) {
2029
            return;
2030
        }
2031
2032
        if (!$courseId) {
2033
            return;
2034
        }
2035
2036
        try {
2037
            /** @var CSurveyInvitation $invitation */
2038
            $invitation = Database::getManager()
2039
                ->createQuery("
2040
                    SELECT i FROM ChamiloCourseBundle:CSurveyInvitation i
2041
                    INNER JOIN ChamiloCourseBundle:CSurvey s
2042
                        WITH (s.code = i.surveyCode AND s.cId = i.cId AND s.sessionId = i.sessionId)
2043
                    INNER JOIN ChamiloCoreBundle:ExtraFieldValues efv WITH efv.itemId = s.iid
2044
                    INNER JOIN ChamiloCoreBundle:ExtraField ef WITH efv.field = ef.id
2045
                    WHERE
2046
                        i.answered = 0 AND
2047
                        i.cId = :course AND
2048
                        i.user = :user AND
2049
                        i.sessionId = :session AND
2050
                        :now BETWEEN s.availFrom AND s.availTill AND
2051
                        ef.variable = :variable AND
2052
                        efv.value = 1 AND
2053
                        s.surveyType != 3
2054
                    ORDER BY s.availTill ASC
2055
                ")
2056
                ->setMaxResults(1)
2057
                ->setParameters([
2058
                    'course' => $courseId,
2059
                    'user' => $userId,
2060
                    'session' => $sessionId,
2061
                    'now' => new DateTime('UTC', new DateTimeZone('UTC')),
2062
                    'variable' => 'is_mandatory',
2063
                ])
2064
                ->getSingleResult();
2065
        } catch (Exception $e) {
2066
            $invitation = null;
2067
        }
2068
2069
        if (!$invitation) {
2070
            return;
2071
        }
2072
2073
        Display::addFlash(
2074
            Display::return_message(get_lang('MandatorySurveyNoAnswered'), 'warning')
2075
        );
2076
2077
        $url = SurveyUtil::generateFillSurveyLink(
2078
            $invitation->getInvitationCode(),
2079
            api_get_course_info(),
2080
            api_get_session_id()
2081
        );
2082
2083
        header('Location: '.$url);
2084
        exit;
2085
    }
2086
2087
    /**
2088
     * This function empty surveys (invitations and answers).
2089
     *
2090
     * @param int $surveyId id of the survey to empty
2091
     *
2092
     * @return bool
2093
     */
2094
    public static function emptySurveyFromId($surveyId)
2095
    {
2096
        // Database table definitions
2097
        $surveyInvitationTable = Database:: get_course_table(TABLE_SURVEY_INVITATION);
2098
        $surveyAnswerTable = Database:: get_course_table(TABLE_SURVEY_ANSWER);
2099
        $surveyTable = Database:: get_course_table(TABLE_SURVEY);
2100
        $surveyId = (int) $surveyId;
2101
        $surveyData = self::get_survey($surveyId);
2102
        if (empty($surveyData)) {
2103
            return false;
2104
        }
2105
2106
        $surveyCode = $surveyData['survey_code'];
2107
        $courseId = (int) $surveyData['c_id'];
2108
        $sessionId = (int) $surveyData['session_id'];
2109
2110
        $sql = "DELETE FROM $surveyInvitationTable
2111
                WHERE session_id = $sessionId AND c_id = $courseId AND survey_code = '$surveyCode' ";
2112
        Database::query($sql);
2113
2114
        $sql = "DELETE FROM $surveyAnswerTable
2115
               WHERE survey_id = $surveyId AND c_id = $courseId ";
2116
        Database::query($sql);
2117
2118
        $sql = "UPDATE $surveyTable
2119
                SET invited = 0, answered = 0
2120
                WHERE survey_id = $surveyId AND c_id = $courseId AND session_id = $sessionId ";
2121
        Database::query($sql);
2122
2123
        return true;
2124
    }
2125
2126
    /**
2127
     * Copy survey specifying course ID and session ID where will be copied.
2128
     *
2129
     * @param int $surveyId
2130
     * @param int $targetCourseId  target course id
2131
     * @param int $targetSessionId target session id
2132
     *
2133
     * @return bool|int when fails or return the new survey id
2134
     */
2135
    public static function copySurveySession(
2136
        $surveyId,
2137
        $targetCourseId,
2138
        $targetSessionId
2139
    ) {
2140
        // Database table definitions
2141
        $surveyTable = Database::get_course_table(TABLE_SURVEY);
2142
        $surveyQuestionGroupTable = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
2143
        $surveyQuestionTable = Database::get_course_table(TABLE_SURVEY_QUESTION);
2144
        $surveyOptionsTable = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2145
        $surveyId = (int) $surveyId;
2146
        $targetCourseId = (int) $targetCourseId;
2147
        $targetSessionId = (int) $targetSessionId;
2148
2149
        $surveyData = self::get_survey($surveyId, 0, '', true);
2150
        if (empty($surveyData) || empty($targetCourseId)) {
2151
            return false;
2152
        }
2153
2154
        $originalCourseId = $surveyData['c_id'];
2155
        $originalSessionId = $surveyData['session_id'];
2156
2157
        $surveyData['code'] = self::generate_unique_code($surveyData['code']);
2158
        $surveyData['c_id'] = $targetCourseId;
2159
        $surveyData['session_id'] = $targetSessionId;
2160
        // Add a "Copy" suffix if copied inside the same course
2161
        if ($targetCourseId == $originalCourseId) {
2162
            $surveyData['title'] = $surveyData['title'].' '.get_lang('Copy');
2163
        }
2164
        unset($surveyData['iid']);
2165
        unset($surveyData['id']);
2166
2167
        $newSurveyId = Database::insert($surveyTable, $surveyData);
2168
2169
        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...
2170
            $sql = "UPDATE $surveyTable SET survey_id = $newSurveyId
2171
                    WHERE iid = $newSurveyId";
2172
            Database::query($sql);
2173
2174
            $sql = "SELECT * FROM $surveyQuestionGroupTable
2175
                    WHERE c_id = $originalCourseId AND survey_id = $surveyId";
2176
            $res = Database::query($sql);
2177
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2178
                $params = [
2179
                    'c_id' => $targetCourseId,
2180
                    'name' => $row['name'],
2181
                    'description' => $row['description'],
2182
                    'survey_id' => $newSurveyId,
2183
                ];
2184
                $insertId = Database::insert($surveyQuestionGroupTable, $params);
2185
                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...
2186
                    $sql = "UPDATE $surveyQuestionGroupTable SET id = iid WHERE iid = $insertId";
2187
                    Database::query($sql);
2188
                    $group_id[$row['id']] = $insertId;
2189
                }
2190
            }
2191
2192
            // Get questions
2193
            $sql = "SELECT * FROM $surveyQuestionTable
2194
                    WHERE c_id = $originalCourseId AND survey_id = $surveyId";
2195
            $res = Database::query($sql);
2196
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2197
                $params = [
2198
                    'c_id' => $targetCourseId,
2199
                    'survey_id' => $newSurveyId,
2200
                    'survey_question' => $row['survey_question'],
2201
                    'survey_question_comment' => $row['survey_question_comment'],
2202
                    'type' => $row['type'],
2203
                    'display' => $row['display'],
2204
                    'sort' => $row['sort'],
2205
                    'shared_question_id' => $row['shared_question_id'],
2206
                    'max_value' => $row['max_value'],
2207
                    'survey_group_pri' => $row['survey_group_pri'],
2208
                    'survey_group_sec1' => $row['survey_group_sec1'],
2209
                    'survey_group_sec2' => $row['survey_group_sec2'],
2210
                ];
2211
2212
                if (api_get_configuration_value('allow_required_survey_questions')) {
2213
                    if (isset($row['is_required'])) {
2214
                        $params['is_required'] = $row['is_required'];
2215
                    }
2216
                }
2217
2218
                $insertId = Database::insert($surveyQuestionTable, $params);
2219
                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...
2220
                    $sql = "UPDATE $surveyQuestionTable
2221
                            SET question_id = iid
2222
                            WHERE iid = $insertId";
2223
                    Database::query($sql);
2224
2225
                    $question_id[$row['question_id']] = $insertId;
2226
                }
2227
            }
2228
2229
            // Get questions options
2230
            $sql = "SELECT * FROM $surveyOptionsTable
2231
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId";
2232
2233
            $res = Database::query($sql);
2234
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2235
                $params = [
2236
                    'c_id' => $targetCourseId,
2237
                    '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...
2238
                    'survey_id' => $newSurveyId,
2239
                    'option_text' => $row['option_text'],
2240
                    'sort' => $row['sort'],
2241
                    'value' => $row['value'],
2242
                ];
2243
                $insertId = Database::insert($surveyOptionsTable, $params);
2244
                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...
2245
                    $sql = "UPDATE $surveyOptionsTable SET question_option_id = $insertId WHERE iid = $insertId";
2246
                    Database::query($sql);
2247
                }
2248
            }
2249
2250
            return $newSurveyId;
2251
        }
2252
2253
        return false;
2254
    }
2255
2256
    /**
2257
     * Copy/duplicate one question (into the same survey).
2258
     * Note: Relies on the question iid to find all necessary info.
2259
     *
2260
     * @param int $questionId
2261
     *
2262
     * @return int The new question's iid, or 0 on error
2263
     */
2264
    public static function copyQuestion($questionId)
2265
    {
2266
        if (empty($questionId)) {
2267
            return 0;
2268
        }
2269
        $questionId = (int) $questionId;
2270
        $questionTable = Database::get_course_table(TABLE_SURVEY_QUESTION);
2271
        $optionsTable = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2272
2273
        // Get questions
2274
        $sql = "SELECT * FROM $questionTable WHERE iid = $questionId";
2275
        $res = Database::query($sql);
2276
        if (false == $res) {
2277
            // Could not find this question
2278
            return 0;
2279
        }
2280
        $row = Database::fetch_array($res, 'ASSOC');
2281
        $params = [
2282
            'c_id' => $row['c_id'],
2283
            'survey_id' => $row['survey_id'],
2284
            'survey_question' => trim($row['survey_question'])."'",
2285
            'survey_question_comment' => $row['survey_question_comment'],
2286
            'type' => $row['type'],
2287
            'display' => $row['display'],
2288
            'shared_question_id' => $row['shared_question_id'],
2289
            'max_value' => $row['max_value'],
2290
            'survey_group_pri' => $row['survey_group_pri'],
2291
            'survey_group_sec1' => $row['survey_group_sec1'],
2292
            'survey_group_sec2' => $row['survey_group_sec2'],
2293
        ];
2294
        if (api_get_configuration_value('allow_required_survey_questions')) {
2295
            if (isset($row['is_required'])) {
2296
                $params['is_required'] = $row['is_required'];
2297
            }
2298
        }
2299
        // Get question position
2300
        $sqlSort = "SELECT max(sort) as sort FROM $questionTable
2301
                    WHERE survey_id = ".$row['survey_id'];
2302
        $resSort = Database::query($sqlSort);
2303
        $rowSort = Database::fetch_assoc($resSort);
2304
        $params['sort'] = $rowSort['sort'] + 1;
2305
        // Insert the new question
2306
        $insertId = Database::insert($questionTable, $params);
2307
        if (false == $insertId) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $insertId of type false|integer against false; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
2308
            return 0;
2309
        }
2310
        // Normalize question_id with iid
2311
        $sql = "UPDATE $questionTable
2312
                SET question_id = iid
2313
                WHERE iid = $insertId";
2314
        Database::query($sql);
2315
2316
        // Get questions options
2317
        $sql = "SELECT * FROM $optionsTable WHERE question_id = $questionId";
2318
        $res = Database::query($sql);
2319
        while ($row = Database::fetch_assoc($res)) {
2320
            $params = [
2321
                'c_id' => $row['c_id'],
2322
                'question_id' => $insertId,
2323
                'survey_id' => $row['survey_id'],
2324
                'option_text' => $row['option_text'],
2325
                'sort' => $row['sort'],
2326
                'value' => $row['value'],
2327
            ];
2328
            $optionId = Database::insert($optionsTable, $params);
2329
            if ($optionId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $optionId 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...
2330
                $sql = "UPDATE $optionsTable SET question_option_id = $optionId WHERE iid = $optionId";
2331
                Database::query($sql);
2332
            }
2333
        }
2334
2335
        return $insertId;
2336
    }
2337
2338
    /**
2339
     * @param array $surveyData
2340
     *
2341
     * @return bool
2342
     */
2343
    public static function removeMultiplicateQuestions($surveyData)
2344
    {
2345
        if (empty($surveyData)) {
2346
            return false;
2347
        }
2348
        $surveyId = $surveyData['survey_id'];
2349
        $courseId = $surveyData['c_id'];
2350
2351
        if (empty($surveyId) || empty($courseId)) {
2352
            return false;
2353
        }
2354
2355
        $questions = self::get_questions($surveyId);
2356
        foreach ($questions as $question) {
2357
            // Questions marked with "geneated" were created using the "multiplicate" feature.
2358
            if ($question['survey_question_comment'] === 'generated') {
2359
                self::delete_survey_question($surveyId, $question['question_id']);
2360
            }
2361
        }
2362
    }
2363
2364
    /**
2365
     * @param array $surveyData
2366
     *
2367
     * @return bool
2368
     */
2369
    public static function multiplicateQuestions($surveyData)
2370
    {
2371
        if (empty($surveyData)) {
2372
            return false;
2373
        }
2374
        $surveyId = $surveyData['survey_id'];
2375
        $courseId = $surveyData['c_id'];
2376
2377
        if (empty($surveyId) || empty($courseId)) {
2378
            return false;
2379
        }
2380
2381
        $questions = self::get_questions($surveyId);
2382
2383
        if (empty($questions)) {
2384
            return false;
2385
        }
2386
2387
        $obj = new UserGroup();
2388
        $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...
2389
        $classList = $obj->getUserGroupInCourse($options);
2390
2391
        $classToParse = [];
2392
        foreach ($classList as $class) {
2393
            $users = $obj->get_users_by_usergroup($class['id']);
2394
            if (empty($users)) {
2395
                continue;
2396
            }
2397
            $classToParse[] = [
2398
                'name' => $class['name'],
2399
                'users' => $users,
2400
            ];
2401
        }
2402
2403
        self::parseMultiplicateUserList($classToParse, $questions, $courseId, $surveyData);
2404
2405
        $extraFieldValue = new ExtraFieldValue('survey');
2406
        $groupData = $extraFieldValue->get_values_by_handler_and_field_variable($surveyId, 'group_id');
2407
        if ($groupData && !empty($groupData['value'])) {
2408
            $groupInfo = GroupManager::get_group_properties($groupData['value']);
2409
            if (!empty($groupInfo)) {
2410
                $users = GroupManager::getStudents($groupInfo['iid'], true);
2411
                if (!empty($users)) {
2412
                    $users = array_column($users, 'id');
2413
                    $classToParse = [
2414
                        [
2415
                            'name' => $groupInfo['name'],
2416
                            'users' => $users,
2417
                        ],
2418
                    ];
2419
                    self::parseMultiplicateUserList($classToParse, $questions, $courseId, $surveyData);
2420
                }
2421
            }
2422
        }
2423
2424
        return true;
2425
    }
2426
2427
    public static function parseMultiplicateUserList($itemList, $questions, $courseId, $surveyData)
2428
    {
2429
        if (empty($itemList) || empty($questions)) {
2430
            return false;
2431
        }
2432
2433
        $surveyId = $surveyData['survey_id'];
2434
        $classTag = '{{class_name}}';
2435
        $studentTag = '{{student_full_name}}';
2436
        $classCounter = 0;
2437
2438
        $newQuestionList = [];
2439
        foreach ($questions as $question) {
2440
            $newQuestionList[$question['sort']] = $question;
2441
        }
2442
        ksort($newQuestionList);
2443
2444
        foreach ($itemList as $class) {
2445
            $className = $class['name'];
2446
            $users = $class['users'];
2447
2448
            foreach ($newQuestionList as $question) {
2449
                $text = $question['question'];
2450
                if (false !== strpos($text, $classTag)) {
2451
                    $replacedText = str_replace($classTag, $className, $text);
2452
                    $values = [
2453
                        'c_id' => $courseId,
2454
                        'question_comment' => 'generated',
2455
                        'type' => $question['type'],
2456
                        'display' => $question['horizontalvertical'],
2457
                        'horizontalvertical' => $question['horizontalvertical'],
2458
                        'question' => $replacedText,
2459
                        'survey_id' => $surveyId,
2460
                        'question_id' => 0,
2461
                        'shared_question_id' => 0,
2462
                        'answers' => $question['answers'],
2463
                    ];
2464
                    self::save_question($surveyData, $values, false);
2465
                    $classCounter++;
2466
                    continue;
2467
                }
2468
2469
                foreach ($users as $userId) {
2470
                    $userInfo = api_get_user_info($userId);
2471
2472
                    if (false !== strpos($text, $studentTag)) {
2473
                        $replacedText = str_replace($studentTag, $userInfo['complete_name'], $text);
2474
                        $values = [
2475
                            'c_id' => $courseId,
2476
                            'question_comment' => 'generated',
2477
                            'type' => $question['type'],
2478
                            'display' => $question['horizontalvertical'],
2479
                            'maximum_score' => $question['maximum_score'],
2480
                            'question' => $replacedText,
2481
                            'survey_id' => $surveyId,
2482
                            'question_id' => 0,
2483
                            'shared_question_id' => 0,
2484
                        ];
2485
2486
                        $answers = [];
2487
                        if (!empty($question['answers'])) {
2488
                            foreach ($question['answers'] as $answer) {
2489
                                $replacedText = str_replace($studentTag, $userInfo['complete_name'], $answer);
2490
                                $answers[] = $replacedText;
2491
                            }
2492
                        }
2493
                        $values['answers'] = $answers;
2494
                        self::save_question($surveyData, $values, false);
2495
                    }
2496
                }
2497
2498
                if ($classCounter < count($itemList)) {
2499
                    // Add end page
2500
                    $values = [
2501
                        'c_id' => $courseId,
2502
                        'question_comment' => 'generated',
2503
                        'type' => 'pagebreak',
2504
                        'display' => 'horizontal',
2505
                        'question' => get_lang('QuestionForNextClass'),
2506
                        'survey_id' => $surveyId,
2507
                        'question_id' => 0,
2508
                        'shared_question_id' => 0,
2509
                    ];
2510
                    self::save_question($surveyData, $values, false);
2511
                }
2512
            }
2513
        }
2514
2515
        return true;
2516
    }
2517
2518
    public static function hasDependency($survey)
2519
    {
2520
        if (false === api_get_configuration_value('survey_question_dependency')) {
2521
            return false;
2522
        }
2523
2524
        if (empty($survey)) {
2525
            return false;
2526
        }
2527
2528
        if (!isset($survey['survey_id'])) {
2529
            return false;
2530
        }
2531
2532
        $courseId = (int) $survey['c_id'];
2533
        $surveyId = (int) $survey['survey_id'];
2534
2535
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
2536
2537
        $sql = "SELECT COUNT(iid) count FROM $table
2538
                WHERE
2539
                    c_id = $courseId AND
2540
                    survey_id = $surveyId AND
2541
                    parent_option_id <> 0
2542
                LIMIT 1
2543
                ";
2544
        $result = Database::query($sql);
2545
        $row = Database::fetch_array($result);
2546
2547
        if ($row) {
2548
            return $row['count'] > 0;
2549
        }
2550
2551
        return false;
2552
    }
2553
2554
    /**
2555
     * @param array $survey
2556
     *
2557
     * @return int
2558
     */
2559
    public static function getCountPages($survey)
2560
    {
2561
        if (empty($survey) || !isset($survey['iid'])) {
2562
            return 0;
2563
        }
2564
2565
        $courseId = (int) $survey['c_id'];
2566
        $surveyId = (int) $survey['survey_id'];
2567
2568
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
2569
2570
        // pagebreak
2571
        $sql = "SELECT COUNT(iid) FROM $table
2572
                WHERE
2573
                    survey_question NOT LIKE '%{{%' AND
2574
                    type = 'pagebreak' AND
2575
                    c_id = $courseId AND
2576
                    survey_id = $surveyId";
2577
        $result = Database::query($sql);
2578
        $numberPageBreaks = Database::result($result, 0, 0);
2579
2580
        // No pagebreak
2581
        $sql = "SELECT COUNT(iid) FROM $table
2582
                WHERE
2583
                    survey_question NOT LIKE '%{{%' AND
2584
                    type != 'pagebreak' AND
2585
                    c_id = $courseId AND
2586
                    survey_id = $surveyId";
2587
        $result = Database::query($sql);
2588
        $countOfQuestions = Database::result($result, 0, 0);
2589
2590
        if ($survey['one_question_per_page'] == 1) {
2591
            if (!empty($countOfQuestions)) {
2592
                return $countOfQuestions;
2593
            }
2594
2595
            return 1;
2596
        }
2597
2598
        if (empty($numberPageBreaks)) {
2599
            return 1;
2600
        }
2601
2602
        return $numberPageBreaks + 1;
2603
    }
2604
2605
    /**
2606
     * Check whether this survey has ended. If so, display message and exit rhis script.
2607
     *
2608
     * @param array $surveyData Survey data
2609
     */
2610
    public static function checkTimeAvailability($surveyData)
2611
    {
2612
        if (empty($surveyData)) {
2613
            api_not_allowed(true);
2614
        }
2615
2616
        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
2617
        $utcZone = new DateTimeZone('UTC');
2618
        $startDate = new DateTime($surveyData['start_date'], $utcZone);
2619
        $endDate = new DateTime($surveyData['end_date'], $utcZone);
2620
        $currentDate = new DateTime('now', $utcZone);
2621
        if (!$allowSurveyAvailabilityDatetime) {
2622
            $currentDate->modify('today');
2623
        }
2624
        if ($currentDate < $startDate) {
2625
            api_not_allowed(
2626
                true,
2627
                Display:: return_message(
2628
                    get_lang('SurveyNotAvailableYet'),
2629
                    'warning',
2630
                    false
2631
                )
2632
            );
2633
        }
2634
2635
        if ($currentDate > $endDate) {
2636
            api_not_allowed(
2637
                true,
2638
                Display:: return_message(
2639
                    get_lang('SurveyNotAvailableAnymore'),
2640
                    'warning',
2641
                    false
2642
                )
2643
            );
2644
        }
2645
    }
2646
2647
    /**
2648
     * @param int    $userId
2649
     * @param string $surveyCode
2650
     * @param int    $courseId
2651
     * @param int    $sessionId
2652
     * @param int    $groupId
2653
     *
2654
     * @return array|CSurveyInvitation[]
2655
     */
2656
    public static function getUserInvitationsForSurveyInCourse(
2657
        $userId,
2658
        $surveyCode,
2659
        $courseId,
2660
        $sessionId = 0,
2661
        $groupId = 0
2662
    ) {
2663
        $invitationRepo = Database::getManager()->getRepository('ChamiloCourseBundle:CSurveyInvitation');
2664
2665
        return $invitationRepo->findBy(
2666
            [
2667
                'user' => $userId,
2668
                'cId' => $courseId,
2669
                'sessionId' => $sessionId,
2670
                'groupId' => $groupId,
2671
                'surveyCode' => $surveyCode,
2672
            ],
2673
            ['invitationDate' => 'DESC']
2674
        );
2675
    }
2676
2677
    /**
2678
     * @param array $userInfo
2679
     * @param int   $answered (1 = answered 0 = not answered)
2680
     *
2681
     * @return string
2682
     */
2683
    public static function surveyReport($userInfo, $answered = 0)
2684
    {
2685
        $userId = isset($userInfo['user_id']) ? (int) $userInfo['user_id'] : 0;
2686
        $answered = (int) $answered;
2687
2688
        if (empty($userId)) {
2689
            return '';
2690
        }
2691
2692
        $em = Database::getManager();
2693
        $repo = $em->getRepository('ChamiloCourseBundle:CSurveyInvitation');
2694
        $repoSurvey = $em->getRepository('ChamiloCourseBundle:CSurvey');
2695
        $invitations = $repo->findBy(['user' => $userId, 'answered' => $answered]);
2696
        $mainUrl = api_get_path(WEB_CODE_PATH).'survey/survey.php?';
2697
        $content = '';
2698
2699
        if (empty($answered)) {
2700
            $content .= Display::page_subheader(get_lang('Unanswered'));
2701
        } else {
2702
            $content .= Display::page_subheader(get_lang('Answered'));
2703
        }
2704
2705
        if (!empty($invitations)) {
2706
            $table = new HTML_Table(['class' => 'table']);
2707
            $table->setHeaderContents(0, 0, get_lang('SurveyName'));
2708
            $table->setHeaderContents(0, 1, get_lang('Course'));
2709
2710
            if (empty($answered)) {
2711
                $table->setHeaderContents(0, 2, get_lang('Survey').' - '.get_lang('EndDate'));
2712
            }
2713
2714
            // Not answered
2715
            /** @var CSurveyInvitation $invitation */
2716
            $row = 1;
2717
            foreach ($invitations as $invitation) {
2718
                $courseId = $invitation->getCId();
2719
                $courseInfo = api_get_course_info_by_id($courseId);
2720
2721
                $courseCode = $courseInfo['code'];
2722
                if (empty($courseInfo)) {
2723
                    continue;
2724
                }
2725
                $sessionId = $invitation->getSessionId();
2726
2727
                if (!empty($answered)) {
2728
                    // check if user is subscribed to the course/session
2729
                    if (empty($sessionId)) {
2730
                        $subscribe = CourseManager::is_user_subscribed_in_course($userId, $courseCode);
2731
                    } else {
2732
                        $subscribe = CourseManager::is_user_subscribed_in_course(
2733
                            $userId,
2734
                            $courseCode,
2735
                            true,
2736
                            $sessionId
2737
                        );
2738
                    }
2739
2740
                    // User is not subscribe skip!
2741
                    if (empty($subscribe)) {
2742
                        continue;
2743
                    }
2744
                }
2745
2746
                $surveyCode = $invitation->getSurveyCode();
2747
2748
                $survey = $repoSurvey->findOneBy([
2749
                    'cId' => $courseId,
2750
                    'sessionId' => $sessionId,
2751
                    'code' => $surveyCode,
2752
                ]);
2753
2754
                if (empty($survey)) {
2755
                    continue;
2756
                }
2757
2758
                $url = $mainUrl.'survey_id='.$survey->getSurveyId().'&cidReq='.$courseCode.'&id_session='.$sessionId;
2759
                $title = $survey->getTitle();
2760
                $title = Display::url($title, $url);
2761
2762
                if (!empty($sessionId)) {
2763
                    $sessionInfo = api_get_session_info($sessionId);
2764
                    $courseInfo['name'] .= ' ('.$sessionInfo['name'].')';
2765
                }
2766
2767
                $surveyData = self::get_survey($survey->getSurveyId(), 0, $courseCode);
2768
                $table->setCellContents($row, 0, $title);
2769
                $table->setCellContents($row, 1, $courseInfo['name']);
2770
2771
                if (empty($answered)) {
2772
                    $table->setHeaderContents(
2773
                        $row,
2774
                        2,
2775
                        api_get_local_time(
2776
                            $survey->getAvailTill(),
2777
                            null,
2778
                            null,
2779
                            true,
2780
                            false
2781
                        )
2782
                    );
2783
                }
2784
2785
                if (!empty($answered) && $surveyData['anonymous'] == 0) {
2786
                    $answers = SurveyUtil::displayCompleteReport(
2787
                        $surveyData,
2788
                        $userId,
2789
                        false,
2790
                        false,
2791
                        false
2792
                    );
2793
                    $table->setCellContents(++$row, 0, $answers);
2794
                    $table->setCellContents(++$row, 1, '');
2795
                }
2796
2797
                $row++;
2798
            }
2799
            $content .= $table->toHtml();
2800
        } else {
2801
            $content .= Display::return_message(get_lang('NoData'));
2802
        }
2803
2804
        return $content;
2805
    }
2806
2807
    public static function sendToTutors($surveyId)
2808
    {
2809
        $survey = Database::getManager()->getRepository('ChamiloCourseBundle:CSurvey')->find($surveyId);
2810
        if (null === $survey) {
2811
            return false;
2812
        }
2813
2814
        $extraFieldValue = new ExtraFieldValue('survey');
2815
        $groupData = $extraFieldValue->get_values_by_handler_and_field_variable($surveyId, 'group_id');
2816
        if ($groupData && !empty($groupData['value'])) {
2817
            $groupInfo = GroupManager::get_group_properties($groupData['value']);
2818
            if ($groupInfo) {
2819
                $tutors = GroupManager::getTutors($groupInfo);
2820
                if (!empty($tutors)) {
2821
                    SurveyUtil::saveInviteMail(
2822
                        $survey,
2823
                        ' ',
2824
                        ' ',
2825
                        false
2826
                    );
2827
2828
                    foreach ($tutors as $tutor) {
2829
                        $subject = sprintf(get_lang('GroupSurveyX'), $groupInfo['name']);
2830
                        $content = sprintf(
2831
                            get_lang('HelloXGroupX'),
2832
                            $tutor['complete_name'],
2833
                            $groupInfo['name']
2834
                        );
2835
2836
                        SurveyUtil::saveInvitations(
2837
                            $surveyId,
2838
                            ['users' => $tutor['user_id']],
2839
                            $subject,
2840
                            $content,
2841
                            false,
2842
                            true,
2843
                            false,
2844
                            true
2845
                        );
2846
                    }
2847
                    Display::addFlash(Display::return_message(get_lang('Updated'), 'confirmation', false));
2848
                }
2849
                SurveyUtil::update_count_invited($survey->getCode());
2850
2851
                return true;
2852
            }
2853
        }
2854
2855
        return false;
2856
    }
2857
}
2858