Passed
Push — 1.11.x ( 698144...1872f9 )
by Julito
12:41
created

SurveyManager::delete_all_survey_answers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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

316
                        $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...
317
                        if ($pos === false) {
318
                            $row['survey_version'] = $row['survey_version'] + 1;
319
                            $versionValue = $row['survey_version'];
320
                        } else {
321
                            $getlast = explode('\.', $row['survey_version']);
322
                            $lastversion = array_pop($getlast);
323
                            $lastversion = $lastversion + 1;
324
                            $add = implode('.', $getlast);
325
                            if ($add != '') {
326
                                $insertnewversion = $add.'.'.$lastversion;
327
                            } else {
328
                                $insertnewversion = $lastversion;
329
                            }
330
                            $versionValue = $insertnewversion;
331
                        }
332
                    }
333
                    $extraParams['survey_version'] = $versionValue;
334
                }
335
            }
336
337
            $params = [
338
                'c_id' => $course_id,
339
                'code' => self::generateSurveyCode($values['survey_code']),
340
                'title' => $values['survey_title'],
341
                'subtitle' => $values['survey_subtitle'],
342
                'author' => $_user['user_id'],
343
                'lang' => $values['survey_language'],
344
                'is_shared' => $shared_survey_id,
345
                'template' => 'template',
346
                'intro' => $values['survey_introduction'],
347
                'surveythanks' => $values['survey_thanks'],
348
                'creation_date' => api_get_utc_datetime(),
349
                'anonymous' => $values['anonymous'],
350
                'session_id' => api_get_session_id(),
351
                'visible_results' => $values['visible_results'],
352
            ];
353
354
            if (!empty($values['start_date'])) {
355
                if ($allowSurveyAvailabilityDatetime) {
356
                    $params['avail_from'] = api_get_utc_datetime($values['start_date'].':00');
357
                } else {
358
                    $params['avail_from'] = $values['start_date'];
359
                }
360
            }
361
362
            if (!empty($values['end_date'])) {
363
                if ($allowSurveyAvailabilityDatetime) {
364
                    $params['avail_till'] = api_get_utc_datetime($values['end_date'].':00');
365
                } else {
366
                    $params['avail_till'] = $values['end_date'];
367
                }
368
            }
369
370
            if (isset($values['survey_type']) && !empty($values['survey_type'])) {
371
                $params['survey_type'] = $values['survey_type'];
372
            }
373
374
            $params = array_merge($params, $extraParams);
375
376
            $survey_id = Database::insert($table_survey, $params);
377
            if ($survey_id > 0) {
378
                $sql = "UPDATE $table_survey SET survey_id = $survey_id
379
                        WHERE iid = $survey_id";
380
                Database::query($sql);
381
382
                // Insert into item_property
383
                api_item_property_update(
384
                    api_get_course_info(),
385
                    TOOL_SURVEY,
386
                    $survey_id,
0 ignored issues
show
Bug introduced by
It seems like $survey_id can also be of type false; however, parameter $item_id of api_item_property_update() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

386
                    /** @scrutinizer ignore-type */ $survey_id,
Loading history...
387
                    'SurveyAdded',
388
                    api_get_user_id()
389
                );
390
            }
391
392
            if ($values['survey_type'] == 1 && !empty($values['parent_id'])) {
393
                self::copy_survey($values['parent_id'], $survey_id);
0 ignored issues
show
Bug introduced by
It seems like $survey_id can also be of type false; however, parameter $new_survey_id of SurveyManager::copy_survey() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

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

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

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

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

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

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

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