Passed
Push — master ( 190bd7...86c511 )
by Julito
09:39
created

SurveyManager::get_surveys()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 2
dl 0
loc 20
rs 9.8666
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
343
            $from = api_get_utc_datetime($values['start_date'].'00:00:00', true, true);
344
            $until = api_get_utc_datetime($values['end_date'].'23:59:59', true, true);
345
            if ($allowSurveyAvailabilityDatetime) {
346
                $from = api_get_utc_datetime($values['start_date'].':00', true, true);
347
                $until = api_get_utc_datetime($values['end_date'].':59', true, true);
348
            }
349
350
            $survey
351
                ->setCId($course_id)
352
                ->setCode(self::generateSurveyCode($values['survey_code']))
353
                ->setTitle($values['survey_title'])
354
                ->setSubtitle($values['survey_title'])
355
                ->setAuthor($_user['user_id'])
356
                ->setLang($values['survey_language'])
357
                ->setAvailFrom($from)
358
                ->setAvailTill($until)
359
                ->setIsShared($shared_survey_id)
360
                ->setTemplate('template')
361
                ->setIntro($values['survey_introduction'])
362
                ->setSurveyThanks($values['survey_thanks'])
363
                ->setAnonymous($values['anonymous'])
364
                ->setSessionId(api_get_session_id())
365
                ->setVisibleResults($values['visible_results'])
366
            ;
367
368
            $em = Database::getManager();
369
            $em->persist($survey);
370
            $em->flush();
371
372
            $survey_id = $survey->getIid();
373
            if ($survey_id > 0) {
374
                $sql = "UPDATE $table_survey SET survey_id = $survey_id
375
                        WHERE iid = $survey_id";
376
                Database::query($sql);
377
378
                // Insert into item_property
379
                api_item_property_update(
380
                    api_get_course_info(),
381
                    TOOL_SURVEY,
382
                    $survey_id,
383
                    'SurveyAdded',
384
                    api_get_user_id()
385
                );
386
            }
387
388
            if ($values['survey_type'] == 1 && !empty($values['parent_id'])) {
389
                self::copy_survey($values['parent_id'], $survey_id);
390
            }
391
392
            Display::addFlash(
393
                Display::return_message(
394
                    get_lang('SurveyCreatedSuccesfully'),
395
                    'success'
396
                )
397
            );
398
            $return['id'] = $survey_id;
399
        } else {
400
            // Check whether the code doesn't soon exists in this language
401
            $sql = 'SELECT 1 FROM '.$table_survey.'
402
			        WHERE
403
			            c_id = '.$course_id.' AND
404
			            code = "'.Database::escape_string($values['survey_code']).'" AND
405
			            lang = "'.Database::escape_string($values['survey_language']).'" AND
406
			            survey_id !='.intval($values['survey_id']);
407
            $rs = Database::query($sql);
408
            if (Database::num_rows($rs) > 0) {
409
                Display::addFlash(
410
                    Display::return_message(
411
                        get_lang('ThisSurveyCodeSoonExistsInThisLanguage'),
412
                        'error'
413
                    )
414
                );
415
                $return['type'] = 'error';
416
                $return['id'] = isset($values['survey_id']) ? $values['survey_id'] : 0;
417
418
                return $return;
419
            }
420
421
            if (!isset($values['anonymous'])
422
                || (isset($values['anonymous']) && $values['anonymous'] == '')
423
            ) {
424
                $values['anonymous'] = 0;
425
            }
426
427
            $values['shuffle'] = isset($values['shuffle']) ? $values['shuffle'] : null;
428
            $values['one_question_per_page'] = isset($values['one_question_per_page']) ? $values['one_question_per_page'] : null;
429
            $values['show_form_profile'] = isset($values['show_form_profile']) ? $values['show_form_profile'] : null;
430
431
            $extraParams = [];
432
            $extraParams['shuffle'] = $values['shuffle'];
433
            $extraParams['one_question_per_page'] = $values['one_question_per_page'];
434
            $extraParams['shuffle'] = $values['shuffle'];
435
436
            if ($values['anonymous'] == 0) {
437
                $extraParams['show_form_profile'] = $values['show_form_profile'];
438
                if ($values['show_form_profile'] == 1) {
439
                    $fields = explode(',', $values['input_name_list']);
440
                    $field_values = '';
441
                    foreach ($fields as &$field) {
442
                        if ($field != '') {
443
                            if (!isset($values[$field]) ||
444
                                (isset($values[$field]) && $values[$field] == '')
445
                            ) {
446
                                $values[$field] = 0;
447
                            }
448
                            $field_values .= $field.':'.$values[$field].'@';
449
                        }
450
                    }
451
                    $extraParams['form_fields'] = $field_values;
452
                } else {
453
                    $extraParams['form_fields'] = '';
454
                }
455
            } else {
456
                $extraParams['show_form_profile'] = 0;
457
                $extraParams['form_fields'] = '';
458
            }
459
460
            $params = [
461
                'title' => $values['survey_title'],
462
                'subtitle' => $values['survey_subtitle'],
463
                'author' => $_user['user_id'],
464
                'lang' => $values['survey_language'],
465
                'avail_from' => $allowSurveyAvailabilityDatetime
466
                    ? api_get_utc_datetime($values['start_date'].':00')
467
                    : $values['start_date'],
468
                'avail_till' => $allowSurveyAvailabilityDatetime
469
                    ? api_get_utc_datetime($values['end_date'].':59')
470
                    : $values['end_date'],
471
                'is_shared' => $shared_survey_id,
472
                'template' => 'template',
473
                'intro' => $values['survey_introduction'],
474
                'surveythanks' => $values['survey_thanks'],
475
                'anonymous' => $values['anonymous'],
476
                'session_id' => api_get_session_id(),
477
                'visible_results' => $values['visible_results'],
478
            ];
479
480
            $params = array_merge($params, $extraParams);
481
            Database::update(
482
                $table_survey,
483
                $params,
484
                [
485
                    'c_id = ? AND survey_id = ?' => [
486
                        $course_id,
487
                        $values['survey_id'],
488
                    ],
489
                ]
490
            );
491
492
            // Update into item_property (update)
493
            api_item_property_update(
494
                api_get_course_info(),
495
                TOOL_SURVEY,
496
                $values['survey_id'],
497
                'SurveyUpdated',
498
                api_get_user_id()
499
            );
500
501
            Display::addFlash(
502
                Display::return_message(
503
                    get_lang('SurveyUpdatedSuccesfully'),
504
                    'confirmation'
505
                )
506
            );
507
508
            $return['id'] = $values['survey_id'];
509
        }
510
511
        $survey_id = intval($return['id']);
512
513
        // Gradebook
514
        $gradebook_option = false;
515
        if (isset($values['survey_qualify_gradebook'])) {
516
            $gradebook_option = $values['survey_qualify_gradebook'] > 0;
517
        }
518
519
        $gradebook_link_type = 8;
520
        $link_info = GradebookUtils::isResourceInCourseGradebook(
521
            $courseCode,
522
            $gradebook_link_type,
523
            $survey_id,
524
            $session_id
525
        );
526
527
        $gradebook_link_id = isset($link_info['id']) ? $link_info['id'] : false;
528
529
        if ($gradebook_option) {
530
            if ($survey_id > 0) {
531
                $title_gradebook = ''; // Not needed here.
532
                $description_gradebook = ''; // Not needed here.
533
                $survey_weight = floatval($_POST['survey_weight']);
534
                $max_score = 1;
535
536
                if (!$gradebook_link_id) {
537
                    GradebookUtils::add_resource_to_course_gradebook(
538
                        $values['category_id'],
539
                        $courseCode,
540
                        $gradebook_link_type,
541
                        $survey_id,
542
                        $title_gradebook,
543
                        $survey_weight,
544
                        $max_score,
545
                        $description_gradebook,
546
                        1,
547
                        $session_id
548
                    );
549
                } else {
550
                    GradebookUtils::updateResourceFromCourseGradebook(
551
                        $gradebook_link_id,
552
                        $courseCode,
553
                        $survey_weight
554
                    );
555
                }
556
            }
557
        } else {
558
            // Delete everything of the gradebook for this $linkId
559
            GradebookUtils::remove_resource_from_course_gradebook($gradebook_link_id);
560
        }
561
562
        return $return;
563
    }
564
565
    /**
566
     * This function stores a shared survey in the central database.
567
     *
568
     * @param array $values
569
     *
570
     * @return array $return the type of return message that has to be displayed and the message in it
571
     *
572
     * @author Patrick Cool <[email protected]>, Ghent University
573
     *
574
     * @version February 2007
575
     */
576
    public function store_shared_survey($values)
577
    {
578
        $_user = api_get_user_info();
579
        $_course = api_get_course_info();
580
581
        // Table definitions
582
        $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
583
584
        if (!$values['survey_id'] ||
585
            !is_numeric($values['survey_id']) ||
586
            $values['survey_share']['survey_share'] == 'true'
587
        ) {
588
            $sql = "INSERT INTO $table_survey (code, title, subtitle, author, lang, template, intro, surveythanks, creation_date, course_code) VALUES (
589
                    '".Database::escape_string($values['survey_code'])."',
590
                    '".Database::escape_string($values['survey_title'])."',
591
                    '".Database::escape_string($values['survey_subtitle'])."',
592
                    '".intval($_user['user_id'])."',
593
                    '".Database::escape_string($values['survey_language'])."',
594
                    '".Database::escape_string('template')."',
595
                    '".Database::escape_string($values['survey_introduction'])."',
596
                    '".Database::escape_string($values['survey_thanks'])."',
597
                    '".api_get_utc_datetime()."',
598
                    '".$_course['id']."')";
599
            Database::query($sql);
600
            $return = Database::insert_id();
601
602
            $sql = "UPDATE $table_survey SET survey_id = $return WHERE iid = $return";
603
            Database::query($sql);
604
        } else {
605
            $sql = "UPDATE $table_survey SET
606
                        code 			= '".Database::escape_string($values['survey_code'])."',
607
                        title 			= '".Database::escape_string($values['survey_title'])."',
608
                        subtitle 		= '".Database::escape_string($values['survey_subtitle'])."',
609
                        author 			= '".intval($_user['user_id'])."',
610
                        lang 			= '".Database::escape_string($values['survey_language'])."',
611
                        template 		= '".Database::escape_string('template')."',
612
                        intro			= '".Database::escape_string($values['survey_introduction'])."',
613
                        surveythanks	= '".Database::escape_string($values['survey_thanks'])."'
614
					WHERE survey_id = '".Database::escape_string($values['survey_share']['survey_share'])."'";
615
            Database::query($sql);
616
            $return = $values['survey_share']['survey_share'];
617
        }
618
619
        return $return;
620
    }
621
622
    /**
623
     * This function deletes a survey (and also all the question in that survey.
624
     *
625
     * @param int  $survey_id id of the survey that has to be deleted
626
     * @param bool $shared
627
     * @param int  $course_id
628
     *
629
     * @return true
630
     *
631
     * @author Patrick Cool <[email protected]>, Ghent University
632
     *
633
     * @version January 2007
634
     */
635
    public static function delete_survey($survey_id, $shared = false, $course_id = 0)
636
    {
637
        // Database table definitions
638
        if (empty($course_id)) {
639
            $course_id = api_get_course_int_id();
640
        }
641
642
        $survey_id = intval($survey_id);
643
644
        if (empty($survey_id)) {
645
            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...
646
        }
647
648
        $course_info = api_get_course_info_by_id($course_id);
649
        $course_id = $course_info['real_id'];
650
651
        $table_survey = Database::get_course_table(TABLE_SURVEY);
652
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
653
654
        if ($shared) {
655
            $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
656
            // Deleting the survey
657
            $sql = "DELETE FROM $table_survey
658
                    WHERE survey_id='".$survey_id."'";
659
            Database::query($sql);
660
        } else {
661
            $sql = "DELETE FROM $table_survey
662
                    WHERE c_id = $course_id AND survey_id='".$survey_id."'";
663
            Database::query($sql);
664
        }
665
666
        // Deleting groups of this survey
667
        $sql = "DELETE FROM $table_survey_question_group
668
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
669
        Database::query($sql);
670
671
        // Deleting the questions of the survey
672
        self::delete_all_survey_questions($survey_id, $shared);
673
674
        // Update into item_property (delete)
675
        api_item_property_update(
676
            $course_info,
677
            TOOL_SURVEY,
678
            $survey_id,
679
            'SurveyDeleted',
680
            api_get_user_id()
681
        );
682
683
        Skill::deleteSkillsFromItem($survey_id, ITEM_TYPE_SURVEY);
684
685
        return true;
686
    }
687
688
    /**
689
     * @param int $survey_id
690
     * @param int $new_survey_id
691
     * @param int $targetCourseId
692
     *
693
     * @return bool
694
     */
695
    public static function copy_survey(
696
        $survey_id,
697
        $new_survey_id = null,
698
        $targetCourseId = null
699
    ) {
700
        $course_id = api_get_course_int_id();
701
        if (!$targetCourseId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $targetCourseId of type integer|null is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

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

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

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

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

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

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