Passed
Push — 1.11.x ( ab4346...9c97d4 )
by Julito
10:45
created

SurveyManager::save_question_options()   B

Complexity

Conditions 11
Paths 48

Size

Total Lines 45
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 29
nc 48
nop 2
dl 0
loc 45
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

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

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

395
                self::copy_survey($values['parent_id'], /** @scrutinizer ignore-type */ $survey_id);
Loading history...
396
            }
397
398
            Display::addFlash(
399
                Display::return_message(
400
                    get_lang('SurveyCreatedSuccesfully'),
401
                    'success'
402
                )
403
            );
404
            $return['id'] = $survey_id;
405
        } else {
406
            // Check whether the code doesn't soon exists in this language
407
            $sql = 'SELECT 1 FROM '.$table_survey.'
408
			        WHERE
409
			            c_id = '.$course_id.' AND
410
			            code = "'.Database::escape_string($values['survey_code']).'" AND
411
			            lang = "'.Database::escape_string($values['survey_language']).'" AND
412
			            survey_id !='.intval($values['survey_id']);
413
            $rs = Database::query($sql);
414
            if (Database::num_rows($rs) > 0) {
415
                Display::addFlash(
416
                    Display::return_message(
417
                        get_lang('ThisSurveyCodeSoonExistsInThisLanguage'),
418
                        'error'
419
                    )
420
                );
421
                $return['type'] = 'error';
422
                $return['id'] = isset($values['survey_id']) ? $values['survey_id'] : 0;
423
424
                return $return;
425
            }
426
427
            if (!isset($values['anonymous'])
428
                || (isset($values['anonymous']) && $values['anonymous'] == '')
429
            ) {
430
                $values['anonymous'] = 0;
431
            }
432
433
            $extraParams = [];
434
            $extraParams['one_question_per_page'] = isset($values['one_question_per_page']) ? $values['one_question_per_page'] : 0;
435
            $extraParams['shuffle'] = isset($values['shuffle']) ? $values['shuffle'] : 0;
436
437
            if ($values['anonymous'] == 0) {
438
                $extraParams['show_form_profile'] = isset($values['show_form_profile']) ? $values['show_form_profile'] : 0;
439
                if ($extraParams['show_form_profile'] == 1) {
440
                    $fields = explode(',', $values['input_name_list']);
441
                    $field_values = '';
442
                    foreach ($fields as &$field) {
443
                        if ($field != '') {
444
                            if (!isset($values[$field]) ||
445
                                (isset($values[$field]) && $values[$field] == '')
446
                            ) {
447
                                $values[$field] = 0;
448
                            }
449
                            $field_values .= $field.':'.$values[$field].'@';
450
                        }
451
                    }
452
                    $extraParams['form_fields'] = $field_values;
453
                } else {
454
                    $extraParams['form_fields'] = '';
455
                }
456
            } else {
457
                $extraParams['show_form_profile'] = 0;
458
                $extraParams['form_fields'] = '';
459
            }
460
461
            $params = [
462
                'title' => $values['survey_title'],
463
                'subtitle' => $values['survey_subtitle'],
464
                'author' => $_user['user_id'],
465
                'lang' => $values['survey_language'],
466
                'avail_from' => $allowSurveyAvailabilityDatetime
467
                    ? api_get_utc_datetime($values['start_date'].':00')
468
                    : $values['start_date'],
469
                'avail_till' => $allowSurveyAvailabilityDatetime
470
                    ? api_get_utc_datetime($values['end_date'].':59')
471
                    : $values['end_date'],
472
                'is_shared' => $shared_survey_id,
473
                'template' => 'template',
474
                'intro' => $values['survey_introduction'],
475
                'surveythanks' => $values['survey_thanks'],
476
                'anonymous' => $values['anonymous'],
477
                'session_id' => api_get_session_id(),
478
                'visible_results' => $values['visible_results'],
479
            ];
480
481
            $params = array_merge($params, $extraParams);
482
            Database::update(
483
                $table_survey,
484
                $params,
485
                [
486
                    'c_id = ? AND survey_id = ?' => [
487
                        $course_id,
488
                        $values['survey_id'],
489
                    ],
490
                ]
491
            );
492
493
            // Update into item_property (update)
494
            api_item_property_update(
495
                api_get_course_info(),
496
                TOOL_SURVEY,
497
                $values['survey_id'],
498
                'SurveyUpdated',
499
                api_get_user_id()
500
            );
501
502
            Display::addFlash(
503
                Display::return_message(
504
                    get_lang('SurveyUpdatedSuccesfully'),
505
                    'confirmation'
506
                )
507
            );
508
509
            $return['id'] = $values['survey_id'];
510
        }
511
512
        $survey_id = (int) $return['id'];
513
514
        // Gradebook
515
        $gradebook_option = false;
516
        if (isset($values['survey_qualify_gradebook'])) {
517
            $gradebook_option = $values['survey_qualify_gradebook'] > 0;
518
        }
519
520
        $gradebook_link_type = 8;
521
        $link_info = GradebookUtils::isResourceInCourseGradebook(
522
            $courseCode,
523
            $gradebook_link_type,
524
            $survey_id,
525
            $session_id
526
        );
527
528
        $gradebook_link_id = isset($link_info['id']) ? $link_info['id'] : false;
529
530
        if ($gradebook_option) {
531
            if ($survey_id > 0) {
532
                $title_gradebook = ''; // Not needed here.
533
                $description_gradebook = ''; // Not needed here.
534
                $survey_weight = floatval($_POST['survey_weight']);
535
                $max_score = 1;
536
537
                if (!$gradebook_link_id) {
538
                    GradebookUtils::add_resource_to_course_gradebook(
539
                        $values['category_id'],
540
                        $courseCode,
541
                        $gradebook_link_type,
542
                        $survey_id,
543
                        $title_gradebook,
544
                        $survey_weight,
545
                        $max_score,
546
                        $description_gradebook,
547
                        1,
548
                        $session_id
549
                    );
550
                } else {
551
                    GradebookUtils::updateResourceFromCourseGradebook(
552
                        $gradebook_link_id,
553
                        $courseCode,
554
                        $survey_weight
555
                    );
556
                }
557
            }
558
        } else {
559
            // Delete everything of the gradebook for this $linkId
560
            GradebookUtils::remove_resource_from_course_gradebook($gradebook_link_id);
561
        }
562
563
        return $return;
564
    }
565
566
    /**
567
     * This function stores a shared survey in the central database.
568
     *
569
     * @param array $values
570
     *
571
     * @return array $return the type of return message that has to be displayed and the message in it
572
     *
573
     * @author Patrick Cool <[email protected]>, Ghent University
574
     *
575
     * @version February 2007
576
     */
577
    public function store_shared_survey($values)
578
    {
579
        $_user = api_get_user_info();
580
        $_course = api_get_course_info();
581
582
        // Table definitions
583
        $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
584
585
        if (!$values['survey_id'] ||
586
            !is_numeric($values['survey_id']) ||
587
            $values['survey_share']['survey_share'] == 'true'
588
        ) {
589
            $sql = "INSERT INTO $table_survey (code, title, subtitle, author, lang, template, intro, surveythanks, creation_date, course_code) VALUES (
590
                    '".Database::escape_string($values['survey_code'])."',
591
                    '".Database::escape_string($values['survey_title'])."',
592
                    '".Database::escape_string($values['survey_subtitle'])."',
593
                    '".intval($_user['user_id'])."',
594
                    '".Database::escape_string($values['survey_language'])."',
595
                    '".Database::escape_string('template')."',
596
                    '".Database::escape_string($values['survey_introduction'])."',
597
                    '".Database::escape_string($values['survey_thanks'])."',
598
                    '".api_get_utc_datetime()."',
599
                    '".$_course['id']."')";
600
            Database::query($sql);
601
            $return = Database::insert_id();
602
603
            $sql = "UPDATE $table_survey SET survey_id = $return WHERE iid = $return";
604
            Database::query($sql);
605
        } else {
606
            $sql = "UPDATE $table_survey SET
607
                        code 			= '".Database::escape_string($values['survey_code'])."',
608
                        title 			= '".Database::escape_string($values['survey_title'])."',
609
                        subtitle 		= '".Database::escape_string($values['survey_subtitle'])."',
610
                        author 			= '".intval($_user['user_id'])."',
611
                        lang 			= '".Database::escape_string($values['survey_language'])."',
612
                        template 		= '".Database::escape_string('template')."',
613
                        intro			= '".Database::escape_string($values['survey_introduction'])."',
614
                        surveythanks	= '".Database::escape_string($values['survey_thanks'])."'
615
					WHERE survey_id = '".Database::escape_string($values['survey_share']['survey_share'])."'";
616
            Database::query($sql);
617
            $return = $values['survey_share']['survey_share'];
618
        }
619
620
        return $return;
621
    }
622
623
    /**
624
     * This function deletes a survey (and also all the question in that survey.
625
     *
626
     * @param int  $survey_id id of the survey that has to be deleted
627
     * @param bool $shared
628
     * @param int  $course_id
629
     *
630
     * @return true
631
     *
632
     * @author Patrick Cool <[email protected]>, Ghent University
633
     *
634
     * @version January 2007
635
     */
636
    public static function delete_survey($survey_id, $shared = false, $course_id = 0)
637
    {
638
        // Database table definitions
639
        if (empty($course_id)) {
640
            $course_id = api_get_course_int_id();
641
        }
642
643
        $survey_id = (int) $survey_id;
644
645
        if (empty($survey_id)) {
646
            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...
647
        }
648
649
        $course_info = api_get_course_info_by_id($course_id);
650
        $course_id = $course_info['real_id'];
651
652
        $table_survey = Database::get_course_table(TABLE_SURVEY);
653
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
654
655
        if ($shared) {
656
            $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
657
            // Deleting the survey
658
            $sql = "DELETE FROM $table_survey
659
                    WHERE survey_id='".$survey_id."'";
660
            Database::query($sql);
661
        } else {
662
            $sql = "DELETE FROM $table_survey
663
                    WHERE c_id = $course_id AND survey_id='".$survey_id."'";
664
            Database::query($sql);
665
        }
666
667
        // Deleting groups of this survey
668
        $sql = "DELETE FROM $table_survey_question_group
669
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
670
        Database::query($sql);
671
672
        // Deleting the questions of the survey
673
        self::delete_all_survey_questions($survey_id, $shared);
674
675
        // Update into item_property (delete)
676
        api_item_property_update(
677
            $course_info,
678
            TOOL_SURVEY,
679
            $survey_id,
680
            'SurveyDeleted',
681
            api_get_user_id()
682
        );
683
684
        Skill::deleteSkillsFromItem($survey_id, ITEM_TYPE_SURVEY);
685
686
        return true;
687
    }
688
689
    /**
690
     * @param int $survey_id
691
     * @param int $new_survey_id
692
     * @param int $targetCourseId
693
     *
694
     * @return bool
695
     */
696
    public static function copy_survey(
697
        $survey_id,
698
        $new_survey_id = null,
699
        $targetCourseId = null
700
    ) {
701
        $course_id = api_get_course_int_id();
702
        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...
703
            $targetCourseId = $course_id;
704
        }
705
706
        // Database table definitions
707
        $table_survey = Database::get_course_table(TABLE_SURVEY);
708
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
709
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
710
        $table_survey_options = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
711
        $survey_id = (int) $survey_id;
712
713
        // Get groups
714
        $survey_data = self::get_survey($survey_id, 0, null, true);
715
        if (empty($survey_data)) {
716
            return true;
717
        }
718
719
        if (empty($new_survey_id)) {
720
            $params = $survey_data;
721
            $params['code'] = self::generate_unique_code($params['code']);
722
            $params['c_id'] = $targetCourseId;
723
            unset($params['survey_id']);
724
            $params['session_id'] = api_get_session_id();
725
            $params['title'] = $params['title'].' '.get_lang('Copy');
726
            unset($params['iid']);
727
            $new_survey_id = Database::insert($table_survey, $params);
728
729
            if ($new_survey_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_survey_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...
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
1019
        $result = Database::query($sql);
1020
        $row = Database::fetch_array($result, 'ASSOC');
1021
1022
        $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...
1023
        $return['question_id'] = $row['question_id'];
1024
        $return['type'] = $row['type'];
1025
        $return['question'] = $row['survey_question'];
1026
        $return['horizontalvertical'] = $row['display'];
1027
        $return['shared_question_id'] = $row['shared_question_id'];
1028
        $return['maximum_score'] = $row['max_value'];
1029
        $return['is_required'] = api_get_configuration_value('allow_required_survey_questions')
1030
            ? $row['is_required']
1031
            : false;
1032
1033
        if ($row['survey_group_pri'] != 0) {
1034
            $return['assigned'] = $row['survey_group_pri'];
1035
            $return['choose'] = 1;
1036
        } else {
1037
            $return['assigned1'] = $row['survey_group_sec1'];
1038
            $return['assigned2'] = $row['survey_group_sec2'];
1039
            $return['choose'] = 2;
1040
        }
1041
1042
        // Getting the information of the question options
1043
        $result = Database::query($sqlOption);
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
            /** @todo this can be done more elegantly (used in reporting) */
1050
            $return['answersid'][] = $row['question_option_id'];
1051
        }
1052
1053
        return $return;
1054
    }
1055
1056
    /**
1057
     * This function gets all the question of any given survey.
1058
     *
1059
     * @param int $surveyId the id of the survey
1060
     * @param int $courseId
1061
     *
1062
     * @return array containing all the questions of the survey
1063
     *
1064
     * @author Patrick Cool <[email protected]>, Ghent University
1065
     *
1066
     * @version February 2007
1067
     *
1068
     * @todo one sql call should do the trick
1069
     */
1070
    public static function get_questions($surveyId, $courseId = 0)
1071
    {
1072
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1073
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1074
1075
        $courseId = (int) $courseId;
1076
        $surveyId = (int) $surveyId;
1077
1078
        if (empty($courseId)) {
1079
            $courseId = api_get_course_int_id();
1080
        }
1081
1082
        // Getting the information of the question
1083
        $sql = "SELECT * FROM $tbl_survey_question
1084
		        WHERE c_id = $courseId AND survey_id='".$surveyId."'";
1085
        $result = Database::query($sql);
1086
        $return = [];
1087
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1088
            $return[$row['question_id']]['survey_id'] = $row['survey_id'];
1089
            $return[$row['question_id']]['question_id'] = $row['question_id'];
1090
            $return[$row['question_id']]['type'] = $row['type'];
1091
            $return[$row['question_id']]['question'] = $row['survey_question'];
1092
            $return[$row['question_id']]['horizontalvertical'] = $row['display'];
1093
            $return[$row['question_id']]['maximum_score'] = $row['max_value'];
1094
            $return[$row['question_id']]['sort'] = $row['sort'];
1095
            $return[$row['question_id']]['survey_question_comment'] = $row['survey_question_comment'];
1096
        }
1097
1098
        // Getting the information of the question options
1099
        $sql = "SELECT * FROM $table_survey_question_option
1100
		        WHERE c_id = $courseId AND survey_id='".$surveyId."'";
1101
        $result = Database::query($sql);
1102
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1103
            $return[$row['question_id']]['answers'][] = $row['option_text'];
1104
        }
1105
1106
        return $return;
1107
    }
1108
1109
    /**
1110
     * This function saves a question in the database.
1111
     * This can be either an update of an existing survey or storing a new survey.
1112
     *
1113
     * @param array $survey_data
1114
     * @param array $form_content all the information of the form
1115
     *
1116
     * @return string
1117
     *
1118
     * @author Patrick Cool <[email protected]>, Ghent University
1119
     *
1120
     * @version January 2007
1121
     */
1122
    public static function save_question($survey_data, $form_content, $showMessage = true)
1123
    {
1124
        $return_message = '';
1125
        if (strlen($form_content['question']) > 1) {
1126
            // Checks length of the question
1127
            $empty_answer = false;
1128
1129
            if ($survey_data['survey_type'] == 1) {
1130
                if (empty($form_content['choose'])) {
1131
                    $return_message = 'PleaseChooseACondition';
1132
1133
                    return $return_message;
1134
                }
1135
1136
                if (($form_content['choose'] == 2) &&
1137
                    ($form_content['assigned1'] == $form_content['assigned2'])
1138
                ) {
1139
                    $return_message = 'ChooseDifferentCategories';
1140
1141
                    return $return_message;
1142
                }
1143
            }
1144
1145
            if ($form_content['type'] != 'percentage') {
1146
                if (isset($form_content['answers'])) {
1147
                    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...
1148
                        if (strlen($form_content['answers'][$i]) < 1) {
1149
                            $empty_answer = true;
1150
                            break;
1151
                        }
1152
                    }
1153
                }
1154
            }
1155
1156
            if ($form_content['type'] == 'score') {
1157
                if (strlen($form_content['maximum_score']) < 1) {
1158
                    $empty_answer = true;
1159
                }
1160
            }
1161
            $course_id = api_get_course_int_id();
1162
            if (!$empty_answer) {
1163
                // Table definitions
1164
                $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1165
1166
                // Getting all the information of the survey
1167
                $survey_data = self::get_survey($form_content['survey_id']);
1168
1169
                // Storing the question in the shared database
1170
                if (is_numeric($survey_data['survey_share']) && $survey_data['survey_share'] != 0) {
1171
                    $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

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

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

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