Passed
Push — master ( 9d7978...5faf0b )
by Julito
10:24
created

SurveyManager::checkTimeAvailability()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 32
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 23
nc 16
nop 1
dl 0
loc 32
rs 9.2408
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CSurvey;
5
use Chamilo\CourseBundle\Entity\CSurveyInvitation;
6
use Chamilo\CourseBundle\Entity\CSurveyQuestion;
7
use Chamilo\CourseBundle\Entity\CSurveyQuestionOption;
8
9
/**
10
 * Class SurveyManager.
11
 *
12
 * @package chamilo.survey
13
 *
14
 * @author Patrick Cool <[email protected]>, Ghent University:
15
 * cleanup, refactoring and rewriting large parts (if not all) of the code
16
 * @author Julio Montoya <[email protected]>, Personality Test modification
17
 * and rewriting large parts of the code
18
 * @author cfasanando
19
 *
20
 * @todo move this file to inc/lib
21
 * @todo use consistent naming for the functions (save vs store for instance)
22
 */
23
class SurveyManager
24
{
25
    /**
26
     * @param $code
27
     *
28
     * @return string
29
     */
30
    public static function generate_unique_code($code)
31
    {
32
        if (empty($code)) {
33
            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...
34
        }
35
        $course_id = api_get_course_int_id();
36
        $table = Database::get_course_table(TABLE_SURVEY);
37
        $code = Database::escape_string($code);
38
        $num = 0;
39
        $new_code = $code;
40
        while (true) {
41
            $sql = "SELECT * FROM $table
42
                    WHERE code = '$new_code' AND c_id = $course_id";
43
            $result = Database::query($sql);
44
            if (Database::num_rows($result)) {
45
                $num++;
46
                $new_code = $code.$num;
47
            } else {
48
                break;
49
            }
50
        }
51
52
        return $code.$num;
53
    }
54
55
    /**
56
     * Deletes all survey invitations of a user.
57
     *
58
     * @param int $user_id
59
     *
60
     * @return bool
61
     * @assert ('') === false
62
     */
63
    public static function delete_all_survey_invitations_by_user($user_id)
64
    {
65
        $user_id = intval($user_id);
66
        if (empty($user_id)) {
67
            return false;
68
        }
69
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
70
        $table_survey = Database::get_course_table(TABLE_SURVEY);
71
72
        $sql = "SELECT survey_invitation_id, survey_code
73
                FROM $table_survey_invitation WHERE user = '$user_id' AND c_id <> 0 ";
74
        $result = Database::query($sql);
75
        while ($row = Database::fetch_array($result, 'ASSOC')) {
76
            $survey_invitation_id = $row['survey_invitation_id'];
77
            $survey_code = $row['survey_code'];
78
            $sql2 = "DELETE FROM $table_survey_invitation
79
                    WHERE survey_invitation_id = '$survey_invitation_id' AND c_id <> 0";
80
            if (Database::query($sql2)) {
81
                $sql3 = "UPDATE $table_survey SET
82
                            invited = invited-1
83
                        WHERE c_id <> 0 AND code ='$survey_code'";
84
                Database::query($sql3);
85
            }
86
        }
87
    }
88
89
    /**
90
     * @param string $course_code
91
     * @param int    $session_id
92
     *
93
     * @return array
94
     * @assert ('') === false
95
     */
96
    public static function get_surveys($course_code, $session_id = 0)
97
    {
98
        if (empty($course_code)) {
99
            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...
100
        }
101
        $course_info = api_get_course_info($course_code);
102
103
        if (empty($course_info)) {
104
            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...
105
        }
106
107
        $session_condition = api_get_session_condition($session_id, true, true);
108
109
        $table = Database::get_course_table(TABLE_SURVEY);
110
        $sql = "SELECT * FROM $table
111
                WHERE c_id = {$course_info['real_id']} $session_condition ";
112
        $result = Database::query($sql);
113
        $result = Database::store_result($result, 'ASSOC');
114
115
        return $result;
116
    }
117
118
    /**
119
     * Retrieves all the survey information.
120
     *
121
     * @param int  $survey_id the id of the survey
122
     * @param bool $shared    this parameter determines if
123
     *                        we have to get the information of a survey from the central (shared) database or from the
124
     *                        course database
125
     * @param string course code optional
126
     *
127
     * @author Patrick Cool <[email protected]>, Ghent University
128
     *
129
     * @version February 2007
130
     * @assert ('') === false
131
     *
132
     * @return array
133
     *
134
     * @todo this is the same function as in create_new_survey.php
135
     */
136
    public static function get_survey(
137
        $survey_id,
138
        $shared = 0,
139
        $course_code = '',
140
        $simple_return = false
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
        } else {
148
            $my_course_id = api_get_course_id();
149
        }
150
        $courseInfo = api_get_course_info($my_course_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='".intval($survey_id)."' ";
157
        } else {
158
            if (empty($courseInfo)) {
159
                return [];
160
            }
161
            $sql = "SELECT * FROM $table_survey
162
		            WHERE
163
		                survey_id='".intval($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
259
            $survey = new CSurvey();
260
261
            $extraParams = [];
262
            if ($values['anonymous'] == 0) {
263
                // Input_name_list
264
                $values['show_form_profile'] = isset($values['show_form_profile']) ? $values['show_form_profile'] : 0;
265
                $survey->setShowFormProfile($values['show_form_profile']);
266
267
                if ($values['show_form_profile'] == 1) {
268
                    // Input_name_list
269
                    $fields = explode(',', $values['input_name_list']);
270
                    $field_values = '';
271
                    foreach ($fields as &$field) {
272
                        if ($field != '') {
273
                            if ($values[$field] == '') {
274
                                $values[$field] = 0;
275
                            }
276
                            $field_values .= $field.':'.$values[$field].'@';
277
                        }
278
                    }
279
                    $extraParams['form_fields'] = $field_values;
280
                } else {
281
                    $extraParams['form_fields'] = '';
282
                }
283
                $survey->setFormFields($extraParams['form_fields']);
284
            } else {
285
                $survey->setShowFormProfile(0);
286
                $survey->setFormFields(0);
287
            }
288
289
            if ($values['survey_type'] == 1) {
290
                $survey
291
                    ->setSurveyType(1)
292
                    ->setShuffle($values['shuffle'])
293
                    ->setOneQuestionPerPage($values['one_question_per_page'])
294
                    ->setParentId($values['parent_id'])
295
                ;
296
                // Logic for versioning surveys
297
                if (!empty($values['parent_id'])) {
298
                    $versionValue = '';
299
                    $sql = 'SELECT survey_version
300
                            FROM '.$table_survey.'
301
					        WHERE
302
					            c_id = '.$course_id.' AND
303
					            parent_id = '.intval($values['parent_id']).'
304
                            ORDER BY survey_version DESC
305
                            LIMIT 1';
306
                    $rs = Database::query($sql);
307
                    if (Database::num_rows($rs) === 0) {
308
                        $sql = 'SELECT survey_version FROM '.$table_survey.'
309
						        WHERE
310
						            c_id = '.$course_id.' AND
311
						            survey_id = '.intval($values['parent_id']);
312
                        $rs = Database::query($sql);
313
                        $getversion = Database::fetch_array($rs, 'ASSOC');
314
                        if (empty($getversion['survey_version'])) {
315
                            $versionValue = ++$getversion['survey_version'];
316
                        } else {
317
                            $versionValue = $getversion['survey_version'];
318
                        }
319
                    } else {
320
                        $row = Database::fetch_array($rs, 'ASSOC');
321
                        $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

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

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

1526
            self::/** @scrutinizer ignore-call */ 
1527
                  save_shared_question_options($form_content, $survey_data);
Loading history...
1527
        }
1528
1529
        // Table definition
1530
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1531
1532
        // We are editing a question so we first have to remove all the existing options from the database
1533
        if (is_numeric($form_content['question_id'])) {
1534
            $sql = "DELETE FROM $table_survey_question_option
1535
			        WHERE c_id = $course_id AND question_id = '".intval($form_content['question_id'])."'";
1536
            Database::query($sql);
1537
        }
1538
1539
        $counter = 1;
1540
        $em = Database::getManager();
1541
        if (isset($form_content['answers']) && is_array($form_content['answers'])) {
1542
            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...
1543
                $values = isset($form_content['values']) ? $form_content['values'][$i] : 0;
1544
                $option = new CSurveyQuestionOption();
1545
                $option
1546
                    ->setCId($course_id)
1547
                    ->setQuestionId($form_content['question_id'])
1548
                    ->setSurveyId($form_content['survey_id'])
1549
                    ->setOptionText($form_content['answers'][$i])
1550
                    ->setValue($values)
1551
                    ->setSort($counter)
1552
                ;
1553
1554
                $em->persist($option);
1555
                $em->flush();
1556
1557
                $insertId = $option->getIid();
1558
                if ($insertId) {
1559
                    $sql = "UPDATE $table_survey_question_option
1560
                            SET question_option_id = $insertId
1561
                            WHERE iid = $insertId";
1562
                    Database::query($sql);
1563
1564
                    $counter++;
1565
                }
1566
            }
1567
        }
1568
    }
1569
1570
    /**
1571
     * This function stores the options of the questions in the shared table.
1572
     *
1573
     * @param array $form_content
1574
     *
1575
     * @author Patrick Cool <[email protected]>, Ghent University
1576
     *
1577
     * @version February 2007
1578
     *
1579
     * @todo writing the update statement when editing a question
1580
     */
1581
    public function save_shared_question_options($form_content, $survey_data)
1582
    {
1583
        if (is_array($form_content) && is_array($form_content['answers'])) {
1584
            // Table definition
1585
            $table = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1586
1587
            // We are editing a question so we first have to remove all the existing options from the database
1588
            $sql = "DELETE FROM $table
1589
                    WHERE question_id = '".Database::escape_string($form_content['shared_question_id'])."'";
1590
            Database::query($sql);
1591
1592
            $counter = 1;
1593
            foreach ($form_content['answers'] as &$answer) {
1594
                $params = [
1595
                    'question_id' => $form_content['shared_question_id'],
1596
                    'survey_id' => $survey_data['is_shared'],
1597
                    'option_text' => $answer,
1598
                    'sort' => $counter,
1599
                ];
1600
                Database::insert($table, $params);
1601
1602
                $counter++;
1603
            }
1604
        }
1605
    }
1606
1607
    /**
1608
     * This function deletes all the options of the questions of a given survey
1609
     * This function is normally only called when a survey is deleted.
1610
     *
1611
     * @param $survey_id the id of the survey that has to be deleted
1612
     *
1613
     * @return true
1614
     *
1615
     * @author Patrick Cool <[email protected]>, Ghent University
1616
     *
1617
     * @version January 2007
1618
     */
1619
    public static function delete_all_survey_questions_options($survey_id, $shared = false)
1620
    {
1621
        // Table definitions
1622
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1623
        $course_id = api_get_course_int_id();
1624
        $course_condition = " c_id = $course_id AND ";
1625
        if ($shared) {
1626
            $course_condition = '';
1627
            $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1628
        }
1629
1630
        $sql = "DELETE FROM $table_survey_question_option
1631
                WHERE $course_condition survey_id='".intval($survey_id)."'";
1632
1633
        // Deleting the options of the survey questions
1634
        Database::query($sql);
1635
1636
        return true;
1637
    }
1638
1639
    /**
1640
     * This function deletes the options of a given question.
1641
     *
1642
     * @param int  $survey_id
1643
     * @param int  $question_id
1644
     * @param bool $shared
1645
     *
1646
     * @return bool
1647
     *
1648
     * @author Patrick Cool <[email protected]>, Ghent University
1649
     * @author Julio Montoya
1650
     *
1651
     * @version March 2007
1652
     */
1653
    public static function delete_survey_question_option(
1654
        $survey_id,
1655
        $question_id,
1656
        $shared = false
1657
    ) {
1658
        $course_id = api_get_course_int_id();
1659
        $course_condition = " c_id = $course_id AND ";
1660
1661
        // Table definitions
1662
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1663
        if ($shared) {
1664
            $course_condition = '';
1665
            $table = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1666
        }
1667
1668
        // Deleting the options of the survey questions
1669
        $sql = "DELETE FROM $table
1670
		        WHERE
1671
		            $course_condition survey_id='".intval($survey_id)."' AND
1672
		            question_id='".intval($question_id)."'";
1673
        Database::query($sql);
1674
1675
        return true;
1676
    }
1677
1678
    /**
1679
     * SURVEY ANSWERS FUNCTIONS.
1680
     */
1681
1682
    /**
1683
     * This function deletes all the answers anyone has given on this survey
1684
     * This function is normally only called when a survey is deleted.
1685
     *
1686
     * @param $survey_id the id of the survey that has to be deleted
1687
     *
1688
     * @return true
1689
     *
1690
     * @todo write the function
1691
     *
1692
     * @author Patrick Cool <[email protected]>, Ghent University
1693
     *
1694
     * @version January 2007,december 2008
1695
     */
1696
    public static function delete_all_survey_answers($survey_id)
1697
    {
1698
        $course_id = api_get_course_int_id();
1699
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
1700
        $survey_id = intval($survey_id);
1701
        $sql = "DELETE FROM $table 
1702
                WHERE c_id = $course_id AND survey_id=$survey_id";
1703
        Database::query($sql);
1704
1705
        return true;
1706
    }
1707
1708
    /**
1709
     * @param int $user_id
1710
     * @param int $survey_id
1711
     * @param int $course_id
1712
     *
1713
     * @return bool
1714
     */
1715
    public static function is_user_filled_survey($user_id, $survey_id, $course_id)
1716
    {
1717
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
1718
        $user_id = intval($user_id);
1719
        $course_id = intval($course_id);
1720
        $survey_id = intval($survey_id);
1721
1722
        $sql = "SELECT DISTINCT user 
1723
                FROM $table
1724
                WHERE
1725
                    c_id		= $course_id AND
1726
                    user		= $user_id AND
1727
                    survey_id	= $survey_id";
1728
        $result = Database::query($sql);
1729
        if (Database::num_rows($result)) {
1730
            return true;
1731
        }
1732
1733
        return false;
1734
    }
1735
1736
    /**
1737
     * This function gets all the persons who have filled the survey.
1738
     *
1739
     * @param int $survey_id
1740
     *
1741
     * @return array
1742
     *
1743
     * @author Patrick Cool <[email protected]>, Ghent University
1744
     *
1745
     * @version February 2007
1746
     */
1747
    public static function get_people_who_filled_survey(
1748
        $survey_id,
1749
        $all_user_info = false,
1750
        $course_id = null
1751
    ) {
1752
        // Database table definition
1753
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1754
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1755
1756
        // Variable initialisation
1757
        $return = [];
1758
1759
        if (empty($course_id)) {
1760
            $course_id = api_get_course_int_id();
1761
        } else {
1762
            $course_id = intval($course_id);
1763
        }
1764
1765
        if ($all_user_info) {
1766
            $order_clause = api_sort_by_first_name()
1767
                ? ' ORDER BY user.firstname, user.lastname'
1768
                : ' ORDER BY user.lastname, user.firstname';
1769
            $sql = "SELECT DISTINCT
1770
			            answered_user.user as invited_user, 
1771
			            user.firstname, 
1772
			            user.lastname, 
1773
			            user.user_id
1774
                    FROM $table_survey_answer answered_user
1775
                    LEFT JOIN $table_user as user ON answered_user.user = user.user_id
1776
                    WHERE
1777
                        answered_user.c_id = $course_id AND
1778
                        survey_id= '".Database::escape_string($survey_id)."' ".
1779
                $order_clause;
1780
        } else {
1781
            $sql = "SELECT DISTINCT user FROM $table_survey_answer
1782
			        WHERE c_id = $course_id AND survey_id= '".Database::escape_string($survey_id)."'  ";
1783
        }
1784
1785
        $res = Database::query($sql);
1786
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1787
            if ($all_user_info) {
1788
                $userInfo = api_get_user_info($row['user_id']);
1789
                $row['user_info'] = $userInfo;
1790
                $return[] = $row;
1791
            } else {
1792
                $return[] = $row['user'];
1793
            }
1794
        }
1795
1796
        return $return;
1797
    }
1798
1799
    /**
1800
     * @return bool
1801
     */
1802
    public static function survey_generation_hash_available()
1803
    {
1804
        if (extension_loaded('mcrypt')) {
1805
            return true;
1806
        }
1807
1808
        return false;
1809
    }
1810
1811
    /**
1812
     * @param int $survey_id
1813
     * @param int $course_id
1814
     * @param int $session_id
1815
     * @param int $group_id
1816
     *
1817
     * @return string
1818
     */
1819
    public static function generate_survey_hash($survey_id, $course_id, $session_id, $group_id)
1820
    {
1821
        $hash = hash('sha512', api_get_security_key().'_'.$course_id.'_'.$session_id.'_'.$group_id.'_'.$survey_id);
1822
1823
        return $hash;
1824
    }
1825
1826
    /**
1827
     * @param int    $survey_id
1828
     * @param int    $course_id
1829
     * @param int    $session_id
1830
     * @param int    $group_id
1831
     * @param string $hash
1832
     *
1833
     * @return bool
1834
     */
1835
    public static function validate_survey_hash($survey_id, $course_id, $session_id, $group_id, $hash)
1836
    {
1837
        $survey_generated_hash = self::generate_survey_hash($survey_id, $course_id, $session_id, $group_id);
1838
        if ($survey_generated_hash == $hash) {
1839
            return true;
1840
        }
1841
1842
        return false;
1843
    }
1844
1845
    /**
1846
     * @param int $survey_id
1847
     * @param int $course_id
1848
     * @param int $session_id
1849
     * @param int $group_id
1850
     *
1851
     * @return string
1852
     */
1853
    public static function generate_survey_link(
1854
        $survey_id,
1855
        $course_id,
1856
        $session_id,
1857
        $group_id
1858
    ) {
1859
        $code = self::generate_survey_hash(
1860
            $survey_id,
1861
            $course_id,
1862
            $session_id,
1863
            $group_id
1864
        );
1865
1866
        return api_get_path(WEB_CODE_PATH).'survey/link.php?h='.$code.'&i='.$survey_id.'&c='.intval($course_id).'&s='
1867
            .intval($session_id).'&g='.$group_id;
1868
    }
1869
1870
    /**
1871
     * Check if the current user has mandatory surveys no-answered
1872
     * and redirect to fill the first found survey.
1873
     */
1874
    public static function protectByMandatory()
1875
    {
1876
        if (strpos($_SERVER['SCRIPT_NAME'], 'fillsurvey.php') !== false) {
1877
            return;
1878
        }
1879
1880
        $userId = api_get_user_id();
1881
        $courseId = api_get_course_int_id();
1882
        $sessionId = api_get_session_id();
1883
1884
        if (!$userId) {
1885
            return;
1886
        }
1887
1888
        if (!$courseId) {
1889
            return;
1890
        }
1891
1892
        try {
1893
            /** @var CSurveyInvitation $invitation */
1894
            $invitation = Database::getManager()
1895
                ->createQuery("
1896
                    SELECT i FROM ChamiloCourseBundle:CSurveyInvitation i
1897
                    INNER JOIN ChamiloCourseBundle:CSurvey s
1898
                        WITH (s.code = i.surveyCode AND s.cId = i.cId AND s.sessionId = i.sessionId)
1899
                    INNER JOIN ChamiloCoreBundle:ExtraFieldValues efv WITH efv.itemId = s.iid
1900
                    INNER JOIN ChamiloCoreBundle:ExtraField ef WITH efv.field = ef.id
1901
                    WHERE 
1902
                        i.answered = 0 AND 
1903
                        i.cId = :course AND 
1904
                        i.user = :user AND 
1905
                        i.sessionId = :session AND 
1906
                        :now BETWEEN s.availFrom AND s.availTill AND 
1907
                        ef.variable = :variable AND 
1908
                        efv.value = 1 AND 
1909
                        s.surveyType != 3
1910
                    ORDER BY s.availTill ASC
1911
                ")
1912
                ->setMaxResults(1)
1913
                ->setParameters([
1914
                    'course' => $courseId,
1915
                    'user' => $userId,
1916
                    'session' => $sessionId,
1917
                    'now' => new DateTime('UTC', new DateTimeZone('UTC')),
1918
                    'variable' => 'is_mandatory',
1919
                ])
1920
                ->getSingleResult();
1921
        } catch (Exception $e) {
1922
            $invitation = null;
1923
        }
1924
1925
        if (!$invitation) {
1926
            return;
1927
        }
1928
1929
        $urlParams = http_build_query([
1930
            'course' => api_get_course_id(),
1931
            'invitationcode' => $invitation->getInvitationCode(),
1932
        ]);
1933
1934
        Display::addFlash(
1935
            Display::return_message(get_lang('MandatorySurveyNoAnswered'), 'warning')
1936
        );
1937
1938
        header('Location: '.api_get_path(WEB_CODE_PATH).'survey/fillsurvey.php?'.$urlParams.'&'.api_get_cidreq());
1939
        exit;
1940
    }
1941
1942
    /**
1943
     * This function empty surveys (invitations and answers).
1944
     *
1945
     * @param int $surveyId id of the survey to empty
1946
     *
1947
     * @return bool
1948
     */
1949
    public static function emptySurveyFromId($surveyId)
1950
    {
1951
        // Database table definitions
1952
        $surveyInvitationTable = Database:: get_course_table(TABLE_SURVEY_INVITATION);
1953
        $surveyAnswerTable = Database:: get_course_table(TABLE_SURVEY_ANSWER);
1954
        $surveyTable = Database:: get_course_table(TABLE_SURVEY);
1955
        $surveyId = (int) $surveyId;
1956
        $surveyData = self::get_survey($surveyId);
1957
        if (empty($surveyData)) {
1958
            return false;
1959
        }
1960
1961
        $surveyCode = $surveyData['survey_code'];
1962
        $courseId = (int) $surveyData['c_id'];
1963
        $sessionId = (int) $surveyData['session_id'];
1964
1965
        $sql = "DELETE FROM $surveyInvitationTable 
1966
                WHERE session_id = $sessionId AND c_id = $courseId AND survey_code = '$surveyCode' ";
1967
        Database::query($sql);
1968
1969
        $sql = "DELETE FROM $surveyAnswerTable 
1970
               WHERE survey_id = $surveyId AND c_id = $courseId ";
1971
        Database::query($sql);
1972
1973
        $sql = "UPDATE $surveyTable 
1974
                SET invited = 0, answered = 0 
1975
                WHERE survey_id = $surveyId AND c_id = $courseId AND session_id = $sessionId ";
1976
        Database::query($sql);
1977
1978
        return true;
1979
    }
1980
1981
    /**
1982
     * This function copy survey specifying course id and session id where will be copied.
1983
     *
1984
     * @param int $surveyId
1985
     * @param int $targetCourseId  target course id
1986
     * @param int $targetSessionId target session id
1987
     *
1988
     * @return bool|int when fails or return the new survey id
1989
     */
1990
    public static function copySurveySession($surveyId, $targetCourseId, $targetSessionId)
1991
    {
1992
        // Database table definitions
1993
        $surveyTable = Database::get_course_table(TABLE_SURVEY);
1994
        $surveyQuestionGroupTable = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
1995
        $surveyQuestionTable = Database::get_course_table(TABLE_SURVEY_QUESTION);
1996
        $surveyOptionsTable = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1997
        $surveyId = (int) $surveyId;
1998
        $targetCourseId = (int) $targetCourseId;
1999
        $targetSessionId = (int) $targetSessionId;
2000
2001
        $surveyData = self::get_survey($surveyId, 0, '', true);
2002
        if (empty($surveyData) || empty($targetCourseId)) {
2003
            return false;
2004
        }
2005
2006
        $originalCourseId = $surveyData['c_id'];
2007
        $originalSessionId = $surveyData['session_id'];
2008
2009
        $surveyData['code'] = self::generate_unique_code($surveyData['code']);
2010
        $surveyData['c_id'] = $targetCourseId;
2011
        $surveyData['session_id'] = $targetSessionId;
2012
        // Add a "Copy" suffix if copied inside the same course
2013
        if ($targetCourseId == $originalCourseId) {
2014
            $surveyData['title'] = $surveyData['title'].' '.get_lang('Copy');
2015
        }
2016
        unset($surveyData['iid']);
2017
        unset($surveyData['id']);
2018
2019
        $newSurveyId = Database::insert($surveyTable, $surveyData);
2020
2021
        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...
2022
            $sql = "UPDATE $surveyTable SET survey_id = $newSurveyId 
2023
                    WHERE iid = $newSurveyId";
2024
            Database::query($sql);
2025
2026
            $sql = "SELECT * FROM $surveyQuestionGroupTable 
2027
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId ";
2028
            $res = Database::query($sql);
2029
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2030
                $params = [
2031
                    'c_id' => $targetCourseId,
2032
                    'name' => $row['name'],
2033
                    'description' => $row['description'],
2034
                    'survey_id' => $newSurveyId,
2035
                ];
2036
                $insertId = Database::insert($surveyQuestionGroupTable, $params);
2037
                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...
2038
                    $sql = "UPDATE $surveyQuestionGroupTable SET id = iid WHERE iid = $insertId";
2039
                    Database::query($sql);
2040
                    $group_id[$row['id']] = $insertId;
2041
                }
2042
            }
2043
2044
            // Get questions
2045
            $sql = "SELECT * FROM $surveyQuestionTable 
2046
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId";
2047
            $res = Database::query($sql);
2048
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2049
                $params = [
2050
                    'c_id' => $targetCourseId,
2051
                    'survey_id' => $newSurveyId,
2052
                    'survey_question' => $row['survey_question'],
2053
                    'survey_question_comment' => $row['survey_question_comment'],
2054
                    'type' => $row['type'],
2055
                    'display' => $row['display'],
2056
                    'sort' => $row['sort'],
2057
                    'shared_question_id' => $row['shared_question_id'],
2058
                    'max_value' => $row['max_value'],
2059
                    'survey_group_pri' => $row['survey_group_pri'],
2060
                    'survey_group_sec1' => $row['survey_group_sec1'],
2061
                    'survey_group_sec2' => $row['survey_group_sec2'],
2062
                ];
2063
                $insertId = Database::insert($surveyQuestionTable, $params);
2064
                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...
2065
                    $sql = "UPDATE $surveyQuestionTable 
2066
                            SET question_id = iid
2067
                            WHERE iid = $insertId";
2068
                    Database::query($sql);
2069
2070
                    $question_id[$row['question_id']] = $insertId;
2071
                }
2072
            }
2073
2074
            // Get questions options
2075
            $sql = "SELECT * FROM $surveyOptionsTable 
2076
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId";
2077
2078
            $res = Database::query($sql);
2079
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2080
                $params = [
2081
                    'c_id' => $targetCourseId,
2082
                    '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...
2083
                    'survey_id' => $newSurveyId,
2084
                    'option_text' => $row['option_text'],
2085
                    'sort' => $row['sort'],
2086
                    'value' => $row['value'],
2087
                ];
2088
                $insertId = Database::insert($surveyOptionsTable, $params);
2089
                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...
2090
                    $sql = "UPDATE $surveyOptionsTable SET question_option_id = $insertId WHERE iid = $insertId";
2091
                    Database::query($sql);
2092
                }
2093
            }
2094
2095
            return $newSurveyId;
2096
        }
2097
2098
        return false;
2099
    }
2100
2101
    public static function removeMultiplicateQuestions($surveyData)
2102
    {
2103
        if (empty($surveyData)) {
2104
            return false;
2105
        }
2106
        $surveyId = $surveyData['survey_id'];
2107
        $courseId = $surveyData['c_id'];
2108
2109
        if (empty($surveyId) || empty($courseId)) {
2110
            return false;
2111
        }
2112
2113
        $questions = self::get_questions($surveyId);
2114
        foreach ($questions as $question) {
2115
            // Questions marked with "geneated" were created using the "multiplicate" feature.
2116
            if ($question['survey_question_comment'] === 'generated') {
2117
                self::delete_survey_question($surveyId, $question['question_id']);
2118
            }
2119
        }
2120
    }
2121
2122
    /**
2123
     * @param array $surveyData
2124
     *
2125
     * @return bool
2126
     */
2127
    public static function multiplicateQuestions($surveyData)
2128
    {
2129
        if (empty($surveyData)) {
2130
            return false;
2131
        }
2132
        $surveyId = $surveyData['survey_id'];
2133
        $courseId = $surveyData['c_id'];
2134
2135
        if (empty($surveyId) || empty($courseId)) {
2136
            return false;
2137
        }
2138
2139
        $questions = self::get_questions($surveyId);
2140
2141
        $obj = new UserGroup();
2142
2143
        $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...
2144
        $classList = $obj->getUserGroupInCourse($options);
2145
2146
        $classTag = '{{class_name}}';
2147
        $studentTag = '{{student_full_name}}';
2148
        $classCounter = 0;
2149
        foreach ($classList as $class) {
2150
            $className = $class['name'];
2151
            foreach ($questions as $question) {
2152
                $users = $obj->get_users_by_usergroup($class['id']);
2153
                if (empty($users)) {
2154
                    continue;
2155
                }
2156
2157
                $text = $question['question'];
2158
                if (strpos($text, $classTag) !== false) {
2159
                    $replacedText = str_replace($classTag, $className, $text);
2160
                    $values = [
2161
                        'c_id' => $courseId,
2162
                        'question_comment' => 'generated',
2163
                        'type' => $question['type'],
2164
                        'display' => $question['horizontalvertical'],
2165
                        'question' => $replacedText,
2166
                        'survey_id' => $surveyId,
2167
                        'question_id' => 0,
2168
                        'shared_question_id' => 0,
2169
                    ];
2170
                    self::save_question($surveyData, $values);
2171
                    $classCounter++;
2172
                    continue;
2173
                }
2174
2175
                foreach ($users as $userId) {
2176
                    $userInfo = api_get_user_info($userId);
2177
2178
                    if (strpos($text, $studentTag) !== false) {
2179
                        $replacedText = str_replace($studentTag, $userInfo['complete_name'], $text);
2180
                        $values = [
2181
                            'c_id' => $courseId,
2182
                            'question_comment' => 'generated',
2183
                            'type' => $question['type'],
2184
                            'display' => $question['horizontalvertical'],
2185
                            'maximum_score' => $question['maximum_score'],
2186
                            'question' => $replacedText,
2187
                            'survey_id' => $surveyId,
2188
                            'question_id' => 0,
2189
                            'shared_question_id' => 0,
2190
                        ];
2191
2192
                        $answers = [];
2193
                        if (!empty($question['answers'])) {
2194
                            foreach ($question['answers'] as $answer) {
2195
                                $replacedText = str_replace($studentTag, $userInfo['complete_name'], $answer);
2196
                                $answers[] = $replacedText;
2197
                            }
2198
                        }
2199
                        $values['answers'] = $answers;
2200
                        self::save_question($surveyData, $values);
2201
                    }
2202
                }
2203
2204
                if ($classCounter < count($classList)) {
2205
                    // Add end page
2206
                    $values = [
2207
                        'c_id' => $courseId,
2208
                        'question_comment' => 'generated',
2209
                        'type' => 'pagebreak',
2210
                        'display' => 'horizontal',
2211
                        'question' => get_lang('QuestionForNextClass'),
2212
                        'survey_id' => $surveyId,
2213
                        'question_id' => 0,
2214
                        'shared_question_id' => 0,
2215
                    ];
2216
                    self::save_question($surveyData, $values);
2217
                }
2218
            }
2219
        }
2220
    }
2221
2222
    /**
2223
     * @param array $survey
2224
     *
2225
     * @return int
2226
     */
2227
    public static function getCountPages($survey)
2228
    {
2229
        if (empty($survey) || !isset($survey['iid'])) {
2230
            return 0;
2231
        }
2232
2233
        $courseId = $survey['c_id'];
2234
        $surveyId = $survey['survey_id'];
2235
2236
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
2237
2238
        // One question per page
2239
        $sql = "SELECT * FROM $table
2240
                WHERE
2241
                    survey_question NOT LIKE '%{{%' AND
2242
                    type = 'pagebreak' AND
2243
                    c_id = $courseId AND
2244
                    survey_id = '".$surveyId."'";
2245
        $result = Database::query($sql);
2246
        $numberPageBreaks = Database::num_rows($result);
2247
2248
        // One question per page
2249
        $sql = "SELECT * FROM $table
2250
                    WHERE
2251
                        survey_question NOT LIKE '%{{%' AND
2252
                        type != 'pagebreak' AND
2253
                        c_id = $courseId AND
2254
                        survey_id = '".$surveyId."'";
2255
        $result = Database::query($sql);
2256
        $countOfQuestions = Database::num_rows($result);
2257
2258
        $count = 1;
2259
        if (!empty($numberPageBreaks) && !empty($countOfQuestions)) {
2260
            // One question per page
2261
            $count = $countOfQuestions;
2262
        }
2263
2264
        if ($survey['one_question_per_page'] == 1) {
2265
            $count = 1;
2266
            if (!empty($countOfQuestions)) {
2267
                $count = $countOfQuestions;
2268
            }
2269
        }
2270
2271
        return $count;
2272
    }
2273
2274
    /**
2275
     * Check whether this survey has ended. If so, display message and exit rhis script.
2276
     *
2277
     * @param array $surveyData Survey data
2278
     */
2279
    public static function checkTimeAvailability($surveyData)
2280
    {
2281
        if (empty($surveyData)) {
2282
            api_not_allowed(true);
2283
        }
2284
2285
        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
2286
        $utcZone = new DateTimeZone('UTC');
2287
        $startDate = new DateTime($surveyData['start_date'], $utcZone);
2288
        $endDate = new DateTime($surveyData['end_date'], $utcZone);
2289
        $currentDate = new DateTime('now', $utcZone);
2290
        if (!$allowSurveyAvailabilityDatetime) {
2291
            $currentDate->modify('today');
2292
        }
2293
        if ($currentDate < $startDate) {
2294
            api_not_allowed(
2295
                true,
2296
                Display:: return_message(
2297
                    get_lang('SurveyNotAvailableYet'),
2298
                    'warning',
2299
                    false
2300
                )
2301
            );
2302
        }
2303
2304
        if ($currentDate > $endDate) {
2305
            api_not_allowed(
2306
                true,
2307
                Display:: return_message(
2308
                    get_lang('SurveyNotAvailableAnymore'),
2309
                    'warning',
2310
                    false
2311
                )
2312
            );
2313
        }
2314
    }
2315
}
2316