Passed
Push — master ( e852e9...c6d6bf )
by Julito
08:04
created

SurveyManager::deleteSurvey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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

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

354
                Event::/** @scrutinizer ignore-call */ 
355
                       addEvent(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
355
                    LOG_SURVEY_CREATED,
356
                    LOG_SURVEY_ID,
357
                    $survey_id,
358
                    null,
359
                    api_get_user_id(),
360
                    api_get_course_int_id(),
361
                    api_get_session_id()
362
                );
363
            }
364
365
            if (1 == $values['survey_type'] && !empty($values['parent_id'])) {
366
                self::copy_survey($values['parent_id'], $survey_id);
367
            }
368
369
            Display::addFlash(
370
                Display::return_message(
371
                    get_lang('The survey has been created succesfully'),
372
                    'success'
373
                )
374
            );
375
            $return['id'] = $survey_id;
376
        } else {
377
            // Check whether the code doesn't soon exists in this language
378
            $sql = 'SELECT 1 FROM '.$table_survey.'
379
			        WHERE
380
			            code = "'.Database::escape_string($values['survey_code']).'" AND
381
			            lang = "'.Database::escape_string($values['survey_language']).'" AND
382
			            iid !='.intval($values['survey_id']);
383
            $rs = Database::query($sql);
384
            if (Database::num_rows($rs) > 0) {
385
                Display::addFlash(
386
                    Display::return_message(
387
                        get_lang('This survey code soon exists in this language'),
388
                        'error'
389
                    )
390
                );
391
                $return['type'] = 'error';
392
                $return['id'] = isset($values['survey_id']) ? $values['survey_id'] : 0;
393
394
                return $return;
395
            }
396
397
            if (!isset($values['anonymous'])
398
                || (isset($values['anonymous']) && '' == $values['anonymous'])
399
            ) {
400
                $values['anonymous'] = 0;
401
            }
402
403
            /** @var CSurvey $survey */
404
            $survey = $repo->find($values['survey_id']);
405
406
            $extraParams = [];
407
            $survey->setOneQuestionPerPage(isset($values['one_question_per_page']) ? $values['one_question_per_page'] : 0);
408
            $survey->setShuffle(isset($values['shuffle']) ? $values['shuffle'] : 0);
409
410
            if (0 == $values['anonymous']) {
411
                $survey->setShowFormProfile(isset($values['show_form_profile']) ? $values['show_form_profile'] : 0);
412
                $isFormProfile = isset($values['show_form_profile']) ? $values['show_form_profile'] : 0;
413
                if (1 == $isFormProfile) {
414
                    $fields = explode(',', $values['input_name_list']);
415
                    $field_values = '';
416
                    foreach ($fields as &$field) {
417
                        if ('' != $field) {
418
                            if (!isset($values[$field]) ||
419
                                (isset($values[$field]) && '' == $values[$field])
420
                            ) {
421
                                $values[$field] = 0;
422
                            }
423
                            $field_values .= $field.':'.$values[$field].'@';
424
                        }
425
                    }
426
                    $survey->setFormFields($field_values);
427
                } else {
428
                    $survey->setFormFields('');
429
                }
430
            } else {
431
                $survey->setFormFields('');
432
                $survey->setShowFormProfile(0);
433
            }
434
435
            $survey
436
                ->setTitle($values['survey_title'])
437
                ->setSubtitle($values['survey_title'])
438
                ->setLang($values['survey_language'])
439
                ->setAvailFrom(api_get_utc_datetime($values['start_date'].':00', true, true))
440
                ->setAvailTill(api_get_utc_datetime($values['end_date'].':59', true, true))
441
                ->setIsShared($shared_survey_id)
442
                ->setTemplate('template')
443
                ->setIntro($values['survey_introduction'])
444
                ->setSurveyThanks($values['survey_thanks'])
445
                ->setAnonymous((string) $values['anonymous'])
446
                ->setVisibleResults((int) $values['visible_results'])
447
            ;
448
449
            $repo->update($survey);
450
            /*
451
            // Update into item_property (update)
452
            api_item_property_update(
453
                api_get_course_info(),
454
                TOOL_SURVEY,
455
                $values['survey_id'],
456
                'SurveyUpdated',
457
                api_get_user_id()
458
            );*/
459
460
            Display::addFlash(
461
                Display::return_message(
462
                    get_lang('The survey has been updated succesfully'),
463
                    'confirmation'
464
                )
465
            );
466
467
            $return['id'] = $values['survey_id'];
468
        }
469
470
        $survey_id = (int) $return['id'];
471
472
        // Gradebook
473
        $gradebook_option = false;
474
        if (isset($values['survey_qualify_gradebook'])) {
475
            $gradebook_option = $values['survey_qualify_gradebook'] > 0;
476
        }
477
478
        $gradebook_link_type = 8;
479
        $link_info = GradebookUtils::isResourceInCourseGradebook(
480
            $courseCode,
481
            $gradebook_link_type,
482
            $survey_id,
483
            $session_id
484
        );
485
486
        $gradebook_link_id = isset($link_info['id']) ? $link_info['id'] : false;
487
488
        if ($gradebook_option) {
489
            if ($survey_id > 0) {
490
                $title_gradebook = ''; // Not needed here.
491
                $description_gradebook = ''; // Not needed here.
492
                $survey_weight = floatval($_POST['survey_weight']);
493
                $max_score = 1;
494
495
                if (!$gradebook_link_id) {
496
                    GradebookUtils::add_resource_to_course_gradebook(
497
                        $values['category_id'],
498
                        $courseCode,
499
                        $gradebook_link_type,
500
                        $survey_id,
501
                        $title_gradebook,
502
                        $survey_weight,
503
                        $max_score,
504
                        $description_gradebook,
505
                        1,
506
                        $session_id
507
                    );
508
                } else {
509
                    GradebookUtils::updateResourceFromCourseGradebook(
510
                        $gradebook_link_id,
511
                        $courseCode,
512
                        $survey_weight
513
                    );
514
                }
515
            }
516
        } else {
517
            // Delete everything of the gradebook for this $linkId
518
            GradebookUtils::remove_resource_from_course_gradebook($gradebook_link_id);
519
        }
520
521
        return $return;
522
    }
523
524
    public static function deleteSurvey(CSurvey $survey)
525
    {
526
        $repo = Container::getSurveyRepository();
527
        $surveyId = $survey->getIid();
528
        $repo->delete($survey);
529
530
        $table_survey = Database::get_course_table(TABLE_SURVEY);
531
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
532
533
        Event::addEvent(
534
            LOG_SURVEY_DELETED,
535
            LOG_SURVEY_ID,
536
            $surveyId,
537
            null,
538
            api_get_user_id(),
539
            api_get_course_int_id(),
540
            api_get_session_id()
541
        );
542
543
        /*// Deleting groups of this survey
544
        $sql = "DELETE FROM $table_survey_question_group
545
                WHERE c_id = $course_id AND iid='".$survey_id."'";
546
        Database::query($sql);*/
547
548
        // Deleting the questions of the survey
549
        self::delete_all_survey_questions($surveyId, false);
550
551
        // Update into item_property (delete)
552
        /*api_item_property_update(
553
            $course_info,
554
            TOOL_SURVEY,
555
            $survey_id,
556
            'SurveyDeleted',
557
            api_get_user_id()
558
        );*/
559
560
        SkillModel::deleteSkillsFromItem($surveyId, ITEM_TYPE_SURVEY);
561
562
        return true;
563
    }
564
565
    /**
566
     * Copy given survey to a new (optional) given survey ID.
567
     *
568
     * @param int $survey_id
569
     * @param int $new_survey_id
570
     * @param int $targetCourseId
571
     *
572
     * @return bool
573
     */
574
    public static function copy_survey($survey_id, $new_survey_id = null, $targetCourseId = null)
575
    {
576
        $course_id = api_get_course_int_id();
577
        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...
578
            $targetCourseId = $course_id;
579
        }
580
581
        // Database table definitions
582
        $table_survey = Database::get_course_table(TABLE_SURVEY);
583
        $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
584
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
585
        $table_survey_options = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
586
        $survey_id = (int) $survey_id;
587
588
        // Get groups
589
        $survey_data = self::get_survey($survey_id, 0, null, true);
590
        if (empty($survey_data)) {
591
            return true;
592
        }
593
594
        if (empty($new_survey_id)) {
595
            $params = $survey_data;
596
            $params['code'] = self::generate_unique_code($params['code']);
597
            $params['c_id'] = $targetCourseId;
598
            unset($params['survey_id']);
599
            $params['session_id'] = api_get_session_id();
600
            $params['title'] = $params['title'].' '.get_lang('Copy');
601
            unset($params['iid']);
602
            $params['invited'] = 0;
603
            $params['answered'] = 0;
604
            $new_survey_id = Database::insert($table_survey, $params);
605
        } else {
606
            $new_survey_id = (int) $new_survey_id;
607
        }
608
609
        $sql = "SELECT * FROM $table_survey_question_group
610
                WHERE c_id = $course_id AND iid = $survey_id";
611
        $res = Database::query($sql);
612
        while ($row = Database::fetch_array($res, 'ASSOC')) {
613
            $params = [
614
                'c_id' => $targetCourseId,
615
                'name' => $row['name'],
616
                'description' => $row['description'],
617
                'survey_id' => $new_survey_id,
618
            ];
619
            $insertId = Database::insert($table_survey_question_group, $params);
620
621
            $sql = "UPDATE $table_survey_question_group SET id = iid
622
                    WHERE iid = $insertId";
623
            Database::query($sql);
624
625
            $group_id[$row['id']] = $insertId;
626
        }
627
628
        // Get questions
629
        $sql = "SELECT * FROM $table_survey_question
630
                WHERE c_id = $course_id AND survey_id = $survey_id";
631
        $res = Database::query($sql);
632
        while ($row = Database::fetch_array($res, 'ASSOC')) {
633
            $params = [
634
                'c_id' => $targetCourseId,
635
                'survey_id' => $new_survey_id,
636
                'survey_question' => $row['survey_question'],
637
                'survey_question_comment' => $row['survey_question_comment'],
638
                'type' => $row['type'],
639
                'display' => $row['display'],
640
                'sort' => $row['sort'],
641
                'shared_question_id' => $row['shared_question_id'],
642
                'max_value' => $row['max_value'],
643
                'survey_group_pri' => $row['survey_group_pri'],
644
                'survey_group_sec1' => $row['survey_group_sec1'],
645
                'survey_group_sec2' => $row['survey_group_sec2'],
646
            ];
647
648
            if (api_get_configuration_value('allow_required_survey_questions')) {
649
                if (isset($row['is_required'])) {
650
                    $params['is_required'] = $row['is_required'];
651
                }
652
            }
653
654
            $insertId = Database::insert($table_survey_question, $params);
655
            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...
656
                /*$sql = "UPDATE $table_survey_question SET question_id = iid WHERE iid = $insertId";
657
                Database::query($sql);*/
658
                $question_id[$row['question_id']] = $insertId;
659
            }
660
        }
661
662
        // Get questions options
663
        $sql = "SELECT * FROM $table_survey_options
664
                WHERE c_id = $course_id AND survey_id='".$survey_id."'";
665
666
        $res = Database::query($sql);
667
        while ($row = Database::fetch_array($res, 'ASSOC')) {
668
            $params = [
669
                'c_id' => $targetCourseId,
670
                '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...
671
                'survey_id' => $new_survey_id,
672
                'option_text' => $row['option_text'],
673
                'sort' => $row['sort'],
674
                'value' => $row['value'],
675
            ];
676
            $insertId = Database::insert($table_survey_options, $params);
677
            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...
678
                $sql = "UPDATE $table_survey_options SET question_option_id = $insertId
679
                        WHERE iid = $insertId";
680
                Database::query($sql);
681
            }
682
        }
683
684
        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...
685
    }
686
687
    /**
688
     * This function duplicates a survey (and also all the question in that survey.
689
     *
690
     * @param int $surveyId id of the survey that has to be duplicated
691
     * @param int $courseId id of the course which survey has to be duplicated
692
     *
693
     * @return true
694
     *
695
     * @author Eric Marguin <[email protected]>, Elixir Interactive
696
     *
697
     * @version October 2007
698
     */
699
    public static function empty_survey($surveyId, $courseId = 0)
700
    {
701
        // Database table definitions
702
        $table_survey_invitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
703
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
704
        $table_survey = Database::get_course_table(TABLE_SURVEY);
705
706
        $courseId = (int) $courseId;
707
        $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
708
        $surveyId = (int) $surveyId;
709
710
        $datas = self::get_survey($surveyId);
711
        $session_where = '';
712
        if (0 != api_get_session_id()) {
713
            $session_where = ' AND session_id = "'.api_get_session_id().'" ';
714
        }
715
716
        $sql = 'DELETE FROM '.$table_survey_invitation.'
717
		        WHERE
718
		            c_id = '.$courseId.' AND
719
		            survey_code = "'.Database::escape_string($datas['code']).'" '.$session_where.' ';
720
        Database::query($sql);
721
722
        $sql = 'DELETE FROM '.$table_survey_answer.'
723
		        WHERE c_id = '.$courseId.' AND survey_id='.$surveyId;
724
        Database::query($sql);
725
726
        $sql = 'UPDATE '.$table_survey.' SET invited=0, answered=0
727
		        WHERE c_id = '.$courseId.' AND iid ='.$surveyId;
728
        Database::query($sql);
729
730
        Event::addEvent(
731
            LOG_SURVEY_CLEAN_RESULTS,
732
            LOG_SURVEY_ID,
733
            $surveyId,
734
            null,
735
            api_get_user_id(),
736
            api_get_course_int_id(),
737
            api_get_session_id()
738
        );
739
740
        return true;
741
    }
742
743
    /**
744
     * Updates c_survey.answered: number of people who have taken the survey (=filled at least one question).
745
     */
746
    public static function updateSurveyAnswered(CSurvey $survey, $user)
747
    {
748
        $em = Database::getManager();
749
        $surveyId = $survey->getIid();
750
        $courseId = api_get_course_int_id();
751
        $sessionId = api_get_session_id();
752
753
        $survey->setAnswered($survey->getAnswered() + 1);
754
        $em->persist($survey);
755
        $em->flush();
756
757
        $table = Database::get_course_table(TABLE_SURVEY_INVITATION);
758
        // Storing that the user has finished the survey.
759
        $sql = "UPDATE $table
760
                SET
761
                    answered_at = '".api_get_utc_datetime()."',
762
                    answered = 1
763
                WHERE
764
                    c_id = $courseId AND
765
                    session_id = $sessionId AND
766
                    user_id ='".Database::escape_string($user)."' AND
767
                    survey_id ='".$surveyId."'";
768
        Database::query($sql);
769
    }
770
771
    /**
772
     * This function return the "icon" of the question type.
773
     *
774
     * @param string $type
775
     *
776
     * @author Patrick Cool <[email protected]>, Ghent University
777
     *
778
     * @version February 2007
779
     */
780
    public static function icon_question($type)
781
    {
782
        // the possible question types
783
        $possible_types = [
784
            'personality',
785
            'yesno',
786
            'multiplechoice',
787
            'multipleresponse',
788
            'open',
789
            'dropdown',
790
            'comment',
791
            'pagebreak',
792
            'percentage',
793
            'score',
794
        ];
795
796
        // the images array
797
        $icon_question = [
798
            'yesno' => 'yesno.png',
799
            'personality' => 'yesno.png',
800
            'multiplechoice' => 'mcua.png',
801
            'multipleresponse' => 'mcma.png',
802
            'open' => 'open_answer.png',
803
            'dropdown' => 'dropdown.png',
804
            'percentage' => 'percentagequestion.png',
805
            'score' => 'scorequestion.png',
806
            'comment' => 'commentquestion.png',
807
            'pagebreak' => 'page_end.png',
808
        ];
809
810
        if (in_array($type, $possible_types)) {
811
            return $icon_question[$type];
812
        }
813
814
        return false;
815
    }
816
817
    /**
818
     * This function retrieves all the information of a question.
819
     *
820
     * @param int  $question_id the id of the question
821
     * @param bool $shared
822
     *
823
     * @return array
824
     *
825
     * @author Patrick Cool <[email protected]>, Ghent University
826
     *
827
     * @version January 2007
828
     *
829
     * @todo one sql call should do the trick
830
     */
831
    public static function get_question($question_id)
832
    {
833
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
834
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
835
        $course_id = api_get_course_int_id();
836
        $question_id = (int) $question_id;
837
838
        if (empty($question_id)) {
839
            return [];
840
        }
841
842
        $sql = "SELECT * FROM $tbl_survey_question
843
                WHERE iid = $question_id
844
                ORDER BY `sort` ";
845
846
        $sqlOption = "  SELECT * FROM $table_survey_question_option
847
                        WHERE question_id='".$question_id."'
848
                        ORDER BY `sort` ";
849
        // Getting the information of the question
850
        $result = Database::query($sql);
851
        $row = Database::fetch_array($result, 'ASSOC');
852
853
        $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...
854
        $return['parent_id'] = isset($row['parent_id']) ? $row['parent_id'] : 0;
855
        $return['parent_option_id'] = isset($row['parent_option_id']) ? $row['parent_option_id'] : 0;
856
        $return['question_id'] = $row['iid'];
857
        $return['type'] = $row['type'];
858
        $return['question'] = $row['survey_question'];
859
        $return['horizontalvertical'] = $row['display'];
860
        $return['shared_question_id'] = $row['shared_question_id'];
861
        $return['maximum_score'] = $row['max_value'];
862
        $return['is_required'] = api_get_configuration_value('allow_required_survey_questions')
863
            ? $row['is_required']
864
            : false;
865
866
        if (0 != $row['survey_group_pri']) {
867
            $return['assigned'] = $row['survey_group_pri'];
868
            $return['choose'] = 1;
869
        } else {
870
            $return['assigned1'] = $row['survey_group_sec1'];
871
            $return['assigned2'] = $row['survey_group_sec2'];
872
            $return['choose'] = 2;
873
        }
874
875
        // Getting the information of the question options
876
        $result = Database::query($sqlOption);
877
        $counter = 0;
878
        while ($row = Database::fetch_array($result, 'ASSOC')) {
879
            /** @todo this should be renamed to options instead of answers */
880
            $return['answers'][] = $row['option_text'];
881
            $return['values'][] = $row['value'];
882
            $return['answer_data'][$counter]['data'] = $row['option_text'];
883
            $return['answer_data'][$counter]['iid'] = $row['iid'];
884
            /** @todo this can be done more elegantly (used in reporting) */
885
            $return['answersid'][] = $row['iid'];
886
            $counter++;
887
        }
888
889
        return $return;
890
    }
891
892
    /**
893
     * This function gets all the question of any given survey.
894
     *
895
     * @param int $surveyId the id of the survey
896
     * @param int $courseId
897
     *
898
     * @return array containing all the questions of the survey
899
     *
900
     * @author Patrick Cool <[email protected]>, Ghent University
901
     *
902
     * @version February 2007
903
     *
904
     * @todo one sql call should do the trick
905
     */
906
    public static function get_questions($surveyId, $courseId = 0)
907
    {
908
        $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
909
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
910
911
        $courseId = (int) $courseId;
912
        $surveyId = (int) $surveyId;
913
914
        // Getting the information of the question
915
        $sql = "SELECT * FROM $tbl_survey_question
916
		        WHERE survey_id= $surveyId ";
917
        $result = Database::query($sql);
918
        $questions = [];
919
        while ($row = Database::fetch_array($result, 'ASSOC')) {
920
            $questionId = $row['iid'];
921
            $questions[$questionId]['survey_id'] = $surveyId;
922
            $questions[$questionId]['question_id'] = $questionId;
923
            $questions[$questionId]['type'] = $row['type'];
924
            $questions[$questionId]['question'] = $row['survey_question'];
925
            $questions[$questionId]['horizontalvertical'] = $row['display'];
926
            $questions[$questionId]['maximum_score'] = $row['max_value'];
927
            $questions[$questionId]['sort'] = $row['sort'];
928
            $questions[$questionId]['survey_question_comment'] = $row['survey_question_comment'];
929
930
            // Getting the information of the question options
931
            $sql = "SELECT * FROM $table_survey_question_option
932
		             WHERE survey_id= $surveyId  AND question_id = $questionId";
933
            $resultOptions = Database::query($sql);
934
            while ($rowOption = Database::fetch_array($resultOptions, 'ASSOC')) {
935
                $questions[$questionId]['answers'][] = $rowOption['option_text'];
936
            }
937
        }
938
939
        return $questions;
940
    }
941
942
    public static function saveQuestion(CSurvey $survey, array $form_content, bool $showMessage = true, array $dataFromDatabase = [])
943
    {
944
        $surveyId = $survey->getIid();
945
946
        $message = '';
947
        if (strlen($form_content['question']) > 1) {
948
            // Checks length of the question
949
            $empty_answer = false;
950
            if (1 == $survey->getSurveyType()) {
951
                if (empty($form_content['choose'])) {
952
                    return 'PleaseChooseACondition';
953
                }
954
955
                if ((2 == $form_content['choose']) &&
956
                    ($form_content['assigned1'] == $form_content['assigned2'])
957
                ) {
958
                    return 'ChooseDifferentCategories';
959
                }
960
            }
961
962
            if ('percentage' !== $form_content['type']) {
963
                if (isset($form_content['answers'])) {
964
                    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...
965
                        if (strlen($form_content['answers'][$i]) < 1) {
966
                            $empty_answer = true;
967
                            break;
968
                        }
969
                    }
970
                }
971
            }
972
973
            if ('score' === $form_content['type']) {
974
                if (strlen($form_content['maximum_score']) < 1) {
975
                    $empty_answer = true;
976
                }
977
            }
978
979
            $em = Database::getManager();
980
            $course_id = api_get_course_int_id();
981
            if (!$empty_answer) {
982
                // Table definitions
983
                $tbl_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
984
985
                // Getting all the information of the survey
986
                $survey_data = self::get_survey($surveyId);
987
988
                // Storing a new question
989
                if ('' == $form_content['question_id'] || !is_numeric($form_content['question_id'])) {
990
                    // Finding the max sort order of the questions in the given survey
991
                    $sql = "SELECT max(sort) AS max_sort
992
					        FROM $tbl_survey_question
993
                            WHERE survey_id = $surveyId ";
994
                    $result = Database::query($sql);
995
                    $row = Database::fetch_array($result, 'ASSOC');
996
                    $max_sort = $row['max_sort'];
997
998
                    $question = new CSurveyQuestion();
999
1000
                    // Some variables defined for survey-test type
1001
                    if (isset($_POST['choose'])) {
1002
                        if (1 == $_POST['choose']) {
1003
                            $question->setSurveyGroupPri($_POST['assigned']);
1004
                        } elseif (2 == $_POST['choose']) {
1005
                            $question->setSurveyGroupSec1($_POST['assigned1']);
1006
                            $question->setSurveyGroupSec2($_POST['assigned2']);
1007
                        }
1008
                    }
1009
1010
                    $question
1011
                        ->setSurveyQuestionComment($form_content['question_comment'] ?? '')
1012
                        ->setMaxValue($form_content['maximum_score'] ?? 0)
1013
                        ->setDisplay($form_content['horizontalvertical'] ?? '')
1014
                        //->setCId($course_id)
1015
                        ->setSurvey($survey)
1016
                        ->setSurveyQuestion($form_content['question'])
1017
                        ->setType($form_content['type'])
1018
                        ->setSort($max_sort + 1)
1019
                        ->setSharedQuestionId((int) $form_content['shared_question_id'])
1020
                    ;
1021
1022
                    if (api_get_configuration_value('allow_required_survey_questions')) {
1023
                        $question->setIsMandatory(isset($form_content['is_required']));
1024
                    }
1025
1026
                    if (api_get_configuration_value('survey_question_dependency')) {
1027
                        $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...
1028
                        $params['parent_option_id'] = 0;
1029
                        if (isset($form_content['parent_id']) &&
1030
                            isset($form_content['parent_option_id']) &&
1031
                            !empty($form_content['parent_id']) &&
1032
                            !empty($form_content['parent_option_id'])
1033
                        ) {
1034
                            $params['parent_id'] = $form_content['parent_id'];
1035
                            $params['parent_option_id'] = $form_content['parent_option_id'];
1036
                        }
1037
                    }
1038
1039
                    $em->persist($question);
1040
                    $em->flush();
1041
1042
                    $question_id = $question->getIid();
1043
                    if ($question_id) {
1044
                        /*$sql = "UPDATE $tbl_survey_question SET question_id = $question_id
1045
                                WHERE iid = $question_id";
1046
                        Database::query($sql);*/
1047
                        $form_content['question_id'] = $question_id;
1048
                        $message = 'The question has been added.';
1049
                    }
1050
                } else {
1051
                    $repo = $em->getRepository(CSurveyQuestion::class);
1052
                    $repoOption = $em->getRepository(CSurveyQuestionOption::class);
1053
                    /** @var CSurveyQuestion $question */
1054
                    $question = $repo->find($form_content['question_id']);
1055
1056
                    if (isset($_POST['choose'])) {
1057
                        if (1 == $_POST['choose']) {
1058
                            $question->setSurveyGroupPri($_POST['assigned']);
1059
                            $question->setSurveyGroupSec1(0);
1060
                            $question->setSurveyGroupSec2(0);
1061
                        } elseif (2 == $_POST['choose']) {
1062
                            $question->setSurveyGroupPri(0);
1063
                            $question->setSurveyGroupSec1($_POST['assigned1']);
1064
                            $question->setSurveyGroupSec2($_POST['assigned2']);
1065
                        }
1066
                    }
1067
1068
                    $maxScore = isset($form_content['maximum_score']) ? $form_content['maximum_score'] : null;
1069
                    $questionComment = $form_content['question_comment'] ?? '';
1070
                    $question
1071
                        ->setSurveyQuestionComment($questionComment)
1072
                        ->setSurveyQuestion($form_content['question'])
1073
                        ->setDisplay($form_content['horizontalvertical'])
1074
                    ;
1075
1076
                    if (api_get_configuration_value('allow_required_survey_questions')) {
1077
                        $question->isMandatory(isset($form_content['is_required']));
1078
                    }
1079
1080
                    if (api_get_configuration_value('survey_question_dependency')) {
1081
                        $params['parent_id'] = 0;
1082
                        $params['parent_option_id'] = 0;
1083
                        if (isset($form_content['parent_id']) &&
1084
                            isset($form_content['parent_option_id']) &&
1085
                            !empty($form_content['parent_id']) &&
1086
                            !empty($form_content['parent_option_id'])
1087
                        ) {
1088
                            $question->setParent($repo->find($form_content['parent_id']));
1089
                            $question->setParentOption($repoOption->find($form_content['parent_option_id']));
1090
                        }
1091
                    }
1092
1093
                    $em->persist($question);
1094
                    $em->flush();
1095
                    $message = 'QuestionUpdated';
1096
                }
1097
                // Storing the options of the question
1098
                self::saveQuestionOptions($survey, $question, $form_content, $dataFromDatabase);
1099
            } else {
1100
                $message = 'PleasFillAllAnswer';
1101
            }
1102
        } else {
1103
            $message = 'PleaseEnterAQuestion';
1104
        }
1105
1106
        if ($showMessage) {
1107
            if (!empty($message)) {
1108
                Display::addFlash(Display::return_message(get_lang($message)));
1109
            }
1110
        }
1111
1112
        return $message;
1113
    }
1114
1115
    /**
1116
     * This functions moves a question of a survey up or down.
1117
     *
1118
     * @param string $direction
1119
     * @param int    $survey_question_id
1120
     * @param int    $survey_id
1121
     *
1122
     * @author Patrick Cool <[email protected]>, Ghent University
1123
     *
1124
     * @version January 2007
1125
     */
1126
    public static function move_survey_question($direction, $survey_question_id, $survey_id)
1127
    {
1128
        // Table definition
1129
        $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1130
        $course_id = api_get_course_int_id();
1131
1132
        if ('moveup' === $direction) {
1133
            $sort = 'DESC';
1134
        }
1135
        if ('movedown' === $direction) {
1136
            $sort = 'ASC';
1137
        }
1138
1139
        $survey_id = (int) $survey_id;
1140
1141
        // Finding the two questions that needs to be swapped
1142
        $sql = "SELECT * FROM $table_survey_question
1143
		        WHERE c_id = $course_id AND survey_id='".$survey_id."'
1144
		        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...
1145
        $result = Database::query($sql);
1146
        $found = false;
1147
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1148
            if ($found) {
1149
                $question_id_two = $row['question_id'];
1150
                $question_sort_two = $row['sort'];
1151
                $found = false;
1152
            }
1153
            if ($row['question_id'] == $survey_question_id) {
1154
                $found = true;
1155
                $question_id_one = $row['question_id'];
1156
                $question_sort_one = $row['sort'];
1157
            }
1158
        }
1159
1160
        $sql = "UPDATE $table_survey_question
1161
                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...
1162
		        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...
1163
        Database::query($sql);
1164
1165
        $sql = "UPDATE $table_survey_question
1166
                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...
1167
		        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...
1168
        Database::query($sql);
1169
    }
1170
1171
    /**
1172
     * This function deletes all the questions of a given survey
1173
     * This function is normally only called when a survey is deleted.
1174
     *
1175
     * @param int $survey_id the id of the survey that has to be deleted
1176
     *
1177
     * @return bool
1178
     *
1179
     * @author Patrick Cool <[email protected]>, Ghent University
1180
     *
1181
     * @version January 2007
1182
     */
1183
    public static function delete_all_survey_questions($survey_id, $shared = false)
1184
    {
1185
        $course_id = api_get_course_int_id();
1186
        $survey_id = (int) $survey_id;
1187
1188
        /*$sql = "DELETE FROM $table_survey_question
1189
                WHERE $course_condition survey_id = '".$survey_id."'";
1190
1191
        // Deleting the survey questions
1192
        Database::query($sql);*/
1193
1194
        // Deleting all the options of the questions of the survey
1195
        //self::delete_all_survey_questions_options($survey_id, $shared);
1196
1197
        // Deleting all the answers on this survey
1198
        //self::delete_all_survey_answers($survey_id);
1199
1200
        return true;
1201
    }
1202
1203
    public static function deleteQuestion($questionId)
1204
    {
1205
        $questionId = (int) $questionId;
1206
        if (empty($questionId)) {
1207
            return false;
1208
        }
1209
1210
        $em = Database::getManager();
1211
        $repo = Container::getSurveyQuestionRepository();
1212
        $question = $repo->find($questionId);
1213
        if ($question) {
1214
            $em->remove($question);
1215
            $em->flush();
1216
1217
            return true;
1218
        }
1219
1220
        return false;
1221
    }
1222
1223
    public static function saveQuestionOptions(CSurvey $survey, CSurveyQuestion $question, $form_content, $dataFromDatabase = [])
1224
    {
1225
        $course_id = api_get_course_int_id();
1226
        $type = $form_content['type'];
1227
1228
        // A percentage question type has options 1 -> 100
1229
        if ('percentage' === $type) {
1230
            for ($i = 1; $i < 101; $i++) {
1231
                $form_content['answers'][] = $i;
1232
            }
1233
        }
1234
        $em = Database::getManager();
1235
1236
        // Table definition
1237
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1238
1239
        // We are editing a question so we first have to remove all the existing options from the database
1240
        $optionsToDelete = [];
1241
        if (isset($dataFromDatabase['answer_data'])) {
1242
            foreach ($dataFromDatabase['answer_data'] as $data) {
1243
                if ('other' === $data['data'] && 'multiplechoiceother' === $type) {
1244
                    continue;
1245
                }
1246
1247
                if (!in_array($data['iid'], $form_content['answersid'])) {
1248
                    $optionsToDelete[] = $data['iid'];
1249
                }
1250
            }
1251
        }
1252
1253
        if (!empty($optionsToDelete)) {
1254
            foreach ($optionsToDelete as $iid) {
1255
                $iid = (int) $iid;
1256
                $sql = "DELETE FROM $table
1257
			            WHERE
1258
			                iid = $iid AND
1259
			                c_id = $course_id AND
1260
                            question_id = '".intval($form_content['question_id'])."'
1261
                            ";
1262
                Database::query($sql);
1263
            }
1264
        }
1265
1266
        $counter = 1;
1267
        if (isset($form_content['answers']) && is_array($form_content['answers'])) {
1268
            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...
1269
                $values = isset($form_content['values']) ? (int) $form_content['values'][$i] : 0;
1270
                $answerId = 0;
1271
                if (isset($form_content['answersid']) && isset($form_content['answersid'][$i])) {
1272
                    $answerId = $form_content['answersid'][$i];
1273
                }
1274
                if (empty($answerId)) {
1275
                    $option = new CSurveyQuestionOption();
1276
                    $option
1277
                        ->setQuestion($question)
1278
                        ->setOptionText($form_content['answers'][$i])
1279
                        ->setSurvey($survey)
1280
                        ->setValue($values)
1281
                        ->setSort($counter)
1282
                    ;
1283
                    $em->persist($option);
1284
                    $em->flush();
1285
                    $insertId = $option->getIid();
1286
                    if ($insertId) {
1287
                        $counter++;
1288
                    }
1289
                } else {
1290
                    $repo = $em->getRepository(CSurveyQuestionOption::class);
1291
                    /** @var CSurveyQuestionOption $option */
1292
                    $option = $repo->find($answerId);
1293
                    if ($option) {
1294
                        $option
1295
                            ->setOptionText($form_content['answers'][$i])
1296
                            ->setValue($values)
1297
                            ->setSort($counter)
1298
                        ;
1299
                        $em->persist($option);
1300
                        $em->flush();
1301
                    }
1302
                    $counter++;
1303
                }
1304
            }
1305
        }
1306
1307
        if ('multiplechoiceother' === $type) {
1308
            if (empty($dataFromDatabase['answer_data'])) {
1309
                $params = [
1310
                    'question_id' => $form_content['question_id'],
1311
                    'survey_id' => $form_content['survey_id'],
1312
                    'option_text' => 'other',
1313
                    'value' => 0,
1314
                    'sort' => $counter,
1315
                ];
1316
                Database::insert($table, $params);
1317
            } else {
1318
                $params = [
1319
                    'option_text' => 'other',
1320
                    'value' => 0,
1321
                    'sort' => $counter,
1322
                ];
1323
                Database::update(
1324
                    $table,
1325
                    $params,
1326
                    [
1327
                        'question_id = ? AND survey_id = ? AND option_text = ?' => [
1328
                            $form_content['question_id'],
1329
                            $form_content['survey_id'],
1330
                            'other',
1331
                        ],
1332
                    ]
1333
                );
1334
            }
1335
        }
1336
    }
1337
1338
    /**
1339
     * This function deletes all the options of the questions of a given survey
1340
     * This function is normally only called when a survey is deleted.
1341
     *
1342
     * @param int $survey_id the id of the survey that has to be deleted
1343
     *
1344
     * @return true
1345
     *
1346
     * @author Patrick Cool <[email protected]>, Ghent University
1347
     *
1348
     * @version January 2007
1349
     */
1350
    public static function delete_all_survey_questions_options($survey_id, $shared = false)
1351
    {
1352
        // Table definitions
1353
        $table_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1354
        $course_id = api_get_course_int_id();
1355
        $course_condition = " c_id = $course_id AND ";
1356
        $sql = "DELETE FROM $table_survey_question_option
1357
                WHERE $course_condition survey_id='".intval($survey_id)."'";
1358
1359
        // Deleting the options of the survey questions
1360
        Database::query($sql);
1361
1362
        return true;
1363
    }
1364
1365
    /**
1366
     * SURVEY ANSWERS FUNCTIONS.
1367
     */
1368
1369
    /**
1370
     * This function deletes all the answers anyone has given on this survey
1371
     * This function is normally only called when a survey is deleted.
1372
     *
1373
     * @param $survey_id the id of the survey that has to be deleted
1374
     *
1375
     * @return true
1376
     *
1377
     * @todo write the function
1378
     *
1379
     * @author Patrick Cool <[email protected]>, Ghent University
1380
     *
1381
     * @version January 2007,december 2008
1382
     */
1383
    public static function delete_all_survey_answers($survey_id)
1384
    {
1385
        $course_id = api_get_course_int_id();
1386
        $table = Database::get_course_table(TABLE_SURVEY_ANSWER);
1387
        $survey_id = (int) $survey_id;
1388
        $sql = "DELETE FROM $table
1389
                WHERE c_id = $course_id AND survey_id = $survey_id";
1390
        Database::query($sql);
1391
1392
        return true;
1393
    }
1394
1395
    /**
1396
     * This function gets all the persons who have filled the survey.
1397
     *
1398
     * @param int $survey_id
1399
     *
1400
     * @return array
1401
     *
1402
     * @author Patrick Cool <[email protected]>, Ghent University
1403
     *
1404
     * @version February 2007
1405
     */
1406
    public static function get_people_who_filled_survey(
1407
        $survey_id,
1408
        $all_user_info = false,
1409
        $course_id = null
1410
    ) {
1411
        // Database table definition
1412
        $table_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1413
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1414
1415
        // Variable initialisation
1416
        $return = [];
1417
1418
        if (empty($course_id)) {
1419
            $course_id = api_get_course_int_id();
1420
        } else {
1421
            $course_id = (int) $course_id;
1422
        }
1423
1424
        $survey_id = (int) $survey_id;
1425
1426
        if ($all_user_info) {
1427
            $order_clause = api_sort_by_first_name()
1428
                ? ' ORDER BY user.firstname, user.lastname'
1429
                : ' ORDER BY user.lastname, user.firstname';
1430
            $sql = "SELECT DISTINCT
1431
			            answered_user.user as invited_user,
1432
			            user.firstname,
1433
			            user.lastname,
1434
			            user.id as user_id
1435
                    FROM $table_survey_answer answered_user
1436
                    LEFT JOIN $table_user as user
1437
                    ON answered_user.user = user.id
1438
                    WHERE
1439
                        survey_id= '".$survey_id."' ".
1440
                $order_clause;
1441
        } else {
1442
            $sql = "SELECT DISTINCT user FROM $table_survey_answer
1443
			        WHERE survey_id= '".$survey_id."'  ";
1444
1445
            if (api_get_configuration_value('survey_anonymous_show_answered')) {
1446
                $tblInvitation = Database::get_course_table(TABLE_SURVEY_INVITATION);
1447
                $tblSurvey = Database::get_course_table(TABLE_SURVEY);
1448
1449
                $sql = "SELECT i.user_id FROM $tblInvitation i
1450
                    INNER JOIN $tblSurvey s
1451
                    ON i.survey_code = s.code
1452
                    WHERE i.answered IS TRUE AND s.iid = $survey_id";
1453
            }
1454
        }
1455
1456
        $res = Database::query($sql);
1457
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1458
            if ($all_user_info) {
1459
                $userInfo = api_get_user_info($row['user_id']);
1460
                $row['user_info'] = $userInfo;
1461
                $return[] = $row;
1462
            } else {
1463
                $return[] = $row['user'];
1464
            }
1465
        }
1466
1467
        return $return;
1468
    }
1469
1470
    /**
1471
     * @return bool
1472
     */
1473
    public static function survey_generation_hash_available()
1474
    {
1475
        if (extension_loaded('mcrypt')) {
1476
            return true;
1477
        }
1478
1479
        return false;
1480
    }
1481
1482
    /**
1483
     * @param int $survey_id
1484
     * @param int $course_id
1485
     * @param int $session_id
1486
     * @param int $group_id
1487
     *
1488
     * @return string
1489
     */
1490
    public static function generate_survey_hash($survey_id, $course_id, $session_id, $group_id)
1491
    {
1492
        return hash(
1493
            'sha512',
1494
            api_get_configuration_value('security_key').'_'.$course_id.'_'.$session_id.'_'.$group_id.'_'.$survey_id
1495
        );
1496
    }
1497
1498
    /**
1499
     * @param int    $survey_id
1500
     * @param int    $course_id
1501
     * @param int    $session_id
1502
     * @param int    $group_id
1503
     * @param string $hash
1504
     *
1505
     * @return bool
1506
     */
1507
    public static function validate_survey_hash($survey_id, $course_id, $session_id, $group_id, $hash)
1508
    {
1509
        $generatedHash = self::generate_survey_hash($survey_id, $course_id, $session_id, $group_id);
1510
        if ($generatedHash == $hash) {
1511
            return true;
1512
        }
1513
1514
        return false;
1515
    }
1516
1517
    /**
1518
     * @param int $survey_id
1519
     * @param int $course_id
1520
     * @param int $session_id
1521
     * @param int $group_id
1522
     *
1523
     * @return string
1524
     */
1525
    public static function generate_survey_link(
1526
        $survey_id,
1527
        $course_id,
1528
        $session_id,
1529
        $group_id
1530
    ) {
1531
        $code = self::generate_survey_hash(
1532
            $survey_id,
1533
            $course_id,
1534
            $session_id,
1535
            $group_id
1536
        );
1537
1538
        return api_get_path(WEB_CODE_PATH).'survey/link.php?h='.$code.'&i='.$survey_id.'&c='.intval($course_id).'&s='
1539
            .intval($session_id).'&g='.$group_id;
1540
    }
1541
1542
    /**
1543
     * Check if the current user has mandatory surveys no-answered
1544
     * and redirect to fill the first found survey.
1545
     */
1546
    public static function protectByMandatory()
1547
    {
1548
        if (false !== strpos($_SERVER['SCRIPT_NAME'], 'fillsurvey.php')) {
1549
            return;
1550
        }
1551
1552
        $userId = api_get_user_id();
1553
        $courseId = api_get_course_int_id();
1554
        $sessionId = api_get_session_id();
1555
1556
        if (!$userId) {
1557
            return;
1558
        }
1559
1560
        if (!$courseId) {
1561
            return;
1562
        }
1563
1564
        try {
1565
            /** @var CSurveyInvitation $invitation */
1566
            $invitation = Database::getManager()
1567
                ->createQuery("
1568
                    SELECT i FROM ChamiloCourseBundle:CSurveyInvitation i
1569
                    INNER JOIN ChamiloCourseBundle:CSurvey s
1570
                        WITH (s.code = i.surveyCode AND s.cId = i.cId AND s.sessionId = i.sessionId)
1571
                    INNER JOIN ChamiloCoreBundle:ExtraFieldValues efv WITH efv.itemId = s.iid
1572
                    INNER JOIN ChamiloCoreBundle:ExtraField ef WITH efv.field = ef.id
1573
                    WHERE
1574
                        i.answered = 0 AND
1575
                        i.cId = :course AND
1576
                        i.user = :user AND
1577
                        i.sessionId = :session AND
1578
                        :now BETWEEN s.availFrom AND s.availTill AND
1579
                        ef.variable = :variable AND
1580
                        efv.value = 1 AND
1581
                        s.surveyType != 3
1582
                    ORDER BY s.availTill ASC
1583
                ")
1584
                ->setMaxResults(1)
1585
                ->setParameters([
1586
                    'course' => $courseId,
1587
                    'user' => $userId,
1588
                    'session' => $sessionId,
1589
                    'now' => new DateTime('UTC', new DateTimeZone('UTC')),
1590
                    'variable' => 'is_mandatory',
1591
                ])
1592
                ->getSingleResult();
1593
        } catch (Exception $e) {
1594
            $invitation = null;
1595
        }
1596
1597
        if (!$invitation) {
1598
            return;
1599
        }
1600
1601
        Display::addFlash(
1602
            Display::return_message(
1603
                get_lang(
1604
                    'A mandatory survey is waiting your answer. To enter the course, you must first complete the survey.'
1605
                ),
1606
                'warning'
1607
            )
1608
        );
1609
1610
        $url = SurveyUtil::generateFillSurveyLink(
1611
            $invitation->getInvitationCode(),
1612
            api_get_course_info(),
1613
            api_get_session_id()
1614
        );
1615
1616
        header('Location: '.$url);
1617
        exit;
1618
    }
1619
1620
    /**
1621
     * This function empty surveys (invitations and answers).
1622
     *
1623
     * @param int $surveyId id of the survey to empty
1624
     *
1625
     * @return bool
1626
     */
1627
    public static function emptySurveyFromId($surveyId)
1628
    {
1629
        // Database table definitions
1630
        $surveyInvitationTable = Database:: get_course_table(TABLE_SURVEY_INVITATION);
1631
        $surveyAnswerTable = Database:: get_course_table(TABLE_SURVEY_ANSWER);
1632
        $surveyTable = Database:: get_course_table(TABLE_SURVEY);
1633
        $surveyId = (int) $surveyId;
1634
        $surveyData = self::get_survey($surveyId);
1635
        if (empty($surveyData)) {
1636
            return false;
1637
        }
1638
1639
        $surveyCode = $surveyData['survey_code'];
1640
        $courseId = (int) $surveyData['c_id'];
1641
        $sessionId = (int) $surveyData['session_id'];
1642
1643
        $sql = "DELETE FROM $surveyInvitationTable
1644
                WHERE session_id = $sessionId AND c_id = $courseId AND survey_code = '$surveyCode' ";
1645
        Database::query($sql);
1646
1647
        $sql = "DELETE FROM $surveyAnswerTable
1648
                WHERE survey_id = $surveyId AND c_id = $courseId ";
1649
        Database::query($sql);
1650
1651
        $sql = "UPDATE $surveyTable
1652
                SET invited = 0, answered = 0
1653
                WHERE iid = $surveyId AND c_id = $courseId AND session_id = $sessionId ";
1654
        Database::query($sql);
1655
1656
        return true;
1657
    }
1658
1659
    /**
1660
     * Copy survey specifying course ID and session ID where will be copied.
1661
     *
1662
     * @param int $surveyId
1663
     * @param int $targetCourseId  target course id
1664
     * @param int $targetSessionId target session id
1665
     *
1666
     * @return bool|int when fails or return the new survey id
1667
     */
1668
    public static function copySurveySession($surveyId, $targetCourseId, $targetSessionId)
1669
    {
1670
        // Database table definitions
1671
        $surveyTable = Database::get_course_table(TABLE_SURVEY);
1672
        $surveyQuestionGroupTable = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
1673
        $surveyQuestionTable = Database::get_course_table(TABLE_SURVEY_QUESTION);
1674
        $surveyOptionsTable = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1675
        $surveyId = (int) $surveyId;
1676
        $targetCourseId = (int) $targetCourseId;
1677
        $targetSessionId = (int) $targetSessionId;
1678
1679
        $surveyData = self::get_survey($surveyId, 0, '', true);
1680
        if (empty($surveyData) || empty($targetCourseId)) {
1681
            return false;
1682
        }
1683
1684
        $originalCourseId = $surveyData['c_id'];
1685
        $originalSessionId = $surveyData['session_id'];
1686
1687
        $surveyData['code'] = self::generate_unique_code($surveyData['code']);
1688
        $surveyData['c_id'] = $targetCourseId;
1689
        $surveyData['session_id'] = $targetSessionId;
1690
        // Add a "Copy" suffix if copied inside the same course
1691
        if ($targetCourseId == $originalCourseId) {
1692
            $surveyData['title'] = $surveyData['title'].' '.get_lang('Copy');
1693
        }
1694
        unset($surveyData['iid']);
1695
        unset($surveyData['id']);
1696
1697
        $newSurveyId = Database::insert($surveyTable, $surveyData);
1698
1699
        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...
1700
            $sql = "SELECT * FROM $surveyQuestionGroupTable
1701
                    WHERE c_id = $originalCourseId AND survey_id = $surveyId";
1702
            $res = Database::query($sql);
1703
            while ($row = Database::fetch_array($res, 'ASSOC')) {
1704
                $params = [
1705
                    'c_id' => $targetCourseId,
1706
                    'name' => $row['name'],
1707
                    'description' => $row['description'],
1708
                    'survey_id' => $newSurveyId,
1709
                ];
1710
                $insertId = Database::insert($surveyQuestionGroupTable, $params);
1711
                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...
1712
                    $sql = "UPDATE $surveyQuestionGroupTable SET id = iid WHERE iid = $insertId";
1713
                    Database::query($sql);
1714
                    $group_id[$row['id']] = $insertId;
1715
                }
1716
            }
1717
1718
            // Get questions
1719
            $sql = "SELECT * FROM $surveyQuestionTable
1720
                    WHERE c_id = $originalCourseId AND survey_id = $surveyId";
1721
            $res = Database::query($sql);
1722
            while ($row = Database::fetch_array($res, 'ASSOC')) {
1723
                $params = [
1724
                    'c_id' => $targetCourseId,
1725
                    'survey_id' => $newSurveyId,
1726
                    'survey_question' => $row['survey_question'],
1727
                    'survey_question_comment' => $row['survey_question_comment'],
1728
                    'type' => $row['type'],
1729
                    'display' => $row['display'],
1730
                    'sort' => $row['sort'],
1731
                    'shared_question_id' => $row['shared_question_id'],
1732
                    'max_value' => $row['max_value'],
1733
                    'survey_group_pri' => $row['survey_group_pri'],
1734
                    'survey_group_sec1' => $row['survey_group_sec1'],
1735
                    'survey_group_sec2' => $row['survey_group_sec2'],
1736
                ];
1737
1738
                if (api_get_configuration_value('allow_required_survey_questions')) {
1739
                    if (isset($row['is_required'])) {
1740
                        $params['is_required'] = $row['is_required'];
1741
                    }
1742
                }
1743
1744
                $insertId = Database::insert($surveyQuestionTable, $params);
1745
                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...
1746
                    /*$sql = "UPDATE $surveyQuestionTable
1747
                            SET question_id = iid
1748
                            WHERE iid = $insertId";
1749
                    Database::query($sql);*/
1750
1751
                    $question_id[$row['question_id']] = $insertId;
1752
                }
1753
            }
1754
1755
            // Get questions options
1756
            $sql = "SELECT * FROM $surveyOptionsTable
1757
                    WHERE survey_id = $surveyId AND c_id = $originalCourseId";
1758
1759
            $res = Database::query($sql);
1760
            while ($row = Database::fetch_array($res, 'ASSOC')) {
1761
                $params = [
1762
                    'c_id' => $targetCourseId,
1763
                    '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...
1764
                    'survey_id' => $newSurveyId,
1765
                    'option_text' => $row['option_text'],
1766
                    'sort' => $row['sort'],
1767
                    'value' => $row['value'],
1768
                ];
1769
                $insertId = Database::insert($surveyOptionsTable, $params);
1770
                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...
1771
                    $sql = "UPDATE $surveyOptionsTable SET question_option_id = $insertId WHERE iid = $insertId";
1772
                    Database::query($sql);
1773
                }
1774
            }
1775
1776
            return $newSurveyId;
1777
        }
1778
1779
        return false;
1780
    }
1781
1782
    /**
1783
     * Copy/duplicate one question (into the same survey).
1784
     * Note: Relies on the question iid to find all necessary info.
1785
     *
1786
     * @param int $questionId
1787
     *
1788
     * @return int The new question's iid, or 0 on error
1789
     */
1790
    public static function copyQuestion($questionId)
1791
    {
1792
        if (empty($questionId)) {
1793
            return 0;
1794
        }
1795
        $questionId = (int) $questionId;
1796
        $questionTable = Database::get_course_table(TABLE_SURVEY_QUESTION);
1797
        $optionsTable = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1798
1799
        // Get questions
1800
        $sql = "SELECT * FROM $questionTable WHERE iid = $questionId";
1801
        $res = Database::query($sql);
1802
        if (false == $res) {
1803
            // Could not find this question
1804
            return 0;
1805
        }
1806
        $row = Database::fetch_array($res, 'ASSOC');
1807
        $params = [
1808
            //'c_id' => $row['c_id'],
1809
            'survey_id' => $row['survey_id'],
1810
            'survey_question' => trim($row['survey_question']),
1811
            'survey_question_comment' => $row['survey_question_comment'],
1812
            'type' => $row['type'],
1813
            'display' => $row['display'],
1814
            'shared_question_id' => $row['shared_question_id'],
1815
            'max_value' => $row['max_value'],
1816
            'survey_group_pri' => $row['survey_group_pri'],
1817
            'survey_group_sec1' => $row['survey_group_sec1'],
1818
            'survey_group_sec2' => $row['survey_group_sec2'],
1819
        ];
1820
        if (api_get_configuration_value('allow_required_survey_questions')) {
1821
            if (isset($row['is_required'])) {
1822
                $params['is_required'] = $row['is_required'];
1823
            }
1824
        }
1825
        // Get question position
1826
        $sqlSort = "SELECT max(sort) as sort FROM $questionTable
1827
                    WHERE survey_id = ".$row['survey_id'];
1828
        $resSort = Database::query($sqlSort);
1829
        $rowSort = Database::fetch_assoc($resSort);
1830
        $params['sort'] = $rowSort['sort'] + 1;
1831
        // Insert the new question
1832
        $insertId = Database::insert($questionTable, $params);
1833
        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...
1834
            return 0;
1835
        }
1836
1837
        // Get questions options
1838
        $sql = "SELECT * FROM $optionsTable WHERE question_id = $questionId";
1839
        $res = Database::query($sql);
1840
        while ($row = Database::fetch_assoc($res)) {
1841
            $params = [
1842
                //'c_id' => $row['c_id'],
1843
                'question_id' => $insertId,
1844
                'survey_id' => $row['survey_id'],
1845
                'option_text' => $row['option_text'],
1846
                'sort' => $row['sort'],
1847
                'value' => $row['value'],
1848
            ];
1849
            Database::insert($optionsTable, $params);
1850
        }
1851
1852
        return $insertId;
1853
    }
1854
1855
    /**
1856
     * @param array $surveyData
1857
     *
1858
     * @return bool
1859
     */
1860
    public static function removeMultiplicateQuestions(CSurvey $survey, $courseId)
1861
    {
1862
        $surveyId = $survey->getIid();
1863
        $courseId = (int) $courseId;
1864
1865
        if (empty($surveyId) || empty($courseId)) {
1866
            return false;
1867
        }
1868
1869
        $questions = $survey->getQuestions();
1870
        foreach ($questions as $question) {
1871
            // Questions marked with "geneated" were created using the "multiplicate" feature.
1872
            if ('generated' === $question->getSurveyQuestionComment()) {
1873
                self::deleteQuestion($question->getIid());
1874
            }
1875
        }
1876
    }
1877
1878
    /**
1879
     * @return bool
1880
     */
1881
    public static function multiplicateQuestions(CSurvey $survey, $courseId)
1882
    {
1883
        $surveyId = $survey->getIid();
1884
1885
        if (empty($surveyId)) {
1886
            return false;
1887
        }
1888
1889
        $questions = self::get_questions($surveyId);
1890
1891
        if (empty($questions)) {
1892
            return false;
1893
        }
1894
1895
        $extraFieldValue = new ExtraFieldValue('survey');
1896
        $groupData = $extraFieldValue->get_values_by_handler_and_field_variable($surveyId, 'group_id');
1897
        $groupId = null;
1898
        if ($groupData && !empty($groupData['value'])) {
1899
            $groupId = (int) $groupData['value'];
1900
        }
1901
1902
        if (null === $groupId) {
1903
            $obj = new UserGroupModel();
1904
            $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...
1905
            $classList = $obj->getUserGroupInCourse($options);
1906
1907
            $classToParse = [];
1908
            foreach ($classList as $class) {
1909
                $users = $obj->get_users_by_usergroup($class['id']);
1910
                if (empty($users)) {
1911
                    continue;
1912
                }
1913
                $classToParse[] = [
1914
                    'name' => $class['name'],
1915
                    'users' => $users,
1916
                ];
1917
            }
1918
            self::parseMultiplicateUserList($classToParse, $questions, $courseId, $survey, true);
1919
        } else {
1920
            $groupInfo = GroupManager::get_group_properties($groupId);
1921
            if (!empty($groupInfo)) {
1922
                $users = GroupManager::getStudents($groupInfo['iid'], true);
1923
                if (!empty($users)) {
1924
                    $users = array_column($users, 'id');
1925
                    self::parseMultiplicateUserList(
1926
                        [
1927
                            [
1928
                                'name' => $groupInfo['name'],
1929
                                'users' => $users,
1930
                            ],
1931
                        ],
1932
                        $questions,
1933
                        $courseId,
1934
                        $survey,
1935
                        false
1936
                    );
1937
                }
1938
            }
1939
        }
1940
1941
        return true;
1942
    }
1943
1944
    public static function parseMultiplicateUserList($itemList, $questions, $courseId, CSurvey $survey, $addClassNewPage = false)
1945
    {
1946
        if (empty($itemList) || empty($questions)) {
1947
            return false;
1948
        }
1949
1950
        $surveyId = $survey->getIid();
1951
        $classTag = '{{class_name}}';
1952
        $studentTag = '{{student_full_name}}';
1953
        $classCounter = 0;
1954
1955
        $newQuestionList = [];
1956
        foreach ($questions as $question) {
1957
            $newQuestionList[$question['sort']] = $question;
1958
        }
1959
        ksort($newQuestionList);
1960
1961
        $order = api_get_configuration_value('survey_duplicate_order_by_name');
1962
        foreach ($itemList as $class) {
1963
            $className = $class['name'];
1964
            $users = $class['users'];
1965
            $userInfoList = [];
1966
            foreach ($users as $userId) {
1967
                $userInfoList[] = api_get_user_info($userId);
1968
            }
1969
1970
            if ($order) {
1971
                usort(
1972
                    $userInfoList,
1973
                    function ($a, $b) {
1974
                        return $a['lastname'] > $b['lastname'];
1975
                    }
1976
                );
1977
            }
1978
1979
            foreach ($newQuestionList as $question) {
1980
                $text = $question['question'];
1981
                if (false !== strpos($text, $classTag)) {
1982
                    $replacedText = str_replace($classTag, $className, $text);
1983
                    $values = [
1984
                        'c_id' => $courseId,
1985
                        'question_comment' => 'generated',
1986
                        'type' => $question['type'],
1987
                        'display' => $question['horizontalvertical'],
1988
                        'horizontalvertical' => $question['horizontalvertical'],
1989
                        'question' => $replacedText,
1990
                        'survey_id' => $surveyId,
1991
                        'question_id' => 0,
1992
                        'shared_question_id' => 0,
1993
                        'answers' => $question['answers'] ?? null,
1994
                    ];
1995
                    self::saveQuestion($survey, $values, false);
1996
                    $classCounter++;
1997
                    continue;
1998
                }
1999
2000
                foreach ($userInfoList as $userInfo) {
2001
                    if (false !== strpos($text, $studentTag)) {
2002
                        $replacedText = str_replace($studentTag, $userInfo['complete_name'], $text);
2003
                        $values = [
2004
                            'c_id' => $courseId,
2005
                            'question_comment' => 'generated',
2006
                            'type' => $question['type'],
2007
                            'display' => $question['horizontalvertical'],
2008
                            'maximum_score' => $question['maximum_score'],
2009
                            'question' => $replacedText,
2010
                            'survey_id' => $surveyId,
2011
                            'question_id' => 0,
2012
                            'shared_question_id' => 0,
2013
                        ];
2014
2015
                        $answers = [];
2016
                        if (!empty($question['answers'])) {
2017
                            foreach ($question['answers'] as $answer) {
2018
                                $replacedText = str_replace($studentTag, $userInfo['complete_name'], $answer);
2019
                                $answers[] = $replacedText;
2020
                            }
2021
                        }
2022
                        $values['answers'] = $answers;
2023
                        self::saveQuestion($survey, $values, false);
2024
                    }
2025
                }
2026
2027
                if ($addClassNewPage && $classCounter < count($itemList)) {
2028
                    // Add end page
2029
                    $values = [
2030
                        'c_id' => $courseId,
2031
                        'question_comment' => 'generated',
2032
                        'type' => 'pagebreak',
2033
                        'display' => 'horizontal',
2034
                        'question' => get_lang('Question for next class'),
2035
                        'survey_id' => $surveyId,
2036
                        'question_id' => 0,
2037
                        'shared_question_id' => 0,
2038
                    ];
2039
                    self::saveQuestion($survey, $values, false);
2040
                }
2041
            }
2042
        }
2043
2044
        return true;
2045
    }
2046
2047
    public static function hasDependency(CSurvey $survey)
2048
    {
2049
        if (false === api_get_configuration_value('survey_question_dependency')) {
2050
            return false;
2051
        }
2052
2053
        $surveyId = $survey->getIid();
2054
2055
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
2056
        $sql = "SELECT COUNT(iid) count FROM $table
2057
                WHERE
2058
                    survey_id = $surveyId AND
2059
                    parent_option_id <> 0
2060
                LIMIT 1
2061
                ";
2062
        $result = Database::query($sql);
2063
        $row = Database::fetch_array($result);
2064
2065
        if ($row) {
2066
            return $row['count'] > 0;
2067
        }
2068
2069
        return false;
2070
    }
2071
2072
    /**
2073
     * @return int
2074
     */
2075
    public static function getCountPages(CSurvey $survey)
2076
    {
2077
        $surveyId = $survey->getIid();
2078
2079
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
2080
2081
        // pagebreak
2082
        $sql = "SELECT COUNT(iid) FROM $table
2083
                WHERE
2084
                    survey_question NOT LIKE '%{{%' AND
2085
                    type = 'pagebreak' AND
2086
                    survey_id = $surveyId";
2087
        $result = Database::query($sql);
2088
        $numberPageBreaks = Database::result($result, 0, 0);
2089
2090
        // No pagebreak
2091
        $sql = "SELECT COUNT(iid) FROM $table
2092
                WHERE
2093
                    survey_question NOT LIKE '%{{%' AND
2094
                    type != 'pagebreak' AND
2095
                    survey_id = $surveyId";
2096
        $result = Database::query($sql);
2097
        $countOfQuestions = Database::result($result, 0, 0);
2098
2099
        if (1 == $survey->getOneQuestionPerPage()) {
2100
            if (!empty($countOfQuestions)) {
2101
                return $countOfQuestions;
2102
            }
2103
2104
            return 1;
2105
        }
2106
2107
        if (empty($numberPageBreaks)) {
2108
            return 1;
2109
        }
2110
2111
        return $numberPageBreaks + 1;
2112
    }
2113
2114
    /**
2115
     * Check whether this survey has ended. If so, display message and exit this script.
2116
     */
2117
    public static function checkTimeAvailability(?CSurvey $survey)
2118
    {
2119
        if (null === $survey) {
2120
            api_not_allowed(true);
2121
        }
2122
2123
        $utcZone = new DateTimeZone('UTC');
2124
        $startDate = $survey->getAvailFrom();
2125
        $endDate = $survey->getAvailTill();
2126
        $currentDate = new DateTime('now', $utcZone);
2127
        $currentDate->modify('today');
2128
2129
        if ($currentDate < $startDate) {
2130
            api_not_allowed(
2131
                true,
2132
                Display:: return_message(
2133
                    get_lang('This survey is not yet available. Please try again later. Thank you.'),
2134
                    'warning',
2135
                    false
2136
                )
2137
            );
2138
        }
2139
2140
        if ($currentDate > $endDate) {
2141
            api_not_allowed(
2142
                true,
2143
                Display:: return_message(
2144
                    get_lang('Sorry, this survey is not available anymore. Thank you for trying.'),
2145
                    'warning',
2146
                    false
2147
                )
2148
            );
2149
        }
2150
    }
2151
2152
    /**
2153
     * @param int    $userId
2154
     * @param string $surveyCode
2155
     * @param int    $courseId
2156
     * @param int    $sessionId
2157
     * @param int    $groupId
2158
     *
2159
     * @return array|CSurveyInvitation[]
2160
     */
2161
    public static function getUserInvitationsForSurveyInCourse(
2162
        $userId,
2163
        $surveyCode,
2164
        $courseId,
2165
        $sessionId = 0,
2166
        $groupId = 0
2167
    ) {
2168
        $invitationRepo = Database::getManager()->getRepository(CSurveyInvitation::class);
2169
2170
        return $invitationRepo->findBy(
2171
            [
2172
                'user' => $userId,
2173
                'cId' => $courseId,
2174
                'sessionId' => $sessionId,
2175
                'groupId' => $groupId,
2176
                'surveyCode' => $surveyCode,
2177
            ],
2178
            ['invitationDate' => 'DESC']
2179
        );
2180
    }
2181
2182
    /**
2183
     * @param array $userInfo
2184
     * @param int   $answered (1 = answered 0 = not answered)
2185
     *
2186
     * @return string
2187
     */
2188
    public static function surveyReport($userInfo, $answered = 0)
2189
    {
2190
        $userId = isset($userInfo['user_id']) ? (int) $userInfo['user_id'] : 0;
2191
        $answered = (int) $answered;
2192
2193
        if (empty($userId)) {
2194
            return '';
2195
        }
2196
2197
        $em = Database::getManager();
2198
        $repo = $em->getRepository(CSurveyInvitation::class);
2199
        $repoSurvey = $em->getRepository(CSurvey::class);
2200
        $invitations = $repo->findBy(['user' => $userId, 'answered' => $answered]);
2201
        $mainUrl = api_get_path(WEB_CODE_PATH).'survey/survey.php?';
2202
        $content = '';
2203
2204
        if (empty($answered)) {
2205
            $content .= Display::page_subheader(get_lang('Unanswered'));
2206
        } else {
2207
            $content .= Display::page_subheader(get_lang('Answered'));
2208
        }
2209
2210
        if (!empty($invitations)) {
2211
            $table = new HTML_Table(['class' => 'table']);
2212
            $table->setHeaderContents(0, 0, get_lang('Survey name'));
2213
            $table->setHeaderContents(0, 1, get_lang('Course'));
2214
2215
            if (empty($answered)) {
2216
                $table->setHeaderContents(0, 2, get_lang('Survey').' - '.get_lang('End Date'));
2217
            }
2218
2219
            // Not answered
2220
            /** @var CSurveyInvitation $invitation */
2221
            $row = 1;
2222
            foreach ($invitations as $invitation) {
2223
                $course = $invitation->getCourse();
2224
                $courseId = $course->getId();
2225
                $courseCode = $course->getCode();
2226
                $sessionId = $invitation->getSession() ? $invitation->getSession()->getId() : 0;
2227
2228
                if (!empty($answered)) {
2229
                    // check if user is subscribed to the course/session
2230
                    if (empty($sessionId)) {
2231
                        $subscribe = CourseManager::is_user_subscribed_in_course($userId, $courseCode);
2232
                    } else {
2233
                        $subscribe = CourseManager::is_user_subscribed_in_course(
2234
                            $userId,
2235
                            $courseCode,
2236
                            true,
2237
                            $sessionId
2238
                        );
2239
                    }
2240
2241
                    // User is not subscribe skip!
2242
                    if (empty($subscribe)) {
2243
                        continue;
2244
                    }
2245
                }
2246
2247
                $survey = $invitation->getSurvey();
2248
                if (null === $survey) {
2249
                    continue;
2250
                }
2251
2252
                $url = $mainUrl.'survey_id='.$survey->getIid().'&cid='.$courseId.'&sid='.$sessionId;
2253
                $title = $survey->getTitle();
2254
                $title = Display::url($title, $url);
2255
                $courseTitle = $course->getTitle();
2256
                if (!empty($sessionId)) {
2257
                    $courseTitle .= ' ('.$invitation->getSession()->getName().')';
2258
                }
2259
2260
                $surveyData = self::get_survey($survey->getIid(), 0, $courseCode);
2261
                $table->setCellContents($row, 0, $title);
2262
                $table->setCellContents($row, 1, $courseTitle);
2263
2264
                if (empty($answered)) {
2265
                    $table->setHeaderContents(
2266
                        $row,
2267
                        2,
2268
                        api_get_local_time(
2269
                            $survey->getAvailTill(),
2270
                            null,
2271
                            null,
2272
                            true,
2273
                            false
2274
                        )
2275
                    );
2276
                }
2277
2278
                if (!empty($answered) && 0 == $survey->getAnonymous()) {
2279
                    $answers = SurveyUtil::displayCompleteReport(
2280
                        $surveyData,
2281
                        $userId,
2282
                        false,
2283
                        false,
2284
                        false
2285
                    );
2286
                    $table->setCellContents(++$row, 0, $answers);
2287
                    $table->setCellContents(++$row, 1, '');
2288
                }
2289
2290
                $row++;
2291
            }
2292
            $content .= $table->toHtml();
2293
        } else {
2294
            $content .= Display::return_message(get_lang('No data available'));
2295
        }
2296
2297
        return $content;
2298
    }
2299
2300
    public static function sendToTutors(CSurvey $survey)
2301
    {
2302
        $surveyId = $survey->getIid();
2303
2304
        $extraFieldValue = new ExtraFieldValue('survey');
2305
        $groupData = $extraFieldValue->get_values_by_handler_and_field_variable($surveyId, 'group_id');
2306
        if ($groupData && !empty($groupData['value'])) {
2307
            $groupInfo = GroupManager::get_group_properties($groupData['value']);
2308
            if ($groupInfo) {
2309
                $tutors = GroupManager::getTutors($groupInfo);
2310
                if (!empty($tutors)) {
2311
                    SurveyUtil::saveInviteMail(
2312
                        $survey,
2313
                        ' ',
2314
                        ' ',
2315
                        false
2316
                    );
2317
2318
                    foreach ($tutors as $tutor) {
2319
                        $subject = sprintf(get_lang('GroupSurveyX'), $groupInfo['name']);
2320
                        $content = sprintf(
2321
                            get_lang('HelloXGroupX'),
2322
                            $tutor['complete_name'],
2323
                            $groupInfo['name']
2324
                        );
2325
2326
                        SurveyUtil::saveInvitations(
2327
                            $survey,
2328
                            ['users' => $tutor['user_id']],
2329
                            $subject,
2330
                            $content,
2331
                            false,
2332
                            true,
2333
                            false,
2334
                            true
2335
                        );
2336
                    }
2337
                    Display::addFlash(Display::return_message(get_lang('Updated'), 'confirmation', false));
2338
                }
2339
                SurveyUtil::updateInvitedCount($survey);
2340
2341
                return true;
2342
            }
2343
        }
2344
2345
        return false;
2346
    }
2347
}
2348