Completed
Push — master ( a638fe...506c79 )
by Julito
08:40
created

SurveyManager::hasDependency()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 34
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
701
            $targetCourseId = $course_id;
702
        }
703
704
        // Database table definitions
705
        $table_survey = Database::get_course_table(TABLE_SURVEY);
706
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
707
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
708
        $table_survey_options = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
709
        $survey_id = (int) $survey_id;
710
711
        // Get groups
712
        $survey_data = self::get_survey($survey_id, 0, null, true);
713
        if (empty($survey_data)) {
714
            return true;
715
        }
716
717
        if (empty($new_survey_id)) {
718
            $params = $survey_data;
719
            $params['code'] = self::generate_unique_code($params['code']);
720
            $params['c_id'] = $targetCourseId;
721
            unset($params['survey_id']);
722
            $params['session_id'] = api_get_session_id();
723
            $params['title'] = $params['title'].' '.get_lang('Copy');
724
            unset($params['iid']);
725
            $params['invited'] = 0;
726
            $params['answered'] = 0;
727
            $new_survey_id = Database::insert($table_survey, $params);
728
729
            if ($new_survey_id) {
730
                $sql = "UPDATE $table_survey SET survey_id = $new_survey_id
731
                        WHERE iid = $new_survey_id";
732
                Database::query($sql);
733
734
                // Insert into item_property
735
                api_item_property_update(
736
                    api_get_course_info(),
737
                    TOOL_SURVEY,
738
                    $new_survey_id,
739
                    'SurveyAdded',
740
                    api_get_user_id()
741
                );
742
            }
743
        } else {
744
            $new_survey_id = (int) $new_survey_id;
745
        }
746
747
        $sql = "SELECT * FROM $table_survey_question_group
748
                WHERE c_id = $course_id AND survey_id = $survey_id";
749
        $res = Database::query($sql);
750
        while ($row = Database::fetch_array($res, 'ASSOC')) {
751
            $params = [
752
                'c_id' => $targetCourseId,
753
                'name' => $row['name'],
754
                'description' => $row['description'],
755
                'survey_id' => $new_survey_id,
756
            ];
757
            $insertId = Database::insert($table_survey_question_group, $params);
758
759
            $sql = "UPDATE $table_survey_question_group SET id = iid
760
                    WHERE iid = $insertId";
761
            Database::query($sql);
762
763
            $group_id[$row['id']] = $insertId;
764
        }
765
766
        // Get questions
767
        $sql = "SELECT * FROM $table_survey_question
768
                WHERE c_id = $course_id AND survey_id = $survey_id";
769
        $res = Database::query($sql);
770
        while ($row = Database::fetch_array($res, 'ASSOC')) {
771
            $params = [
772
                'c_id' => $targetCourseId,
773
                'survey_id' => $new_survey_id,
774
                'survey_question' => $row['survey_question'],
775
                'survey_question_comment' => $row['survey_question_comment'],
776
                'type' => $row['type'],
777
                'display' => $row['display'],
778
                'sort' => $row['sort'],
779
                'shared_question_id' => $row['shared_question_id'],
780
                'max_value' => $row['max_value'],
781
                'survey_group_pri' => $row['survey_group_pri'],
782
                'survey_group_sec1' => $row['survey_group_sec1'],
783
                'survey_group_sec2' => $row['survey_group_sec2'],
784
            ];
785
786
            if (api_get_configuration_value('allow_required_survey_questions')) {
787
                if (isset($row['is_required'])) {
788
                    $params['is_required'] = $row['is_required'];
789
                }
790
            }
791
792
            $insertId = Database::insert($table_survey_question, $params);
793
            if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
794
                $sql = "UPDATE $table_survey_question SET question_id = iid WHERE iid = $insertId";
795
                Database::query($sql);
796
                $question_id[$row['question_id']] = $insertId;
797
            }
798
        }
799
800
        // Get questions options
801
        $sql = "SELECT * FROM $table_survey_options
802
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
803
804
        $res = Database::query($sql);
805
        while ($row = Database::fetch_array($res, 'ASSOC')) {
806
            $params = [
807
                'c_id' => $targetCourseId,
808
                'question_id' => $question_id[$row['question_id']],
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $question_id does not seem to be defined for all execution paths leading up to this point.
Loading history...
809
                'survey_id' => $new_survey_id,
810
                'option_text' => $row['option_text'],
811
                'sort' => $row['sort'],
812
                'value' => $row['value'],
813
            ];
814
            $insertId = Database::insert($table_survey_options, $params);
815
            if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
816
                $sql = "UPDATE $table_survey_options SET question_option_id = $insertId
817
                        WHERE iid = $insertId";
818
                Database::query($sql);
819
            }
820
        }
821
822
        return $new_survey_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $new_survey_id also could return the type integer which is incompatible with the documented return type boolean.
Loading history...
823
    }
824
825
    /**
826
     * This function duplicates a survey (and also all the question in that survey.
827
     *
828
     * @param int $surveyId id of the survey that has to be duplicated
829
     * @param int $courseId id of the course which survey has to be duplicated
830
     *
831
     * @return true
832
     *
833
     * @author Eric Marguin <[email protected]>, Elixir Interactive
834
     *
835
     * @version October 2007
836
     */
837
    public static function empty_survey($surveyId, $courseId = 0)
838
    {
839
        // Database table definitions
840
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
841
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
842
        $table_survey = Database::get_course_table(TABLE_SURVEY);
843
844
        $courseId = (int) $courseId;
845
        $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
846
        $surveyId = (int) $surveyId;
847
848
        $datas = self::get_survey($surveyId);
849
        $session_where = '';
850
        if (0 != api_get_session_id()) {
851
            $session_where = ' AND session_id = "'.api_get_session_id().'" ';
852
        }
853
854
        $sql = 'DELETE FROM '.$table_survey_invitation.'
855
		        WHERE
856
		            c_id = '.$courseId.' AND
857
		            survey_code = "'.Database::escape_string($datas['code']).'" '.$session_where.' ';
858
        Database::query($sql);
859
860
        $sql = 'DELETE FROM '.$table_survey_answer.'
861
		        WHERE c_id = '.$courseId.' AND survey_id='.$surveyId;
862
        Database::query($sql);
863
864
        $sql = 'UPDATE '.$table_survey.' SET invited=0, answered=0
865
		        WHERE c_id = '.$courseId.' AND survey_id='.$surveyId;
866
        Database::query($sql);
867
868
        return true;
869
    }
870
871
    /**
872
     * This function recalculates the number of people who have taken the survey (=filled at least one question).
873
     *
874
     * @param array  $survey_data
875
     * @param array  $user
876
     * @param string $survey_code
877
     *
878
     * @return bool
879
     *
880
     * @author Patrick Cool <[email protected]>, Ghent University
881
     *
882
     * @version February 2007
883
     */
884
    public static function update_survey_answered($survey_data, $user, $survey_code)
885
    {
886
        if (empty($survey_data)) {
887
            return false;
888
        }
889
890
        // Database table definitions
891
        $table_survey = Database::get_course_table(TABLE_SURVEY);
892
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
893
894
        $survey_id = (int) $survey_data['survey_id'];
895
        $course_id = (int) $survey_data['c_id'];
896
        $session_id = $survey_data['session_id'];
897
898
        // Getting a list with all the people who have filled the survey
899
        /*$people_filled = self::get_people_who_filled_survey($survey_id, false, $course_id);
900
        $number = count($people_filled);*/
901
902
        // Storing this value in the survey table
903
        $sql = "UPDATE $table_survey
904
		        SET answered = answered + 1
905
		        WHERE
906
                    c_id = $course_id AND
907
		            survey_id = ".$survey_id;
908
        Database::query($sql);
909
910
        $allow = api_get_configuration_value('survey_answered_at_field');
911
        // Requires DB change:
912
        // ALTER TABLE c_survey_invitation ADD answered_at DATETIME DEFAULT NULL;
913
        $answeredAt = '';
914
        if ($allow) {
915
            $answeredAt = "answered_at = '".api_get_utc_datetime()."',";
916
        }
917
918
        // Storing that the user has finished the survey.
919
        $sql = "UPDATE $table_survey_invitation
920
                SET $answeredAt answered = 1
921
                WHERE
922
                    c_id = $course_id AND
923
                    session_id = $session_id AND
924
                    user ='".Database::escape_string($user)."' AND
925
                    survey_code='".Database::escape_string($survey_code)."'";
926
        Database::query($sql);
927
    }
928
929
    /**
930
     * This function return the "icon" of the question type.
931
     *
932
     * @param string $type
933
     *
934
     * @author Patrick Cool <[email protected]>, Ghent University
935
     *
936
     * @version February 2007
937
     */
938
    public static function icon_question($type)
939
    {
940
        // the possible question types
941
        $possible_types = [
942
            'personality',
943
            'yesno',
944
            'multiplechoice',
945
            'multipleresponse',
946
            'open',
947
            'dropdown',
948
            'comment',
949
            'pagebreak',
950
            'percentage',
951
            'score',
952
        ];
953
954
        // the images array
955
        $icon_question = [
956
            'yesno' => 'yesno.png',
957
            'personality' => 'yesno.png',
958
            'multiplechoice' => 'mcua.png',
959
            'multipleresponse' => 'mcma.png',
960
            'open' => 'open_answer.png',
961
            'dropdown' => 'dropdown.png',
962
            'percentage' => 'percentagequestion.png',
963
            'score' => 'scorequestion.png',
964
            'comment' => 'commentquestion.png',
965
            'pagebreak' => 'page_end.png',
966
        ];
967
968
        if (in_array($type, $possible_types)) {
969
            return $icon_question[$type];
970
        }
971
972
        return false;
973
    }
974
975
    /**
976
     * This function retrieves all the information of a question.
977
     *
978
     * @param int  $question_id the id of the question
979
     * @param bool $shared
980
     *
981
     * @return array
982
     *
983
     * @author Patrick Cool <[email protected]>, Ghent University
984
     *
985
     * @version January 2007
986
     *
987
     * @todo one sql call should do the trick
988
     */
989
    public static function get_question($question_id, $shared = false)
990
    {
991
        // Table definitions
992
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
993
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
994
        $course_id = api_get_course_int_id();
995
        $question_id = (int) $question_id;
996
997
        if (empty($question_id)) {
998
            return [];
999
        }
1000
1001
        $sql = "SELECT * FROM $tbl_survey_question
1002
                WHERE c_id = $course_id AND question_id = $question_id
1003
                ORDER BY `sort` ";
1004
1005
        $sqlOption = "  SELECT * FROM $table_survey_question_option
1006
                        WHERE c_id = $course_id AND question_id='".$question_id."'
1007
                        ORDER BY `sort` ";
1008
1009
        if ($shared) {
1010
            $tbl_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
1011
            $table_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
1012
1013
            $sql = "SELECT * FROM $tbl_survey_question
1014
                    WHERE question_id = $question_id
1015
                    ORDER BY `sort` ";
1016
            $sqlOption = "SELECT * FROM $table_survey_question_option
1017
                          WHERE question_id = $question_id
1018
                          ORDER BY `sort` ";
1019
        }
1020
        // Getting the information of the question
1021
1022
        $result = Database::query($sql);
1023
        $row = Database::fetch_array($result, 'ASSOC');
1024
1025
        $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...
1026
        $return['parent_id'] = isset($row['parent_id']) ? $row['parent_id'] : 0;
1027
        $return['parent_option_id'] = isset($row['parent_option_id']) ? $row['parent_option_id'] : 0;
1028
        $return['question_id'] = $row['question_id'];
1029
        $return['type'] = $row['type'];
1030
        $return['question'] = $row['survey_question'];
1031
        $return['horizontalvertical'] = $row['display'];
1032
        $return['shared_question_id'] = $row['shared_question_id'];
1033
        $return['maximum_score'] = $row['max_value'];
1034
        $return['is_required'] = api_get_configuration_value('allow_required_survey_questions')
1035
            ? $row['is_required']
1036
            : false;
1037
1038
        if (0 != $row['survey_group_pri']) {
1039
            $return['assigned'] = $row['survey_group_pri'];
1040
            $return['choose'] = 1;
1041
        } else {
1042
            $return['assigned1'] = $row['survey_group_sec1'];
1043
            $return['assigned2'] = $row['survey_group_sec2'];
1044
            $return['choose'] = 2;
1045
        }
1046
1047
        // Getting the information of the question options
1048
        $result = Database::query($sqlOption);
1049
        $counter = 0;
1050
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1051
            /** @todo this should be renamed to options instead of answers */
1052
            $return['answers'][] = $row['option_text'];
1053
            $return['values'][] = $row['value'];
1054
            $return['answer_data'][$counter]['data'] = $row['option_text'];
1055
            $return['answer_data'][$counter]['iid'] = $row['iid'];
1056
            /** @todo this can be done more elegantly (used in reporting) */
1057
            $return['answersid'][] = $row['question_option_id'];
1058
            $counter++;
1059
        }
1060
1061
        return $return;
1062
    }
1063
1064
    /**
1065
     * This function gets all the question of any given survey.
1066
     *
1067
     * @param int $surveyId the id of the survey
1068
     * @param int $courseId
1069
     *
1070
     * @return array containing all the questions of the survey
1071
     *
1072
     * @author Patrick Cool <[email protected]>, Ghent University
1073
     *
1074
     * @version February 2007
1075
     *
1076
     * @todo one sql call should do the trick
1077
     */
1078
    public static function get_questions($surveyId, $courseId = 0)
1079
    {
1080
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1081
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1082
1083
        $courseId = (int) $courseId;
1084
        $surveyId = (int) $surveyId;
1085
1086
        if (empty($courseId)) {
1087
            $courseId = api_get_course_int_id();
1088
        }
1089
1090
        // Getting the information of the question
1091
        $sql = "SELECT * FROM $tbl_survey_question
1092
		        WHERE c_id = $courseId AND survey_id= $surveyId ";
1093
        $result = Database::query($sql);
1094
        $questions = [];
1095
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1096
            $questionId = $row['question_id'];
1097
            $questions[$questionId]['survey_id'] = $surveyId;
1098
            $questions[$questionId]['question_id'] = $questionId;
1099
            $questions[$questionId]['type'] = $row['type'];
1100
            $questions[$questionId]['question'] = $row['survey_question'];
1101
            $questions[$questionId]['horizontalvertical'] = $row['display'];
1102
            $questions[$questionId]['maximum_score'] = $row['max_value'];
1103
            $questions[$questionId]['sort'] = $row['sort'];
1104
            $questions[$questionId]['survey_question_comment'] = $row['survey_question_comment'];
1105
1106
        // Getting the information of the question options
1107
        $sql = "SELECT * FROM $table_survey_question_option
1108
		             WHERE c_id = $courseId AND survey_id= $surveyId  AND question_id = $questionId";
1109
            $resultOptions = Database::query($sql);
1110
            while ($rowOption = Database::fetch_array($resultOptions, 'ASSOC')) {
1111
                $questions[$questionId]['answers'][] = $rowOption['option_text'];
1112
            }
1113
        }
1114
1115
        return $questions;
1116
    }
1117
1118
    /**
1119
     * This function saves a question in the database.
1120
     * This can be either an update of an existing survey or storing a new survey.
1121
     *
1122
     * @param array $survey_data
1123
     * @param array $form_content all the information of the form
1124
     *
1125
     * @return string
1126
     *
1127
     * @author Patrick Cool <[email protected]>, Ghent University
1128
     *
1129
     * @version January 2007
1130
     */
1131
    public static function save_question($survey_data, $form_content, $showMessage = true, $dataFromDatabase = [])
1132
    {
1133
        $return_message = '';
1134
        if (strlen($form_content['question']) > 1) {
1135
            // Checks length of the question
1136
            $empty_answer = false;
1137
            if ($survey_data['survey_type'] == 1) {
1138
                if (empty($form_content['choose'])) {
1139
                    return 'PleaseChooseACondition';
1140
                }
1141
1142
                if (($form_content['choose'] == 2) &&
1143
                    ($form_content['assigned1'] == $form_content['assigned2'])
1144
                ) {
1145
                    return 'ChooseDifferentCategories';
1146
                }
1147
            }
1148
1149
            if ($form_content['type'] !== 'percentage') {
1150
                if (isset($form_content['answers'])) {
1151
                    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...
1152
                        if (strlen($form_content['answers'][$i]) < 1) {
1153
                            $empty_answer = true;
1154
                            break;
1155
                        }
1156
                    }
1157
                }
1158
            }
1159
1160
            if ('score' == $form_content['type']) {
1161
                if (strlen($form_content['maximum_score']) < 1) {
1162
                    $empty_answer = true;
1163
                }
1164
            }
1165
1166
            $course_id = api_get_course_int_id();
1167
1168
            if (!$empty_answer) {
1169
                // Table definitions
1170
                $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1171
                $surveyId = (int) $form_content['survey_id'];
1172
1173
                // Getting all the information of the survey
1174
                $survey_data = self::get_survey($surveyId);
1175
1176
                // Storing the question in the shared database
1177
                if (is_numeric($survey_data['survey_share']) && $survey_data['survey_share'] != 0) {
1178
                    $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

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

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