Completed
Push — master ( 1a5e2c...34133a )
by Julito
08:10
created

SurveyManager::save_question_options()   F

Complexity

Conditions 23
Paths 128

Size

Total Lines 115
Code Lines 80

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 80
c 0
b 0
f 0
nc 128
nop 3
dl 0
loc 115
rs 3.9333

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

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

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1149
                        if (strlen($form_content['answers'][$i]) < 1) {
1150
                            $empty_answer = true;
1151
                            break;
1152
                        }
1153
                    }
1154
                }
1155
            }
1156
1157
            if ('score' == $form_content['type']) {
1158
                if (strlen($form_content['maximum_score']) < 1) {
1159
                    $empty_answer = true;
1160
                }
1161
            }
1162
1163
            $course_id = api_get_course_int_id();
1164
1165
            if (!$empty_answer) {
1166
                // Table definitions
1167
                $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1168
                $surveyId = (int) $form_content['survey_id'];
1169
1170
                // Getting all the information of the survey
1171
                $survey_data = self::get_survey($surveyId);
1172
1173
                // Storing the question in the shared database
1174
                if (is_numeric($survey_data['survey_share']) && $survey_data['survey_share'] != 0) {
1175
                    $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

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

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

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

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

Loading history...
1540
    {
1541
        // Table definitions
1542
        $table_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1543
        $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1544
1545
        // First we have to get the shared_question_id
1546
        $question_data = self::get_question($question_id);
1547
1548
        // Deleting the survey questions
1549
        $sql = "DELETE FROM $table_survey_question
1550
		        WHERE question_id='".intval($question_data['shared_question_id'])."'";
1551
        Database::query($sql);
1552
1553
        // Deleting the options of the question of the survey question
1554
        $sql = "DELETE FROM $table_survey_question_option
1555
		        WHERE question_id='".intval($question_data['shared_question_id'])."'";
1556
        Database::query($sql);
1557
    }
1558
1559
    /**
1560
     * This function stores the options of the questions in the table.
1561
     *
1562
     * @param array $form_content
1563
     *
1564
     * @author Patrick Cool <[email protected]>, Ghent University
1565
     *
1566
     * @version January 2007
1567
     *
1568
     * @todo writing the update statement when editing a question
1569
     */
1570
    public static function save_question_options($form_content, $survey_data, $dataFromDatabase = [])
1571
    {
1572
        $course_id = api_get_course_int_id();
1573
        $type = $form_content['type'];
1574
        // A percentage question type has options 1 -> 100
1575
        if ('percentage' === $form_content['type']) {
1576
            for ($i = 1; $i < 101; $i++) {
1577
                $form_content['answers'][] = $i;
1578
            }
1579
        }
1580
1581
        if (is_numeric($survey_data['survey_share']) && 0 != $survey_data['survey_share']) {
1582
            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

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