Passed
Push — master ( 8d1f02...5a0940 )
by Julito
07:38
created

SurveyManager::checkTimeAvailability()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 30
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 21
nc 8
nop 1
dl 0
loc 30
rs 9.584
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 survey_invitation_id, survey_code
73
                FROM $table_survey_invitation WHERE user = '$user_id' AND c_id <> 0 ";
74
        $result = Database::query($sql);
75
        while ($row = Database::fetch_array($result, 'ASSOC')) {
76
            $survey_invitation_id = $row['survey_invitation_id'];
77
            $survey_code = $row['survey_code'];
78
            $sql2 = "DELETE FROM $table_survey_invitation
79
                    WHERE survey_invitation_id = '$survey_invitation_id' AND c_id <> 0";
80
            if (Database::query($sql2)) {
81
                $sql3 = "UPDATE $table_survey SET
82
                            invited = invited-1
83
                        WHERE c_id <> 0 AND code ='$survey_code'";
84
                Database::query($sql3);
85
            }
86
        }
87
    }
88
89
    /**
90
     * @param string $course_code
91
     * @param int    $session_id
92
     *
93
     * @return array
94
     * @assert ('') === false
95
     */
96
    public static function get_surveys($course_code, $session_id = 0)
97
    {
98
        if (empty($course_code)) {
99
            return false;
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
        $my_course_id = api_get_course_id();
142
143
        // Table definition
144
        if (!empty($course_code)) {
145
            $my_course_id = $course_code;
146
        } elseif (isset($_GET['course'])) {
147
            $my_course_id = Security::remove_XSS($_GET['course']);
148
        }
149
150
        $courseInfo = api_get_course_info($my_course_id);
151
        $survey_id = (int) $survey_id;
152
        $table_survey = Database::get_course_table(TABLE_SURVEY);
153
154
        if (0 != $shared) {
155
            $table_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
156
            $sql = "SELECT * FROM $table_survey
157
                    WHERE iid =' ".$survey_id."' ";
158
        } else {
159
            if (empty($courseInfo)) {
160
                return [];
161
            }
162
            $sql = "SELECT * FROM $table_survey
163
		            WHERE
164
		                iid = '".$survey_id."' AND
165
		                c_id = ".$courseInfo['real_id'];
166
        }
167
168
        $result = Database::query($sql);
169
        $return = [];
170
171
        if (Database::num_rows($result) > 0) {
172
            $return = Database::fetch_array($result, 'ASSOC');
173
            if ($simple_return) {
174
                return $return;
175
            }
176
            // We do this (temporarily) to have the array match the quickform elements immediately
177
            // idealiter the fields in the db match the quickform fields
178
            $return['survey_code'] = $return['code'];
179
            $return['survey_title'] = $return['title'];
180
            $return['survey_subtitle'] = $return['subtitle'];
181
            $return['survey_language'] = $return['lang'];
182
            $return['start_date'] = $return['avail_from'];
183
            $return['end_date'] = $return['avail_till'];
184
            $return['survey_share'] = $return['is_shared'];
185
            $return['survey_introduction'] = $return['intro'];
186
            $return['survey_thanks'] = $return['surveythanks'];
187
            $return['survey_type'] = $return['survey_type'];
188
            $return['one_question_per_page'] = $return['one_question_per_page'];
189
            $return['show_form_profile'] = $return['show_form_profile'];
190
            $return['input_name_list'] = isset($return['input_name_list']) ? $return['input_name_list'] : null;
191
            $return['shuffle'] = $return['shuffle'];
192
            $return['parent_id'] = $return['parent_id'];
193
            $return['survey_version'] = $return['survey_version'];
194
            $return['anonymous'] = $return['anonymous'];
195
            $return['c_id'] = isset($return['c_id']) ? $return['c_id'] : 0;
196
            $return['session_id'] = isset($return['session_id']) ? $return['session_id'] : 0;
197
        }
198
199
        return $return;
200
    }
201
202
    /**
203
     * @param string $code
204
     *
205
     * @return string
206
     */
207
    public static function generateSurveyCode($code)
208
    {
209
        return strtolower(CourseManager::generate_course_code($code));
210
    }
211
212
    /**
213
     * This function stores a survey in the database.
214
     *
215
     * @param array $values
216
     *
217
     * @return array $return the type of return message that has to be displayed and the message in it
218
     *
219
     * @author Patrick Cool <[email protected]>, Ghent University
220
     *
221
     * @version February 2007
222
     */
223
    public static function store_survey($values)
224
    {
225
        $_user = api_get_user_info();
226
        $course_id = api_get_course_int_id();
227
        $session_id = api_get_session_id();
228
        $courseCode = api_get_course_id();
229
        $table_survey = Database::get_course_table(TABLE_SURVEY);
230
        $shared_survey_id = '';
231
        $repo = Container::getSurveyRepository();
232
233
        if (!isset($values['survey_id'])) {
234
            // Check if the code doesn't soon exists in this language
235
            $sql = 'SELECT 1 FROM '.$table_survey.'
236
			        WHERE
237
			            c_id = '.$course_id.' AND
238
			            code = "'.Database::escape_string($values['survey_code']).'" AND
239
			            lang = "'.Database::escape_string($values['survey_language']).'"';
240
            $rs = Database::query($sql);
241
            if (Database::num_rows($rs) > 0) {
242
                Display::addFlash(
243
                    Display::return_message(
244
                        get_lang('This survey code soon exists in this language'),
245
                        'error'
246
                    )
247
                );
248
                $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...
249
                $return['id'] = isset($values['survey_id']) ? $values['survey_id'] : 0;
250
251
                return $return;
252
            }
253
254
            if (!isset($values['anonymous'])) {
255
                $values['anonymous'] = 0;
256
            }
257
258
            $values['anonymous'] = (int) $values['anonymous'];
259
260
            $survey = new CSurvey();
261
            $extraParams = [];
262
            if (0 == $values['anonymous']) {
263
                // Input_name_list
264
                $values['show_form_profile'] = isset($values['show_form_profile']) ? $values['show_form_profile'] : 0;
265
                $survey->setShowFormProfile($values['show_form_profile']);
266
267
                if (1 == $values['show_form_profile']) {
268
                    // Input_name_list
269
                    $fields = explode(',', $values['input_name_list']);
270
                    $field_values = '';
271
                    foreach ($fields as &$field) {
272
                        if ('' != $field) {
273
                            if ('' == $values[$field]) {
274
                                $values[$field] = 0;
275
                            }
276
                            $field_values .= $field.':'.$values[$field].'@';
277
                        }
278
                    }
279
                    $extraParams['form_fields'] = $field_values;
280
                } else {
281
                    $extraParams['form_fields'] = '';
282
                }
283
                $survey->setFormFields($extraParams['form_fields']);
284
            } else {
285
                $survey->setShowFormProfile(0);
286
                $survey->setFormFields(0);
287
            }
288
289
            $extraParams['one_question_per_page'] = isset($values['one_question_per_page']) ? $values['one_question_per_page'] : 0;
290
            $extraParams['shuffle'] = isset($values['shuffle']) ? $values['shuffle'] : 0;
291
292
            if (1 == $values['survey_type']) {
293
                $survey
294
                    ->setSurveyType(1)
295
                    ->setShuffle($values['shuffle'])
296
                    ->setOneQuestionPerPage($values['one_question_per_page'])
297
                    ->setParentId($values['parent_id'])
298
                ;
299
                // Logic for versioning surveys
300
                if (!empty($values['parent_id'])) {
301
                    $versionValue = '';
302
                    $sql = 'SELECT survey_version
303
                            FROM '.$table_survey.'
304
					        WHERE
305
					            c_id = '.$course_id.' AND
306
					            parent_id = '.intval($values['parent_id']).'
307
                            ORDER BY survey_version DESC
308
                            LIMIT 1';
309
                    $rs = Database::query($sql);
310
                    if (0 === Database::num_rows($rs)) {
311
                        $sql = 'SELECT survey_version FROM '.$table_survey.'
312
						        WHERE
313
						            c_id = '.$course_id.' AND
314
						            iid = '.intval($values['parent_id']);
315
                        $rs = Database::query($sql);
316
                        $getversion = Database::fetch_array($rs, 'ASSOC');
317
                        if (empty($getversion['survey_version'])) {
318
                            $versionValue = ++$getversion['survey_version'];
319
                        } else {
320
                            $versionValue = $getversion['survey_version'];
321
                        }
322
                    } else {
323
                        $row = Database::fetch_array($rs, 'ASSOC');
324
                        $pos = api_strpos($row['survey_version'], '.');
325
                        if (false === $pos) {
326
                            $row['survey_version'] = $row['survey_version'] + 1;
327
                            $versionValue = $row['survey_version'];
328
                        } else {
329
                            $getlast = explode('\.', $row['survey_version']);
330
                            $lastversion = array_pop($getlast);
331
                            $lastversion = $lastversion + 1;
332
                            $add = implode('.', $getlast);
333
                            if ('' != $add) {
334
                                $insertnewversion = $add.'.'.$lastversion;
335
                            } else {
336
                                $insertnewversion = $lastversion;
337
                            }
338
                            $versionValue = $insertnewversion;
339
                        }
340
                    }
341
                    $survey->setSurveyVersion($versionValue);
342
                }
343
            }
344
345
            $from = api_get_utc_datetime($values['start_date'].':00', true, true);
346
            $until = api_get_utc_datetime($values['end_date'].':59', true, true);
347
348
            $course = api_get_course_entity();
349
            $session = api_get_session_entity();
350
351
            $survey
352
                ->setCId($course_id)
353
                ->setCode(self::generateSurveyCode($values['survey_code']))
354
                ->setTitle($values['survey_title'])
355
                ->setSubtitle($values['survey_title'])
356
                //->setAuthor($_user['user_id'])
357
                ->setLang($values['survey_language'])
358
                ->setAvailFrom($from)
359
                ->setAvailTill($until)
360
                ->setIsShared($shared_survey_id)
361
                ->setTemplate('template')
362
                ->setIntro($values['survey_introduction'])
363
                ->setSurveyThanks($values['survey_thanks'])
364
                ->setAnonymous((string) $values['anonymous'])
365
                ->setSessionId(api_get_session_id())
366
                ->setVisibleResults((int) $values['visible_results'])
367
                ->setParent($course)
368
                ->addCourseLink($course, $session)
369
            ;
370
371
            $repo->create($survey);
372
373
            $survey_id = $survey->getIid();
374
            if ($survey_id > 0) {
375
                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

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

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

2379
                    self::/** @scrutinizer ignore-call */ 
2380
                          save_question($surveyData, $values, false);

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...
2380
                    $classCounter++;
2381
                    continue;
2382
                }
2383
2384
                foreach ($userInfoList as $userInfo) {
2385
                    if (false !== strpos($text, $studentTag)) {
2386
                        $replacedText = str_replace($studentTag, $userInfo['complete_name'], $text);
2387
                        $values = [
2388
                            'c_id' => $courseId,
2389
                            'question_comment' => 'generated',
2390
                            'type' => $question['type'],
2391
                            'display' => $question['horizontalvertical'],
2392
                            'maximum_score' => $question['maximum_score'],
2393
                            'question' => $replacedText,
2394
                            'survey_id' => $surveyId,
2395
                            'question_id' => 0,
2396
                            'shared_question_id' => 0,
2397
                        ];
2398
2399
                        $answers = [];
2400
                        if (!empty($question['answers'])) {
2401
                            foreach ($question['answers'] as $answer) {
2402
                                $replacedText = str_replace($studentTag, $userInfo['complete_name'], $answer);
2403
                                $answers[] = $replacedText;
2404
                            }
2405
                        }
2406
                        $values['answers'] = $answers;
2407
                        self::save_question($surveyData, $values, false);
2408
                    }
2409
                }
2410
2411
                if ($addClassNewPage && $classCounter < count($itemList)) {
2412
                    // Add end page
2413
                    $values = [
2414
                        'c_id' => $courseId,
2415
                        'question_comment' => 'generated',
2416
                        'type' => 'pagebreak',
2417
                        'display' => 'horizontal',
2418
                        'question' => get_lang('Question for next class'),
2419
                        'survey_id' => $surveyId,
2420
                        'question_id' => 0,
2421
                        'shared_question_id' => 0,
2422
                    ];
2423
                    self::save_question($surveyData, $values, false);
2424
                }
2425
            }
2426
        }
2427
2428
        return true;
2429
    }
2430
2431
    public static function hasDependency($survey)
2432
    {
2433
        if (false === api_get_configuration_value('survey_question_dependency')) {
2434
            return false;
2435
        }
2436
2437
        if (empty($survey)) {
2438
            return false;
2439
        }
2440
2441
        if (!isset($survey['survey_id'])) {
2442
            return false;
2443
        }
2444
2445
        $courseId = (int) $survey['c_id'];
2446
        $surveyId = (int) $survey['survey_id'];
2447
2448
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
2449
        $sql = "SELECT COUNT(iid) count FROM $table
2450
                WHERE
2451
                    c_id = $courseId AND
2452
                    survey_id = $surveyId AND
2453
                    parent_option_id <> 0
2454
                LIMIT 1
2455
                ";
2456
        $result = Database::query($sql);
2457
        $row = Database::fetch_array($result);
2458
2459
        if ($row) {
2460
            return $row['count'] > 0;
2461
        }
2462
2463
        return false;
2464
    }
2465
2466
    /**
2467
     * @param array $survey
2468
     *
2469
     * @return int
2470
     */
2471
    public static function getCountPages($survey)
2472
    {
2473
        if (empty($survey) || !isset($survey['iid'])) {
2474
            return 0;
2475
        }
2476
2477
        $courseId = (int) $survey['c_id'];
2478
        $surveyId = (int) $survey['iid'];
2479
2480
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
2481
2482
        // pagebreak
2483
        $sql = "SELECT COUNT(iid) FROM $table
2484
                WHERE
2485
                    survey_question NOT LIKE '%{{%' AND
2486
                    type = 'pagebreak' AND
2487
                    c_id = $courseId AND
2488
                    survey_id = $surveyId";
2489
        $result = Database::query($sql);
2490
        $numberPageBreaks = Database::result($result, 0, 0);
2491
2492
        // No pagebreak
2493
        $sql = "SELECT COUNT(iid) FROM $table
2494
                WHERE
2495
                    survey_question NOT LIKE '%{{%' AND
2496
                    type != 'pagebreak' AND
2497
                    c_id = $courseId AND
2498
                    survey_id = $surveyId";
2499
        $result = Database::query($sql);
2500
        $countOfQuestions = Database::result($result, 0, 0);
2501
2502
        if (1 == $survey['one_question_per_page']) {
2503
            if (!empty($countOfQuestions)) {
2504
                return $countOfQuestions;
2505
            }
2506
2507
            return 1;
2508
        }
2509
2510
        if (empty($numberPageBreaks)) {
2511
            return 1;
2512
        }
2513
2514
        return $numberPageBreaks + 1;
2515
    }
2516
2517
    /**
2518
     * Check whether this survey has ended. If so, display message and exit rhis script.
2519
     *
2520
     * @param array $surveyData Survey data
2521
     */
2522
    public static function checkTimeAvailability($surveyData)
2523
    {
2524
        if (empty($surveyData)) {
2525
            api_not_allowed(true);
2526
        }
2527
2528
        $utcZone = new DateTimeZone('UTC');
2529
        $startDate = new DateTime($surveyData['start_date'], $utcZone);
2530
        $endDate = new DateTime($surveyData['end_date'], $utcZone);
2531
        $currentDate = new DateTime('now', $utcZone);
2532
        $currentDate->modify('today');
2533
2534
        if ($currentDate < $startDate) {
2535
            api_not_allowed(
2536
                true,
2537
                Display:: return_message(
2538
                    get_lang('This survey is not yet available. Please try again later. Thank you.'),
2539
                    'warning',
2540
                    false
2541
                )
2542
            );
2543
        }
2544
2545
        if ($currentDate > $endDate) {
2546
            api_not_allowed(
2547
                true,
2548
                Display:: return_message(
2549
                    get_lang('Sorry, this survey is not available anymore. Thank you for trying.'),
2550
                    'warning',
2551
                    false
2552
                )
2553
            );
2554
        }
2555
    }
2556
2557
    /**
2558
     * @param int    $userId
2559
     * @param string $surveyCode
2560
     * @param int    $courseId
2561
     * @param int    $sessionId
2562
     * @param int    $groupId
2563
     *
2564
     * @return array|CSurveyInvitation[]
2565
     */
2566
    public static function getUserInvitationsForSurveyInCourse(
2567
        $userId,
2568
        $surveyCode,
2569
        $courseId,
2570
        $sessionId = 0,
2571
        $groupId = 0
2572
    ) {
2573
        $invitationRepo = Database::getManager()->getRepository(CSurveyInvitation::class);
2574
2575
        return $invitationRepo->findBy(
2576
            [
2577
                'user' => $userId,
2578
                'cId' => $courseId,
2579
                'sessionId' => $sessionId,
2580
                'groupId' => $groupId,
2581
                'surveyCode' => $surveyCode,
2582
            ],
2583
            ['invitationDate' => 'DESC']
2584
        );
2585
    }
2586
2587
    /**
2588
     * @param array $userInfo
2589
     * @param int   $answered (1 = answered 0 = not answered)
2590
     *
2591
     * @return string
2592
     */
2593
    public static function surveyReport($userInfo, $answered = 0)
2594
    {
2595
        $userId = isset($userInfo['user_id']) ? (int) $userInfo['user_id'] : 0;
2596
        $answered = (int) $answered;
2597
2598
        if (empty($userId)) {
2599
            return '';
2600
        }
2601
2602
        $em = Database::getManager();
2603
        $repo = $em->getRepository(CSurveyInvitation::class);
2604
        $repoSurvey = $em->getRepository(CSurvey::class);
2605
        $invitations = $repo->findBy(['user' => $userId, 'answered' => $answered]);
2606
        $mainUrl = api_get_path(WEB_CODE_PATH).'survey/survey.php?';
2607
        $content = '';
2608
2609
        if (empty($answered)) {
2610
            $content .= Display::page_subheader(get_lang('Unanswered'));
2611
        } else {
2612
            $content .= Display::page_subheader(get_lang('Answered'));
2613
        }
2614
2615
        if (!empty($invitations)) {
2616
            $table = new HTML_Table(['class' => 'table']);
2617
            $table->setHeaderContents(0, 0, get_lang('Survey name'));
2618
            $table->setHeaderContents(0, 1, get_lang('Course'));
2619
2620
            if (empty($answered)) {
2621
                $table->setHeaderContents(0, 2, get_lang('Survey').' - '.get_lang('End Date'));
2622
            }
2623
2624
            // Not answered
2625
            /** @var CSurveyInvitation $invitation */
2626
            $row = 1;
2627
            foreach ($invitations as $invitation) {
2628
                $courseId = $invitation->getCId();
2629
                $courseInfo = api_get_course_info_by_id($courseId);
2630
2631
                $courseCode = $courseInfo['code'];
2632
                if (empty($courseInfo)) {
2633
                    continue;
2634
                }
2635
                $sessionId = $invitation->getSessionId();
2636
2637
                if (!empty($answered)) {
2638
                    // check if user is subscribed to the course/session
2639
                    if (empty($sessionId)) {
2640
                        $subscribe = CourseManager::is_user_subscribed_in_course($userId, $courseCode);
2641
                    } else {
2642
                        $subscribe = CourseManager::is_user_subscribed_in_course(
2643
                            $userId,
2644
                            $courseCode,
2645
                            true,
2646
                            $sessionId
2647
                        );
2648
                    }
2649
2650
                    // User is not subscribe skip!
2651
                    if (empty($subscribe)) {
2652
                        continue;
2653
                    }
2654
                }
2655
2656
                $surveyCode = $invitation->getSurveyCode();
2657
2658
                $survey = $repoSurvey->findOneBy([
2659
                    'cId' => $courseId,
2660
                    'sessionId' => $sessionId,
2661
                    'code' => $surveyCode,
2662
                ]);
2663
2664
                if (empty($survey)) {
2665
                    continue;
2666
                }
2667
2668
                $url = $mainUrl.'survey_id='.$survey->getIid().'&cid='.$courseId.'&sid='.$sessionId;
2669
                $title = $survey->getTitle();
2670
                $title = Display::url($title, $url);
2671
2672
                if (!empty($sessionId)) {
2673
                    $sessionInfo = api_get_session_info($sessionId);
2674
                    $courseInfo['name'] .= ' ('.$sessionInfo['name'].')';
2675
                }
2676
2677
                $surveyData = self::get_survey($survey->getIid(), 0, $courseCode);
2678
                $table->setCellContents($row, 0, $title);
2679
                $table->setCellContents($row, 1, $courseInfo['name']);
2680
2681
                if (empty($answered)) {
2682
                    $table->setHeaderContents(
2683
                        $row,
2684
                        2,
2685
                        api_get_local_time(
2686
                            $survey->getAvailTill(),
2687
                            null,
2688
                            null,
2689
                            true,
2690
                            false
2691
                        )
2692
                    );
2693
                }
2694
2695
                if (!empty($answered) && 0 == $surveyData['anonymous']) {
2696
                    $answers = SurveyUtil::displayCompleteReport(
2697
                        $surveyData,
2698
                        $userId,
2699
                        false,
2700
                        false,
2701
                        false
2702
                    );
2703
                    $table->setCellContents(++$row, 0, $answers);
2704
                    $table->setCellContents(++$row, 1, '');
2705
                }
2706
2707
                $row++;
2708
            }
2709
            $content .= $table->toHtml();
2710
        } else {
2711
            $content .= Display::return_message(get_lang('No data available'));
2712
        }
2713
2714
        return $content;
2715
    }
2716
2717
    public static function sendToTutors($surveyId)
2718
    {
2719
        $survey = Database::getManager()->getRepository(CSurvey::class)->find($surveyId);
2720
        if (null === $survey) {
2721
            return false;
2722
        }
2723
2724
        $extraFieldValue = new ExtraFieldValue('survey');
2725
        $groupData = $extraFieldValue->get_values_by_handler_and_field_variable($surveyId, 'group_id');
2726
        if ($groupData && !empty($groupData['value'])) {
2727
            $groupInfo = GroupManager::get_group_properties($groupData['value']);
2728
            if ($groupInfo) {
2729
                $tutors = GroupManager::getTutors($groupInfo);
2730
                if (!empty($tutors)) {
2731
                    SurveyUtil::saveInviteMail(
2732
                        $survey,
2733
                        ' ',
2734
                        ' ',
2735
                        false
2736
                    );
2737
2738
                    foreach ($tutors as $tutor) {
2739
                        $subject = sprintf(get_lang('GroupSurveyX'), $groupInfo['name']);
2740
                        $content = sprintf(
2741
                            get_lang('HelloXGroupX'),
2742
                            $tutor['complete_name'],
2743
                            $groupInfo['name']
2744
                        );
2745
2746
                        SurveyUtil::saveInvitations(
2747
                            $surveyId,
2748
                            ['users' => $tutor['user_id']],
2749
                            $subject,
2750
                            $content,
2751
                            false,
2752
                            true,
2753
                            false,
2754
                            true
2755
                        );
2756
                    }
2757
                    Display::addFlash(Display::return_message(get_lang('Updated'), 'confirmation', false));
2758
                }
2759
                SurveyUtil::update_count_invited($survey->getCode());
2760
2761
                return true;
2762
            }
2763
        }
2764
2765
        return false;
2766
    }
2767
}
2768