Passed
Push — 1.11.x ( 1068fc...2c4fea )
by Angel Fernando Quiroz
10:34 queued 11s
created

CourseBuilder::build_survey_questions()   B

Complexity

Conditions 7
Paths 28

Size

Total Lines 41
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 30
c 0
b 0
f 0
nc 28
nop 1
dl 0
loc 41
rs 8.5066
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
namespace Chamilo\CourseBundle\Component\CourseCopy;
5
6
use Category;
7
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Announcement;
8
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Asset;
9
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Attendance;
10
use Chamilo\CourseBundle\Component\CourseCopy\Resources\CalendarEvent;
11
use Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseCopyLearnpath;
12
use Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseCopyTestCategory;
13
use Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseDescription;
14
use Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseSession;
15
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Document;
16
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Forum;
17
use Chamilo\CourseBundle\Component\CourseCopy\Resources\ForumCategory;
18
use Chamilo\CourseBundle\Component\CourseCopy\Resources\ForumPost;
19
use Chamilo\CourseBundle\Component\CourseCopy\Resources\ForumTopic;
20
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Glossary;
21
use Chamilo\CourseBundle\Component\CourseCopy\Resources\GradeBookBackup;
22
use Chamilo\CourseBundle\Component\CourseCopy\Resources\LearnPathCategory;
23
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Link;
24
use Chamilo\CourseBundle\Component\CourseCopy\Resources\LinkCategory;
25
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Quiz;
26
use Chamilo\CourseBundle\Component\CourseCopy\Resources\QuizQuestion;
27
use Chamilo\CourseBundle\Component\CourseCopy\Resources\QuizQuestionOption;
28
use Chamilo\CourseBundle\Component\CourseCopy\Resources\ScormDocument;
29
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Survey;
30
use Chamilo\CourseBundle\Component\CourseCopy\Resources\SurveyQuestion;
31
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Thematic;
32
use Chamilo\CourseBundle\Component\CourseCopy\Resources\ToolIntro;
33
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Wiki;
34
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Work;
35
use Chamilo\CourseBundle\Component\CourseCopy\Resources\XapiTool;
36
use Chamilo\CourseBundle\Entity\CLpCategory;
37
use CourseManager;
38
use Database;
39
use Link as LinkManager;
40
use TestCategory;
41
42
/**
43
 * Class CourseBuilder
44
 * Builds a course-object from a Chamilo-course.
45
 *
46
 * @author Bart Mollet <[email protected]>
47
 *
48
 * @package chamilo.backup
49
 */
50
class CourseBuilder
51
{
52
    /** @var Course */
53
    public $course;
54
55
    /* With this array you can filter the tools you want to be parsed by
56
    default all tools are included */
57
    public $tools_to_build = [
58
        'announcements',
59
        'attendance',
60
        'course_descriptions',
61
        'documents',
62
        'events',
63
        'forum_category',
64
        'forums',
65
        'forum_topics',
66
        'glossary',
67
        'quizzes',
68
        'test_category',
69
        'learnpath_category',
70
        'learnpaths',
71
        'links',
72
        'surveys',
73
        'tool_intro',
74
        'thematic',
75
        'wiki',
76
        'works',
77
        'gradebook',
78
    ];
79
80
    public $toolToName = [
81
        'announcements' => RESOURCE_ANNOUNCEMENT,
82
        'attendance' => RESOURCE_ATTENDANCE,
83
        'course_descriptions' => RESOURCE_COURSEDESCRIPTION,
84
        'documents' => RESOURCE_DOCUMENT,
85
        'events' => RESOURCE_EVENT,
86
        'forum_category' => RESOURCE_FORUMCATEGORY,
87
        'forums' => RESOURCE_FORUM,
88
        'forum_topics' => RESOURCE_FORUMTOPIC,
89
        'glossary' => RESOURCE_GLOSSARY,
90
        'quizzes' => RESOURCE_QUIZ,
91
        'test_category' => RESOURCE_TEST_CATEGORY,
92
        'learnpath_category' => RESOURCE_LEARNPATH_CATEGORY,
93
        'learnpaths' => RESOURCE_LEARNPATH,
94
        'links' => RESOURCE_LINK,
95
        'surveys' => RESOURCE_SURVEY,
96
        'tool_intro' => RESOURCE_TOOL_INTRO,
97
        'thematic' => RESOURCE_THEMATIC,
98
        'wiki' => RESOURCE_WIKI,
99
        'works' => RESOURCE_WORK,
100
        'gradebook' => RESOURCE_GRADEBOOK,
101
    ];
102
103
    /* With this array you can filter wich elements of the tools are going
104
    to be added in the course obj (only works with LPs) */
105
    public $specific_id_list = [];
106
    public $documentsAddedInText = [];
107
    public $itemListToAdd = [];
108
109
    public $isXapiEnabled = false;
110
111
    /**
112
     * Create a new CourseBuilder.
113
     *
114
     * @param string $type
115
     * @param null   $course
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $course is correct as it would always require null to be passed?
Loading history...
116
     */
117
    public function __construct($type = '', $course = null)
118
    {
119
        $_course = api_get_course_info();
120
121
        if (!empty($course['official_code'])) {
122
            $_course = $course;
123
        }
124
125
        $this->course = new Course();
126
        $this->course->code = $_course['code'];
127
        $this->course->type = $type;
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
128
        $this->course->path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/';
129
        $this->course->backup_path = api_get_path(SYS_COURSE_PATH).$_course['path'];
130
        $this->course->encoding = api_get_system_encoding();
131
        $this->course->info = $_course;
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
132
    }
133
134
    /**
135
     * @param array $list
136
     */
137
    public function addDocumentList($list)
138
    {
139
        foreach ($list as $item) {
140
            if (!in_array($item[0], $this->documentsAddedInText)) {
141
                $this->documentsAddedInText[$item[0]] = $item;
142
            }
143
        }
144
    }
145
146
    /**
147
     * @param string $text
148
     */
149
    public function findAndSetDocumentsInText($text)
150
    {
151
        $documentList = \DocumentManager::get_resources_from_source_html($text);
152
        $this->addDocumentList($documentList);
153
    }
154
155
    /**
156
     * Parse documents added in the documentsAddedInText variable.
157
     */
158
    public function restoreDocumentsFromList()
159
    {
160
        if (!empty($this->documentsAddedInText)) {
161
            $list = [];
162
            $courseInfo = api_get_course_info();
163
            foreach ($this->documentsAddedInText as $item) {
164
                // Get information about source url
165
                $url = $item[0]; // url
166
                $scope = $item[1]; // scope (local, remote)
167
                $type = $item[2]; // type (rel, abs, url)
168
169
                $origParseUrl = parse_url($url);
170
                $realOrigPath = isset($origParseUrl['path']) ? $origParseUrl['path'] : null;
171
172
                if ($scope == 'local') {
173
                    if ($type == 'abs' || $type == 'rel') {
174
                        $documentFile = strstr($realOrigPath, 'document');
175
                        if (strpos($realOrigPath, $documentFile) !== false) {
176
                            $documentFile = str_replace('document', '', $documentFile);
177
                            $itemDocumentId = \DocumentManager::get_document_id($courseInfo, $documentFile);
178
                            // Document found! Add it to the list
179
                            if ($itemDocumentId) {
180
                                $list[] = $itemDocumentId;
181
                            }
182
                        }
183
                    }
184
                }
185
            }
186
187
            $this->build_documents(
188
                api_get_session_id(),
189
                api_get_course_int_id(),
190
                true,
191
                $list
192
            );
193
        }
194
    }
195
196
    /**
197
     * @param array $array
198
     */
199
    public function set_tools_to_build($array)
200
    {
201
        $this->tools_to_build = $array;
202
    }
203
204
    /**
205
     * @param array $array
206
     */
207
    public function set_tools_specific_id_list($array)
208
    {
209
        $this->specific_id_list = $array;
210
    }
211
212
    /**
213
     * Get the created course.
214
     *
215
     * @return course The course
216
     */
217
    public function get_course()
218
    {
219
        return $this->course;
220
    }
221
222
    /**
223
     * Build the course-object.
224
     *
225
     * @param int    $session_id
226
     * @param string $courseCode
227
     * @param bool   $withBaseContent   true if you want to get the elements that exists in the course and
228
     *                                  in the session, (session_id = 0 or session_id = X)
229
     * @param array  $parseOnlyToolList
230
     * @param array  $toolsFromPost
231
     *
232
     * @return Course The course object structure
233
     */
234
    public function build(
235
        $session_id = 0,
236
        $courseCode = '',
237
        $withBaseContent = false,
238
        $parseOnlyToolList = [],
239
        $toolsFromPost = []
240
    ) {
241
        $course = api_get_course_info($courseCode);
242
        $courseId = $course['real_id'];
243
244
        $xapiEnabled = \XApiPlugin::create()->isEnabled();
245
        if ($xapiEnabled) {
246
            $this->tools_to_build[] = 'xapi_tool';
247
            $this->toolToName['xapi_tool'] = RESOURCE_XAPI_TOOL;
248
            $this->isXapiEnabled = $xapiEnabled;
249
        }
250
251
        foreach ($this->tools_to_build as $tool) {
252
            if (!empty($parseOnlyToolList) && !in_array($this->toolToName[$tool], $parseOnlyToolList)) {
253
                continue;
254
            }
255
            $function_build = 'build_'.$tool;
256
            $specificIdList = isset($this->specific_id_list[$tool]) ? $this->specific_id_list[$tool] : null;
257
            $buildOrphanQuestions = true;
258
            if ($tool === 'quizzes') {
259
                if (!empty($toolsFromPost['quiz'])) {
260
                    $specificIdList = array_keys($toolsFromPost['quiz']);
261
                }
262
                if (!isset($toolsFromPost[RESOURCE_QUIZ][-1])) {
263
                    $buildOrphanQuestions = false;
264
                }
265
266
                // Force orphan load
267
                if ($this->course->type === 'complete') {
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
268
                    $buildOrphanQuestions = true;
269
                }
270
271
                $this->build_quizzes(
272
                    $session_id,
273
                    $courseId,
274
                    $withBaseContent,
275
                    $specificIdList,
276
                    $buildOrphanQuestions
277
                );
278
            } else {
279
                if (!empty($toolsFromPost[RESOURCE_LEARNPATH]) && 'learnpaths' === $tool) {
280
                    $specificIdList = array_keys($toolsFromPost[RESOURCE_LEARNPATH]);
281
                }
282
                $this->$function_build(
283
                    $session_id,
284
                    $courseId,
285
                    $withBaseContent,
286
                    $specificIdList
287
                );
288
            }
289
        }
290
291
        // Add asset
292
        if ($course['course_image_source'] && basename($course['course_image_source']) !== 'course.png') {
293
            // Add course image courses/XXX/course-pic85x85.png
294
            $asset = new Asset(
295
                $course['course_image_source'],
296
                basename($course['course_image_source']),
297
                basename($course['course_image_source'])
298
            );
299
            $this->course->add_resource($asset);
300
301
            $asset = new Asset(
302
                $course['course_image_large_source'],
303
                basename($course['course_image_large_source']),
304
                basename($course['course_image_large_source'])
305
            );
306
            $this->course->add_resource($asset);
307
        }
308
309
        // Once we've built the resources array a bit more, try to get items
310
        // from the item_property table and order them in the "resources" array
311
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
312
        foreach ($this->course->resources as $type => $resources) {
313
            if (!empty($parseOnlyToolList) && !in_array($this->toolToName[$tool], $parseOnlyToolList)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tool does not seem to be defined for all execution paths leading up to this point.
Loading history...
314
                continue;
315
            }
316
            foreach ($resources as $id => $resource) {
317
                if ($resource) {
318
                    $tool = $resource->get_tool();
319
                    if ($tool != null) {
320
                        $sql = "SELECT * FROM $table
321
                                WHERE
322
                                    c_id = $courseId AND
323
                                    tool = '".$tool."' AND
324
                                    ref = '".$resource->get_id()."'";
325
                        $res = Database::query($sql);
326
                        $properties = [];
327
                        while ($property = Database::fetch_array($res)) {
328
                            $properties[] = $property;
329
                        }
330
                        $this->course->resources[$type][$id]->item_properties = $properties;
331
                    }
332
                }
333
            }
334
        }
335
336
        return $this->course;
337
    }
338
339
    /**
340
     * Build the documents.
341
     *
342
     * @param int   $session_id
343
     * @param int   $courseId
344
     * @param bool  $withBaseContent
345
     * @param array $idList
346
     */
347
    public function build_documents(
348
        $session_id = 0,
349
        $courseId = 0,
350
        $withBaseContent = false,
351
        $idList = []
352
    ) {
353
        $table_doc = Database::get_course_table(TABLE_DOCUMENT);
354
        $table_prop = Database::get_course_table(TABLE_ITEM_PROPERTY);
355
356
        // Remove chat_files, shared_folder, exercises files
357
        $avoid_paths = "
358
                         path NOT LIKE '/shared_folder%' AND
359
                         path NOT LIKE '/chat_files%' AND
360
                         path NOT LIKE '/../exercises/%'
361
                         ";
362
        $documentCondition = '';
363
        if (!empty($idList)) {
364
            $idList = array_unique($idList);
365
            $idList = array_map('intval', $idList);
366
            $documentCondition = ' d.iid IN ("'.implode('","', $idList).'") AND ';
367
        }
368
369
        if (!empty($courseId) && !empty($session_id)) {
370
            $session_id = (int) $session_id;
371
            if ($withBaseContent) {
372
                $session_condition = api_get_session_condition(
373
                    $session_id,
374
                    true,
375
                    true,
376
                    'd.session_id'
377
                );
378
            } else {
379
                $session_condition = api_get_session_condition(
380
                    $session_id,
381
                    true,
382
                    false,
383
                    'd.session_id'
384
                );
385
            }
386
387
            if (!empty($this->course->type) && $this->course->type == 'partial') {
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
388
                $sql = "SELECT d.iid, d.path, d.comment, d.title, d.filetype, d.size
389
                        FROM $table_doc d
390
                        INNER JOIN $table_prop p
391
                        ON (p.ref = d.id AND d.c_id = p.c_id)
392
                        WHERE
393
                            d.c_id = $courseId AND
394
                            p.c_id = $courseId AND
395
                            tool = '".TOOL_DOCUMENT."' AND
396
                            $documentCondition
397
                            p.visibility != 2 AND
398
                            path NOT LIKE '/images/gallery%' AND
399
                            $avoid_paths
400
                            $session_condition
401
                        ORDER BY path";
402
            } else {
403
                $sql = "SELECT d.iid, d.path, d.comment, d.title, d.filetype, d.size
404
                        FROM $table_doc d
405
                        INNER JOIN $table_prop p
406
                        ON (p.ref = d.id AND d.c_id = p.c_id)
407
                        WHERE
408
                            d.c_id = $courseId AND
409
                            p.c_id = $courseId AND
410
                            tool = '".TOOL_DOCUMENT."' AND
411
                            $documentCondition
412
                            $avoid_paths AND
413
                            p.visibility != 2 $session_condition
414
                        ORDER BY path";
415
            }
416
417
            $db_result = Database::query($sql);
418
            while ($obj = Database::fetch_object($db_result)) {
419
                $doc = new Document(
420
                    $obj->iid,
421
                    $obj->path,
422
                    $obj->comment,
423
                    $obj->title,
424
                    $obj->filetype,
425
                    $obj->size
426
                );
427
                $this->course->add_resource($doc);
428
            }
429
        } else {
430
            if (!empty($this->course->type) && $this->course->type == 'partial') {
431
                $sql = "SELECT d.iid, d.path, d.comment, d.title, d.filetype, d.size
432
                        FROM $table_doc d
433
                        INNER JOIN $table_prop p
434
                        ON (p.ref = d.id AND d.c_id = p.c_id)
435
                        WHERE
436
                            d.c_id = $courseId AND
437
                            p.c_id = $courseId AND
438
                            tool = '".TOOL_DOCUMENT."' AND
439
                            $documentCondition
440
                            p.visibility != 2 AND
441
                            path NOT LIKE '/images/gallery%' AND
442
                            $avoid_paths AND
443
                            (d.session_id = 0 OR d.session_id IS NULL)
444
                        ORDER BY path";
445
            } else {
446
                $sql = "SELECT d.iid, d.path, d.comment, d.title, d.filetype, d.size
447
                        FROM $table_doc d
448
                        INNER JOIN $table_prop p
449
                        ON (p.ref = d.id AND d.c_id = p.c_id)
450
                        WHERE
451
                            d.c_id = $courseId AND
452
                            p.c_id = $courseId AND
453
                            tool = '".TOOL_DOCUMENT."' AND
454
                            $documentCondition
455
                            p.visibility != 2 AND
456
                            $avoid_paths AND
457
                            (d.session_id = 0 OR d.session_id IS NULL)
458
                        ORDER BY path";
459
            }
460
461
            $result = Database::query($sql);
462
            while ($obj = Database::fetch_object($result)) {
463
                $doc = new Document(
464
                    $obj->iid,
465
                    $obj->path,
466
                    $obj->comment,
467
                    $obj->title,
468
                    $obj->filetype,
469
                    $obj->size
470
                );
471
                $this->course->add_resource($doc);
472
            }
473
        }
474
    }
475
476
    /**
477
     * Build the forums.
478
     *
479
     * @param int   $session_id      Internal session ID
480
     * @param int   $courseId        Internal course ID
481
     * @param bool  $withBaseContent Whether to include content from the course without session or not
482
     * @param array $idList          If you want to restrict the structure to only the given IDs
483
     */
484
    public function build_forums(
485
        $session_id = 0,
486
        $courseId = 0,
487
        $withBaseContent = false,
488
        $idList = []
489
    ) {
490
        $table = Database::get_course_table(TABLE_FORUM);
491
        $sessionCondition = api_get_session_condition(
492
            $session_id,
493
            true,
494
            $withBaseContent
495
        );
496
497
        $idCondition = '';
498
        if (!empty($idList)) {
499
            $idList = array_unique($idList);
500
            $idList = array_map('intval', $idList);
501
            $idCondition = ' AND iid IN ("'.implode('","', $idList).'") ';
502
        }
503
504
        $sql = "SELECT * FROM $table WHERE c_id = $courseId $sessionCondition $idCondition";
505
        $sql .= " ORDER BY forum_title, forum_category";
506
        $db_result = Database::query($sql);
507
        while ($obj = Database::fetch_object($db_result)) {
508
            $forum = new Forum($obj);
509
            $this->course->add_resource($forum);
510
        }
511
    }
512
513
    /**
514
     * Build a forum-category.
515
     *
516
     * @param int   $session_id      Internal session ID
517
     * @param int   $courseId        Internal course ID
518
     * @param bool  $withBaseContent Whether to include content from the course without session or not
519
     * @param array $idList          If you want to restrict the structure to only the given IDs
520
     */
521
    public function build_forum_category(
522
        $session_id = 0,
523
        $courseId = 0,
524
        $withBaseContent = false,
525
        $idList = []
526
    ) {
527
        $table = Database::get_course_table(TABLE_FORUM_CATEGORY);
528
529
        $sessionCondition = api_get_session_condition(
530
            $session_id,
531
            true,
532
            $withBaseContent
533
        );
534
535
        $idCondition = '';
536
        if (!empty($idList)) {
537
            $idList = array_unique($idList);
538
            $idList = array_map('intval', $idList);
539
            $idCondition = ' AND iid IN ("'.implode('","', $idList).'") ';
540
        }
541
542
        $sql = "SELECT * FROM $table
543
                WHERE c_id = $courseId $sessionCondition $idCondition
544
                ORDER BY cat_title";
545
546
        $result = Database::query($sql);
547
        while ($obj = Database::fetch_object($result)) {
548
            $forumCategory = new ForumCategory($obj);
549
            $this->course->add_resource($forumCategory);
550
        }
551
    }
552
553
    /**
554
     * Build the forum-topics.
555
     *
556
     * @param int   $session_id      Internal session ID
557
     * @param int   $courseId        Internal course ID
558
     * @param bool  $withBaseContent Whether to include content from the course without session or not
559
     * @param array $idList          If you want to restrict the structure to only the given IDs
560
     */
561
    public function build_forum_topics(
562
        $session_id = 0,
563
        $courseId = 0,
564
        $withBaseContent = false,
565
        $idList = []
566
    ) {
567
        $table = Database::get_course_table(TABLE_FORUM_THREAD);
568
569
        $sessionCondition = api_get_session_condition(
570
            $session_id,
571
            true,
572
            $withBaseContent
573
        );
574
575
        $idCondition = '';
576
        if (!empty($idList)) {
577
            $idList = array_map('intval', $idList);
578
            $idCondition = ' AND iid IN ("'.implode('","', $idList).'") ';
579
        }
580
581
        $sql = "SELECT * FROM $table WHERE c_id = $courseId
582
                $sessionCondition
583
                $idCondition
584
                ORDER BY thread_title ";
585
        $result = Database::query($sql);
586
587
        while ($obj = Database::fetch_object($result)) {
588
            $forumTopic = new ForumTopic($obj);
589
            $this->course->add_resource($forumTopic);
590
            $this->build_forum_posts($courseId, $obj->thread_id, $obj->forum_id);
591
        }
592
    }
593
594
    /**
595
     * Build the forum-posts
596
     * TODO: All tree structure of posts should be built, attachments for example.
597
     *
598
     * @param int   $courseId  Internal course ID
599
     * @param int   $thread_id Internal thread ID
600
     * @param int   $forum_id  Internal forum ID
601
     * @param array $idList
602
     */
603
    public function build_forum_posts(
604
        $courseId = 0,
605
        $thread_id = null,
606
        $forum_id = null,
607
        $idList = []
608
    ) {
609
        $table = Database::get_course_table(TABLE_FORUM_POST);
610
        $courseId = (int) $courseId;
611
        $sql = "SELECT * FROM $table WHERE c_id = $courseId ";
612
        if (!empty($thread_id) && !empty($forum_id)) {
613
            $forum_id = intval($forum_id);
614
            $thread_id = intval($thread_id);
615
            $sql .= " AND thread_id = $thread_id AND forum_id = $forum_id ";
616
        }
617
618
        if (!empty($idList)) {
619
            $idList = array_map('intval', $idList);
620
            $sql .= ' AND iid IN ("'.implode('","', $idList).'") ';
621
        }
622
623
        $sql .= " ORDER BY post_id ASC LIMIT 1";
624
        $db_result = Database::query($sql);
625
        while ($obj = Database::fetch_object($db_result)) {
626
            $forum_post = new ForumPost($obj);
627
            $this->course->add_resource($forum_post);
628
        }
629
    }
630
631
    /**
632
     * Build the links.
633
     *
634
     * @param int   $session_id      Internal session ID
635
     * @param int   $courseId        Internal course ID
636
     * @param bool  $withBaseContent Whether to include content from the course without session or not
637
     * @param array $idList          If you want to restrict the structure to only the given IDs
638
     */
639
    public function build_links(
640
        $session_id = 0,
641
        $courseId = 0,
642
        $withBaseContent = false,
643
        $idList = []
644
    ) {
645
        $categories = LinkManager::getLinkCategories(
646
            $courseId,
647
            $session_id,
648
            $withBaseContent
649
        );
650
651
        // Adding empty category
652
        $categories[] = ['id' => 0];
653
654
        foreach ($categories as $category) {
655
            $this->build_link_category($category);
656
657
            $links = LinkManager::getLinksPerCategory(
658
                $category['id'],
659
                $courseId,
660
                $session_id,
661
                $withBaseContent
662
            );
663
664
            foreach ($links as $item) {
665
                if (!empty($idList)) {
666
                    if (!in_array($item['id'], $idList)) {
667
                        continue;
668
                    }
669
                }
670
671
                $link = new Link(
672
                    $item['id'],
673
                    $item['title'],
674
                    $item['url'],
675
                    $item['description'],
676
                    $item['category_id'],
677
                    $item['on_homepage']
678
                );
679
                $link->target = $item['target'];
680
                $this->course->add_resource($link);
681
                $this->course->resources[RESOURCE_LINK][$item['id']]->add_linked_resource(
682
                    RESOURCE_LINKCATEGORY,
683
                    $item['category_id']
684
                );
685
            }
686
        }
687
    }
688
689
    /**
690
     * Build tool intro.
691
     *
692
     * @param int   $session_id      Internal session ID
693
     * @param int   $courseId        Internal course ID
694
     * @param bool  $withBaseContent Whether to include content from the course without session or not
695
     * @param array $idList          If you want to restrict the structure to only the given IDs
696
     */
697
    public function build_tool_intro(
698
        $session_id = 0,
699
        $courseId = 0,
700
        $withBaseContent = false,
701
        $idList = []
702
    ) {
703
        $table = Database::get_course_table(TABLE_TOOL_INTRO);
704
705
        $sessionCondition = api_get_session_condition(
706
            $session_id,
707
            true,
708
            $withBaseContent
709
        );
710
711
        $courseId = (int) $courseId;
712
713
        $sql = "SELECT * FROM $table
714
                WHERE c_id = $courseId $sessionCondition";
715
716
        $db_result = Database::query($sql);
717
        while ($obj = Database::fetch_object($db_result)) {
718
            $tool_intro = new ToolIntro($obj->id, $obj->intro_text);
719
            $this->course->add_resource($tool_intro);
720
        }
721
    }
722
723
    /**
724
     * Build a link category.
725
     *
726
     * @return int
727
     */
728
    public function build_link_category($category)
729
    {
730
        if (empty($category) || empty($category['category_title'])) {
731
            return 0;
732
        }
733
734
        $linkCategory = new LinkCategory(
735
            $category['id'],
736
            $category['category_title'],
737
            $category['description'],
738
            $category['display_order']
739
        );
740
        $this->course->add_resource($linkCategory);
741
742
        return $category['id'];
743
    }
744
745
    /**
746
     * Build the Quizzes.
747
     *
748
     * @param int   $session_id           Internal session ID
749
     * @param int   $courseId             Internal course ID
750
     * @param bool  $withBaseContent      Whether to include content from the course without session or not
751
     * @param array $idList               If you want to restrict the structure to only the given IDs
752
     * @param bool  $buildOrphanQuestions
753
     */
754
    public function build_quizzes(
755
        $session_id = 0,
756
        $courseId = 0,
757
        $withBaseContent = false,
758
        $idList = [],
759
        $buildOrphanQuestions = true
760
    ) {
761
        $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
762
        $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
763
        $table_doc = Database::get_course_table(TABLE_DOCUMENT);
764
765
        $courseId = (int) $courseId;
766
        $idCondition = '';
767
        if (!empty($idList)) {
768
            $idList = array_map('intval', $idList);
769
            $idCondition = ' iid IN ("'.implode('","', $idList).'") AND ';
770
        }
771
772
        if (!empty($courseId) && !empty($session_id)) {
773
            $session_id = (int) $session_id;
774
            if ($withBaseContent) {
775
                $sessionCondition = api_get_session_condition(
776
                    $session_id,
777
                    true,
778
                    true
779
                );
780
            } else {
781
                $sessionCondition = api_get_session_condition(
782
                    $session_id,
783
                    true
784
                );
785
            }
786
787
            // Select only quizzes with active = 0 or 1 (not -1 which is for deleted quizzes)
788
            $sql = "SELECT * FROM $table_qui
789
                    WHERE
790
                      c_id = $courseId AND
791
                      $idCondition
792
                      active >=0
793
                      $sessionCondition ";
794
        } else {
795
            // Select only quizzes with active = 0 or 1 (not -1 which is for deleted quizzes)
796
            $sql = "SELECT * FROM $table_qui
797
                    WHERE
798
                      c_id = $courseId AND
799
                      $idCondition
800
                      active >=0 AND
801
                      (session_id = 0 OR session_id IS NULL)";
802
        }
803
804
        $sql .= ' ORDER BY title';
805
        $db_result = Database::query($sql);
806
        $questionList = [];
807
        while ($obj = Database::fetch_object($db_result)) {
808
            if (strlen($obj->sound) > 0) {
809
                $sql = "SELECT iid FROM $table_doc
810
                        WHERE c_id = $courseId AND path = '/audio/".$obj->sound."'";
811
                $res = Database::query($sql);
812
                $doc = Database::fetch_object($res);
813
                $obj->sound = $doc->iid;
814
            }
815
            $this->findAndSetDocumentsInText($obj->description);
816
817
            $quiz = new Quiz($obj);
818
            $sql = "SELECT * FROM $table_rel
819
                WHERE c_id = $courseId AND exercice_id = {$obj->iid}";
820
            $db_result2 = Database::query($sql);
821
            while ($obj2 = Database::fetch_object($db_result2)) {
822
                $quiz->add_question($obj2->question_id, $obj2->question_order);
823
                $questionList[] = $obj2->question_id;
824
            }
825
            $this->course->add_resource($quiz);
826
        }
827
828
        if (!empty($courseId)) {
829
            $this->build_quiz_questions($courseId, $questionList, $buildOrphanQuestions);
830
        } else {
831
            $this->build_quiz_questions(0, $questionList, $buildOrphanQuestions);
832
        }
833
    }
834
835
    /**
836
     * Build the Quiz-Questions.
837
     *
838
     * @param int   $courseId             Internal course ID
839
     * @param array $questionList
840
     * @param bool  $buildOrphanQuestions
841
     */
842
    public function build_quiz_questions($courseId = 0, $questionList = [], $buildOrphanQuestions = true)
843
    {
844
        $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
845
        $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
846
        $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION);
847
        $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER);
848
        $courseId = (int) $courseId;
849
        $questionListToString = implode("','", $questionList);
850
851
        // Building normal tests (many queries)
852
        $sql = "SELECT * FROM $table_que
853
                WHERE iid IN ('$questionListToString')";
854
        $result = Database::query($sql);
855
856
        while ($obj = Database::fetch_object($result)) {
857
            // find the question category
858
            // @todo : need to be adapted for multi category questions in 1.10
859
            $question_category_id = TestCategory::getCategoryForQuestion(
860
                $obj->iid,
861
                $courseId
862
            );
863
864
            $this->findAndSetDocumentsInText($obj->description);
865
            // It searches images from hotspot to build
866
            if (HOT_SPOT == $obj->type) {
867
                if (is_numeric($obj->picture)) {
868
                    $itemDocumentId = (int) $obj->picture;
869
                    $document = \DocumentManager::get_document_data_by_id($itemDocumentId, api_get_course_id());
870
                    if (file_exists($document['absolute_path'])) {
871
                        $directUrl = $document['direct_url'];
872
                        $path = str_replace(api_get_path(WEB_PATH), '/', $directUrl);
873
                        $this->documentsAddedInText[] = [
874
                            0 => $path,
875
                            1 => 'local',
876
                            2 => 'rel',
877
                        ];
878
                    }
879
                }
880
            }
881
882
            // build the backup resource question object
883
            $question = new QuizQuestion(
884
                $obj->iid,
885
                $obj->question,
886
                $obj->description,
887
                $obj->ponderation,
888
                $obj->type,
889
                $obj->position,
890
                $obj->picture,
891
                $obj->level,
892
                $obj->extra,
893
                $question_category_id
894
            );
895
            $question->addPicture($this);
896
897
            $sql = "SELECT * FROM $table_ans
898
                WHERE question_id = {$obj->iid}";
899
            $db_result2 = Database::query($sql);
900
            while ($obj2 = Database::fetch_object($db_result2)) {
901
                $question->add_answer(
902
                    $obj2->iid,
903
                    $obj2->answer,
904
                    $obj2->correct,
905
                    $obj2->comment,
906
                    $obj2->ponderation,
907
                    $obj2->position,
908
                    $obj2->hotspot_coordinates,
909
                    $obj2->hotspot_type
910
                );
911
912
                $this->findAndSetDocumentsInText($obj2->answer);
913
                $this->findAndSetDocumentsInText($obj2->comment);
914
915
                if ($obj->type == MULTIPLE_ANSWER_TRUE_FALSE) {
916
                    $table_options = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
917
                    $sql = "SELECT * FROM $table_options
918
                        WHERE question_id = {$obj->iid}";
919
                    $db_result3 = Database::query($sql);
920
                    while ($obj3 = Database::fetch_object($db_result3)) {
921
                        $question_option = new QuizQuestionOption($obj3);
922
                        $question->add_option($question_option);
923
                    }
924
                }
925
            }
926
            $this->course->add_resource($question);
927
        }
928
929
        // Check if a global setting has been set to avoid copying orphan questions
930
        if (true === api_get_configuration_value('quiz_discard_orphan_in_course_export')) {
931
            $buildOrphanQuestions = false;
932
        }
933
934
        if ($buildOrphanQuestions) {
935
            // Building a fictional test for collecting orphan questions.
936
            // When a course is emptied this option should be activated (true).
937
            //$build_orphan_questions = !empty($_POST['recycle_option']);
938
939
            // 1st union gets the orphan questions from deleted exercises
940
            // 2nd union gets the orphan questions from question that were deleted in a exercise.
941
            $sql = " (
942
                        SELECT question_id, q.* FROM $table_que q
943
                        INNER JOIN $table_rel r
944
                        ON q.iid = r.question_id
945
                        INNER JOIN $table_qui ex
946
                        ON (ex.iid = r.exercice_id AND ex.c_id = r.c_id)
947
                        WHERE ex.c_id = $courseId AND ex.active = '-1'
948
                    )
949
                    UNION
950
                     (
951
                        SELECT question_id, q.* FROM $table_que q
952
                        left OUTER JOIN $table_rel r
953
                        ON q.iid = r.question_id
954
                        WHERE q.c_id = $courseId AND r.question_id is null
955
                     )
956
                     UNION
957
                     (
958
                        SELECT question_id, q.* FROM $table_que q
959
                        INNER JOIN $table_rel r
960
                        ON q.iid = r.question_id
961
                        WHERE r.c_id = $courseId AND (r.exercice_id = '-1' OR r.exercice_id = '0')
962
                     )
963
                 ";
964
965
            $result = Database::query($sql);
966
            if (Database::num_rows($result) > 0) {
967
                $orphanQuestionIds = [];
968
                while ($obj = Database::fetch_object($result)) {
969
                    // Orphan questions
970
                    if (!empty($obj->question_id)) {
971
                        $obj->iid = $obj->question_id;
972
                    }
973
974
                    // Avoid adding the same question twice
975
                    if (!isset($this->course->resources[$obj->iid])) {
976
                        // find the question category
977
                        // @todo : need to be adapted for multi category questions in 1.10
978
                        $question_category_id = TestCategory::getCategoryForQuestion($obj->iid, $courseId);
979
                        $question = new QuizQuestion(
980
                            $obj->iid,
981
                            $obj->question,
982
                            $obj->description,
983
                            $obj->ponderation,
984
                            $obj->type,
985
                            $obj->position,
986
                            $obj->picture,
987
                            $obj->level,
988
                            $obj->extra,
989
                            $question_category_id
990
                        );
991
                        $question->addPicture($this);
992
                        $sql = "SELECT * FROM $table_ans
993
                                WHERE question_id = {$obj->iid}";
994
                        $db_result2 = Database::query($sql);
995
                        if (Database::num_rows($db_result2)) {
996
                            while ($obj2 = Database::fetch_object($db_result2)) {
997
                                $question->add_answer(
998
                                    $obj2->iid,
999
                                    $obj2->answer,
1000
                                    $obj2->correct,
1001
                                    $obj2->comment,
1002
                                    $obj2->ponderation,
1003
                                    $obj2->position,
1004
                                    $obj2->hotspot_coordinates,
1005
                                    $obj2->hotspot_type
1006
                                );
1007
                            }
1008
                            $orphanQuestionIds[] = $obj->iid;
1009
                        }
1010
                        $this->course->add_resource($question);
1011
                    }
1012
                }
1013
            }
1014
        }
1015
1016
        $obj = [
1017
            'iid' => -1,
1018
            'title' => get_lang('OrphanQuestions'),
1019
            'type' => 2,
1020
        ];
1021
        $newQuiz = new Quiz((object) $obj);
1022
        if (!empty($orphanQuestionIds)) {
1023
            foreach ($orphanQuestionIds as $index => $orphanId) {
1024
                $order = $index + 1;
1025
                $newQuiz->add_question($orphanId, $order);
1026
            }
1027
        }
1028
        $this->course->add_resource($newQuiz);
1029
    }
1030
1031
    /**
1032
     * @deprecated
1033
     * Build the orphan questions
1034
     */
1035
    public function build_quiz_orphan_questions()
1036
    {
1037
        $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
1038
        $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
1039
        $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION);
1040
        $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER);
1041
1042
        $courseId = api_get_course_int_id();
1043
1044
        $sql = 'SELECT *
1045
                FROM '.$table_que.' as questions
1046
                LEFT JOIN '.$table_rel.' as quizz_questions
1047
                ON questions.iid=quizz_questions.question_id
1048
                LEFT JOIN '.$table_qui.' as exercises
1049
                ON quizz_questions.exercice_id = exercises.iid
1050
                WHERE
1051
                    exercises.c_id = '.$courseId.' AND
1052
                    (quizz_questions.exercice_id IS NULL OR
1053
                    exercises.active = -1)';
1054
1055
        $db_result = Database::query($sql);
1056
        if (Database::num_rows($db_result) > 0) {
1057
            // This is the fictional test for collecting orphan questions.
1058
            $orphan_questions = new Quiz(
1059
                -1,
1060
                get_lang('OrphanQuestions', ''),
1061
                '',
1062
                0,
1063
                0,
1064
                1,
1065
                '',
1066
                0
1067
            );
1068
1069
            $this->course->add_resource($orphan_questions);
1070
            while ($obj = Database::fetch_object($db_result)) {
1071
                $question = new QuizQuestion(
1072
                    $obj->iid,
1073
                    $obj->question,
1074
                    $obj->description,
1075
                    $obj->ponderation,
1076
                    $obj->type,
1077
                    $obj->position,
1078
                    $obj->picture,
1079
                    $obj->level,
1080
                    $obj->extra
1081
                );
1082
                $question->addPicture($this);
1083
1084
                $sql = 'SELECT * FROM '.$table_ans.' WHERE question_id = '.$obj->iid;
1085
                $db_result2 = Database::query($sql);
1086
                while ($obj2 = Database::fetch_object($db_result2)) {
1087
                    $question->add_answer(
1088
                        $obj2->iid,
1089
                        $obj2->answer,
1090
                        $obj2->correct,
1091
                        $obj2->comment,
1092
                        $obj2->ponderation,
1093
                        $obj2->position,
1094
                        $obj2->hotspot_coordinates,
1095
                        $obj2->hotspot_type
1096
                    );
1097
                }
1098
                $this->course->add_resource($question);
1099
            }
1100
        }
1101
    }
1102
1103
    /**
1104
     * Build the test category.
1105
     *
1106
     * @param int   $sessionId       Internal session ID
1107
     * @param int   $courseId        Internal course ID
1108
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1109
     * @param array $idList          If you want to restrict the structure to only the given IDs
1110
     *
1111
     * @todo add course session
1112
     */
1113
    public function build_test_category(
1114
        $sessionId = 0,
1115
        $courseId = 0,
1116
        $withBaseContent = false,
1117
        $idList = []
1118
    ) {
1119
        // get all test category in course
1120
        $categories = TestCategory::getCategoryListInfo('', $courseId);
1121
        foreach ($categories as $category) {
1122
            $this->findAndSetDocumentsInText($category->description);
1123
1124
            /** @var TestCategory $category */
1125
            $courseCopyTestCategory = new CourseCopyTestCategory(
1126
                $category->iid,
1127
                $category->name,
1128
                $category->description
1129
            );
1130
            $this->course->add_resource($courseCopyTestCategory);
1131
        }
1132
    }
1133
1134
    /**
1135
     * Build the Surveys.
1136
     *
1137
     * @param int   $session_id      Internal session ID
1138
     * @param int   $courseId        Internal course ID
1139
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1140
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1141
     */
1142
    public function build_surveys(
1143
        $session_id = 0,
1144
        $courseId = 0,
1145
        $withBaseContent = false,
1146
        $id_list = []
1147
    ) {
1148
        $table_survey = Database::get_course_table(TABLE_SURVEY);
1149
        $table_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1150
1151
        $courseId = (int) $courseId;
1152
1153
        $sessionCondition = api_get_session_condition(
1154
            $session_id,
1155
            true,
1156
            $withBaseContent
1157
        );
1158
1159
        $sql = 'SELECT * FROM '.$table_survey.'
1160
                WHERE c_id = '.$courseId.' '.$sessionCondition;
1161
        if ($id_list) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id_list of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1162
            $sql .= " AND iid IN (".implode(', ', $id_list).")";
1163
        }
1164
        $db_result = Database::query($sql);
1165
        while ($obj = Database::fetch_object($db_result)) {
1166
            $survey = new Survey(
1167
                $obj->survey_id,
1168
                $obj->code,
1169
                $obj->title,
1170
                $obj->subtitle,
1171
                $obj->author,
1172
                $obj->lang,
1173
                $obj->avail_from,
1174
                $obj->avail_till,
1175
                $obj->is_shared,
1176
                $obj->template,
1177
                $obj->intro,
1178
                $obj->surveythanks,
1179
                $obj->creation_date,
1180
                $obj->invited,
1181
                $obj->answered,
1182
                $obj->invite_mail,
1183
                $obj->reminder_mail,
1184
                $obj->one_question_per_page,
1185
                $obj->shuffle
1186
            );
1187
            $sql = 'SELECT * FROM '.$table_question.'
1188
                    WHERE c_id = '.$courseId.' AND survey_id = '.$obj->survey_id;
1189
            $db_result2 = Database::query($sql);
1190
            while ($obj2 = Database::fetch_object($db_result2)) {
1191
                $survey->add_question($obj2->question_id);
1192
            }
1193
            $this->course->add_resource($survey);
1194
        }
1195
        $this->build_survey_questions($courseId);
1196
    }
1197
1198
    /**
1199
     * Build the Survey Questions.
1200
     *
1201
     * @param int $courseId Internal course ID
1202
     */
1203
    public function build_survey_questions($courseId)
1204
    {
1205
        $table_que = Database::get_course_table(TABLE_SURVEY_QUESTION);
1206
        $table_opt = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1207
1208
        $courseId = (int) $courseId;
1209
        $idList = isset($this->specific_id_list['surveys']) ? $this->specific_id_list['surveys'] : [];
1210
1211
        $sql = 'SELECT * FROM '.$table_que.' WHERE c_id = '.$courseId.'  ';
1212
1213
        if (!empty($idList)) {
1214
            $sql .= " AND survey_id IN (".implode(', ', $idList).")";
1215
        }
1216
1217
        $db_result = Database::query($sql);
1218
        $is_required = 0;
1219
        while ($obj = Database::fetch_object($db_result)) {
1220
            if (api_get_configuration_value('allow_required_survey_questions')) {
1221
                if (isset($obj->is_required)) {
1222
                    $is_required = $obj->is_required;
1223
                }
1224
            }
1225
            $question = new SurveyQuestion(
1226
                $obj->question_id,
1227
                $obj->survey_id,
1228
                $obj->survey_question,
1229
                $obj->survey_question_comment,
1230
                $obj->type,
1231
                $obj->display,
1232
                $obj->sort,
1233
                $obj->shared_question_id,
1234
                $obj->max_value,
1235
                $is_required
1236
            );
1237
            $sql = 'SELECT * FROM '.$table_opt.'
1238
                    WHERE c_id = '.$courseId.' AND question_id = '.$obj->question_id;
1239
            $db_result2 = Database::query($sql);
1240
            while ($obj2 = Database::fetch_object($db_result2)) {
1241
                $question->add_answer($obj2->option_text, $obj2->sort);
1242
            }
1243
            $this->course->add_resource($question);
1244
        }
1245
    }
1246
1247
    /**
1248
     * Build the announcements.
1249
     *
1250
     * @param int   $session_id      Internal session ID
1251
     * @param int   $courseId        Internal course ID
1252
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1253
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1254
     */
1255
    public function build_announcements(
1256
        $session_id = 0,
1257
        $courseId = 0,
1258
        $withBaseContent = false,
1259
        $id_list = []
1260
    ) {
1261
        $table = Database::get_course_table(TABLE_ANNOUNCEMENT);
1262
1263
        $sessionCondition = api_get_session_condition(
1264
            $session_id,
1265
            true,
1266
            $withBaseContent
1267
        );
1268
1269
        $courseId = (int) $courseId;
1270
1271
        $sql = 'SELECT * FROM '.$table.'
1272
                WHERE c_id = '.$courseId.' '.$sessionCondition;
1273
        $db_result = Database::query($sql);
1274
        $table_attachment = Database::get_course_table(
1275
            TABLE_ANNOUNCEMENT_ATTACHMENT
1276
        );
1277
        while ($obj = Database::fetch_object($db_result)) {
1278
            if (empty($obj->id)) {
1279
                continue;
1280
            }
1281
            $sql = 'SELECT path, comment, filename, size
1282
                    FROM '.$table_attachment.'
1283
                    WHERE c_id = '.$courseId.' AND announcement_id = '.$obj->id.'';
1284
            $result = Database::query($sql);
1285
            $attachment_obj = Database::fetch_object($result);
1286
            $att_path = $att_filename = $att_size = $atth_comment = '';
1287
1288
            if (!empty($attachment_obj)) {
1289
                $att_path = $attachment_obj->path;
1290
                $att_filename = $attachment_obj->filename;
1291
                $att_size = $attachment_obj->size;
1292
                $atth_comment = $attachment_obj->comment;
1293
            }
1294
1295
            $announcement = new Announcement(
1296
                $obj->id,
1297
                $obj->title,
1298
                $obj->content,
1299
                $obj->end_date,
1300
                $obj->display_order,
1301
                $obj->email_sent,
1302
                $att_path,
1303
                $att_filename,
1304
                $att_size,
1305
                $atth_comment
1306
            );
1307
            $this->course->add_resource($announcement);
1308
        }
1309
    }
1310
1311
    /**
1312
     * Build the events.
1313
     *
1314
     * @param int   $session_id      Internal session ID
1315
     * @param int   $courseId        Internal course ID
1316
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1317
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1318
     */
1319
    public function build_events(
1320
        $session_id = 0,
1321
        $courseId = 0,
1322
        $withBaseContent = false,
1323
        $id_list = []
1324
    ) {
1325
        $table = Database::get_course_table(TABLE_AGENDA);
1326
1327
        $sessionCondition = api_get_session_condition(
1328
            $session_id,
1329
            true,
1330
            $withBaseContent
1331
        );
1332
1333
        $courseId = (int) $courseId;
1334
1335
        $sql = 'SELECT * FROM '.$table.'
1336
                WHERE c_id = '.$courseId.' '.$sessionCondition;
1337
        $db_result = Database::query($sql);
1338
        while ($obj = Database::fetch_object($db_result)) {
1339
            $table_attachment = Database::get_course_table(
1340
                TABLE_AGENDA_ATTACHMENT
1341
            );
1342
            $sql = 'SELECT path, comment, filename, size
1343
                    FROM '.$table_attachment.'
1344
                    WHERE c_id = '.$courseId.' AND agenda_id = '.$obj->id.'';
1345
            $result = Database::query($sql);
1346
1347
            $attachment_obj = Database::fetch_object($result);
1348
            $att_path = $att_filename = $att_size = $atth_comment = '';
1349
            if (!empty($attachment_obj)) {
1350
                $att_path = $attachment_obj->path;
1351
                $att_filename = $attachment_obj->filename;
1352
                $att_size = $attachment_obj->size;
1353
                $atth_comment = $attachment_obj->comment;
1354
            }
1355
            $event = new CalendarEvent(
1356
                $obj->id,
1357
                $obj->title,
1358
                $obj->content,
1359
                $obj->start_date,
1360
                $obj->end_date,
1361
                $att_path,
1362
                $att_filename,
1363
                $att_size,
1364
                $atth_comment,
1365
                $obj->all_day
1366
            );
1367
            $this->course->add_resource($event);
1368
        }
1369
    }
1370
1371
    /**
1372
     * Build the course-descriptions.
1373
     *
1374
     * @param int   $session_id      Internal session ID
1375
     * @param int   $courseId        Internal course ID
1376
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1377
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1378
     */
1379
    public function build_course_descriptions(
1380
        $session_id = 0,
1381
        $courseId = 0,
1382
        $withBaseContent = false,
1383
        $id_list = []
1384
    ) {
1385
        $table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
1386
        $courseId = (int) $courseId;
1387
1388
        if (!empty($session_id) && !empty($courseId)) {
1389
            $session_id = intval($session_id);
1390
            if ($withBaseContent) {
1391
                $sessionCondition = api_get_session_condition(
1392
                    $session_id,
1393
                    true,
1394
                    true
1395
                );
1396
            } else {
1397
                $sessionCondition = api_get_session_condition(
1398
                    $session_id,
1399
                    true
1400
                );
1401
            }
1402
            $sql = 'SELECT * FROM '.$table.'
1403
                    WHERE c_id = '.$courseId.' '.$sessionCondition;
1404
        } else {
1405
            $table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
1406
            $sql = 'SELECT * FROM '.$table.'
1407
                    WHERE c_id = '.$courseId.'  AND session_id = 0';
1408
        }
1409
1410
        $db_result = Database::query($sql);
1411
        while ($obj = Database::fetch_object($db_result)) {
1412
            $cd = new CourseDescription(
1413
                $obj->id,
1414
                $obj->title,
1415
                $obj->content,
1416
                $obj->description_type
1417
            );
1418
            $this->course->add_resource($cd);
1419
        }
1420
    }
1421
1422
    /**
1423
     * @param int   $session_id
1424
     * @param int   $courseId
1425
     * @param bool  $withBaseContent
1426
     * @param array $idList
1427
     */
1428
    public function build_learnpath_category($session_id = 0, $courseId = 0, $withBaseContent = false, $idList = [])
1429
    {
1430
        $categories = \learnpath::getCategories($courseId);
1431
1432
        /** @var CLpCategory $item */
1433
        foreach ($categories as $item) {
1434
            $categoryId = $item->getId();
1435
            if (!empty($idList)) {
1436
                if (!in_array($categoryId, $idList)) {
1437
                    continue;
1438
                }
1439
            }
1440
            $category = new LearnPathCategory($categoryId, $item);
1441
            $this->course->add_resource($category);
1442
        }
1443
    }
1444
1445
    /**
1446
     * Build the learnpaths.
1447
     *
1448
     * @param int   $session_id      Internal session ID
1449
     * @param int   $courseId        Internal course ID
1450
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1451
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1452
     * @param bool  $addScormFolder
1453
     */
1454
    public function build_learnpaths(
1455
        $session_id = 0,
1456
        $courseId = 0,
1457
        $withBaseContent = false,
1458
        $id_list = [],
1459
        $addScormFolder = true
1460
    ) {
1461
        $lpTable = Database::get_course_table(TABLE_LP_MAIN);
1462
        $table_item = Database::get_course_table(TABLE_LP_ITEM);
1463
        $table_tool = Database::get_course_table(TABLE_TOOL_LIST);
1464
1465
        $courseId = (int) $courseId;
1466
1467
        if (!empty($session_id) && !empty($courseId)) {
1468
            $session_id = (int) $session_id;
1469
            if ($withBaseContent) {
1470
                $sessionCondition = api_get_session_condition(
1471
                    $session_id,
1472
                    true,
1473
                    true
1474
                );
1475
            } else {
1476
                $sessionCondition = api_get_session_condition(
1477
                    $session_id,
1478
                    true
1479
                );
1480
            }
1481
            $sql = 'SELECT * FROM '.$lpTable.'
1482
                    WHERE c_id = '.$courseId.'  '.$sessionCondition;
1483
        } else {
1484
            $sql = 'SELECT * FROM '.$lpTable.'
1485
                    WHERE c_id = '.$courseId.' AND (session_id = 0 OR session_id IS NULL)';
1486
        }
1487
1488
        if (!empty($id_list)) {
1489
            $id_list = array_map('intval', $id_list);
1490
            $sql .= " AND id IN (".implode(', ', $id_list).") ";
1491
        }
1492
1493
        $result = Database::query($sql);
1494
        if ($result) {
0 ignored issues
show
introduced by
$result is of type Doctrine\DBAL\Driver\Statement, thus it always evaluated to true.
Loading history...
1495
            while ($obj = Database::fetch_object($result)) {
1496
                $items = [];
1497
                $sql = "SELECT * FROM $table_item
1498
                        WHERE c_id = '$courseId' AND lp_id = ".$obj->id;
1499
                $resultItem = Database::query($sql);
1500
                while ($obj_item = Database::fetch_object($resultItem)) {
1501
                    $item['id'] = $obj_item->iid;
1502
                    $item['item_type'] = $obj_item->item_type;
1503
                    $item['ref'] = $obj_item->ref;
1504
                    $item['title'] = $obj_item->title;
1505
                    $item['description'] = $obj_item->description;
1506
                    $item['path'] = $obj_item->path;
1507
                    $item['min_score'] = $obj_item->min_score;
1508
                    $item['max_score'] = $obj_item->max_score;
1509
                    $item['mastery_score'] = $obj_item->mastery_score;
1510
                    $item['parent_item_id'] = $obj_item->parent_item_id;
1511
                    $item['previous_item_id'] = $obj_item->previous_item_id;
1512
                    $item['next_item_id'] = $obj_item->next_item_id;
1513
                    $item['display_order'] = $obj_item->display_order;
1514
                    $item['prerequisite'] = $obj_item->prerequisite;
1515
                    $item['prerequisite_min_score'] = $obj_item->prerequisite_min_score;
1516
                    $item['prerequisite_max_score'] = $obj_item->prerequisite_max_score;
1517
                    $item['parameters'] = $obj_item->parameters;
1518
                    $item['launch_data'] = $obj_item->launch_data;
1519
                    $item['audio'] = $obj_item->audio;
1520
                    $items[] = $item;
1521
                    $this->itemListToAdd[$obj_item->item_type][] = $obj_item->path;
1522
                }
1523
1524
                $sql = "SELECT id FROM $table_tool
1525
                        WHERE
1526
                            c_id = $courseId AND
1527
                            (link LIKE '%lp_controller.php%lp_id=".$obj->id."%' AND image='scormbuilder.gif') AND
1528
                            visibility = '1' ";
1529
                $db_tool = Database::query($sql);
1530
                $visibility = '0';
1531
                if (Database::num_rows($db_tool)) {
1532
                    $visibility = '1';
1533
                }
1534
1535
                $accumulateWorkTime = 0;
1536
                if (api_get_configuration_value('lp_minimum_time')) {
1537
                    if (isset($obj->accumulate_work_time) && !empty($obj->accumulate_work_time)) {
1538
                        $accumulateWorkTime = $obj->accumulate_work_time;
1539
                    }
1540
                }
1541
1542
                $lp = new CourseCopyLearnpath(
1543
                    $obj->id,
1544
                    $obj->lp_type,
1545
                    $obj->name,
1546
                    $obj->path,
1547
                    $obj->ref,
1548
                    $obj->description,
1549
                    $obj->content_local,
1550
                    $obj->default_encoding,
1551
                    $obj->default_view_mod,
1552
                    $obj->prevent_reinit,
1553
                    $obj->force_commit,
1554
                    $obj->content_maker,
1555
                    $obj->display_order,
1556
                    $obj->js_lib,
1557
                    $obj->content_license,
1558
                    $obj->debug,
1559
                    $visibility,
1560
                    $obj->author,
1561
                    $obj->preview_image,
1562
                    $obj->use_max_score,
1563
                    $obj->autolaunch,
1564
                    $obj->created_on,
1565
                    $obj->modified_on,
1566
                    $obj->publicated_on,
1567
                    $obj->expired_on,
1568
                    $obj->session_id,
1569
                    $obj->category_id,
1570
                    $obj->subscribe_users,
1571
                    $obj->hide_toc_frame,
1572
                    $items,
1573
                    $accumulateWorkTime
1574
                );
1575
                $extraFieldValue = new \ExtraFieldValue('lp');
1576
                $lp->extraFields = $extraFieldValue->getAllValuesByItem($obj->id);
1577
                $this->course->add_resource($lp);
1578
1579
                if (!empty($obj->preview_image)) {
1580
                    // Add LP image
1581
                    $asset = new Asset(
1582
                        $obj->preview_image,
1583
                        '/upload/learning_path/images/'.$obj->preview_image,
1584
                        '/upload/learning_path/images/'.$obj->preview_image
1585
                    );
1586
                    $this->course->add_resource($asset);
1587
                }
1588
            }
1589
        }
1590
1591
        // Save scorm directory (previously build_scorm_documents())
1592
        if ($addScormFolder) {
1593
            $i = 1;
1594
            if ($dir = @opendir($this->course->backup_path.'/scorm')) {
1595
                while ($file = readdir($dir)) {
1596
                    if (is_dir($this->course->backup_path.'/scorm/'.$file) &&
1597
                        !in_array($file, ['.', '..'])
1598
                    ) {
1599
                        $doc = new ScormDocument($i++, '/'.$file, $file);
1600
                        $this->course->add_resource($doc);
1601
                    }
1602
                }
1603
                closedir($dir);
1604
            }
1605
        }
1606
    }
1607
1608
    /**
1609
     * It builds the resources used in a LP , also it adds the documents related.
1610
     */
1611
    public function exportToCourseBuildFormat()
1612
    {
1613
        if (empty($this->itemListToAdd)) {
1614
            return false;
1615
        }
1616
        $itemList = $this->itemListToAdd;
1617
        $courseId = api_get_course_int_id();
1618
        $sessionId = api_get_session_id();
1619
        $courseInfo = api_get_course_info_by_id($courseId);
1620
        if (isset($itemList['document'])) {
1621
            // Get parents
1622
            foreach ($itemList['document'] as $documentId) {
1623
                $documentInfo = \DocumentManager::get_document_data_by_id($documentId, $courseInfo['code'], true);
1624
                if (!empty($documentInfo['parents'])) {
1625
                    foreach ($documentInfo['parents'] as $parentInfo) {
1626
                        if (in_array($parentInfo['iid'], $itemList['document'])) {
1627
                            continue;
1628
                        }
1629
                        $itemList['document'][] = $parentInfo['iid'];
1630
                    }
1631
                }
1632
            }
1633
1634
            foreach ($itemList['document'] as $documentId) {
1635
                $documentInfo = \DocumentManager::get_document_data_by_id($documentId, $courseInfo['code']);
1636
                $items = \DocumentManager::get_resources_from_source_html(
1637
                    $documentInfo['absolute_path'],
1638
                    true,
1639
                    TOOL_DOCUMENT
1640
                );
1641
1642
                if (!empty($items)) {
1643
                    foreach ($items as $item) {
1644
                        // Get information about source url
1645
                        $url = $item[0]; // url
1646
                        $scope = $item[1]; // scope (local, remote)
1647
                        $type = $item[2]; // type (rel, abs, url)
1648
1649
                        $origParseUrl = parse_url($url);
1650
                        $realOrigPath = isset($origParseUrl['path']) ? $origParseUrl['path'] : null;
1651
1652
                        if ($scope == 'local') {
1653
                            if ($type == 'abs' || $type == 'rel') {
1654
                                $documentFile = strstr($realOrigPath, 'document');
1655
                                $documentFile = (string) $documentFile;
1656
                                $realOrigPath = (string) $realOrigPath;
1657
                                if (!empty($documentFile) && false !== strpos($realOrigPath, $documentFile)) {
1658
                                    $documentFile = str_replace('document', '', $documentFile);
1659
                                    $itemDocumentId = \DocumentManager::get_document_id($courseInfo, $documentFile);
1660
                                    // Document found! Add it to the list
1661
                                    if ($itemDocumentId) {
1662
                                        $itemList['document'][] = $itemDocumentId;
1663
                                    }
1664
                                }
1665
                            }
1666
                        }
1667
                    }
1668
                }
1669
            }
1670
1671
            $this->build_documents(
1672
                $sessionId,
1673
                $courseId,
1674
                true,
1675
                $itemList['document']
1676
            );
1677
        }
1678
1679
        if (isset($itemList['quiz'])) {
1680
            $this->build_quizzes(
1681
                $sessionId,
1682
                $courseId,
1683
                true,
1684
                $itemList['quiz']
1685
            );
1686
        }
1687
1688
        require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
1689
1690
        if (!empty($itemList['thread'])) {
1691
            $threadList = [];
1692
            $em = Database::getManager();
1693
            $repo = $em->getRepository('ChamiloCourseBundle:CForumThread');
1694
            foreach ($itemList['thread'] as $threadId) {
1695
                /** @var \Chamilo\CourseBundle\Entity\CForumThread $thread */
1696
                $thread = $repo->find($threadId);
1697
                if ($thread) {
1698
                    $itemList['forum'][] = $thread->getForumId();
1699
                    $threadList[] = $thread->getIid();
1700
                }
1701
            }
1702
1703
            if (!empty($threadList)) {
1704
                $this->build_forum_topics(
1705
                    $sessionId,
1706
                    $courseId,
1707
                    null,
1708
                    $threadList
1709
                );
1710
            }
1711
        }
1712
1713
        $forumCategoryList = [];
1714
        if (isset($itemList['forum'])) {
1715
            foreach ($itemList['forum'] as $forumId) {
1716
                $forumInfo = get_forums($forumId);
1717
                $forumCategoryList[] = $forumInfo['forum_category'];
1718
            }
1719
        }
1720
1721
        if (!empty($forumCategoryList)) {
1722
            $this->build_forum_category(
1723
                $sessionId,
1724
                $courseId,
1725
                true,
1726
                $forumCategoryList
1727
            );
1728
        }
1729
1730
        if (!empty($itemList['forum'])) {
1731
            $this->build_forums(
1732
                $sessionId,
1733
                $courseId,
1734
                true,
1735
                $itemList['forum']
1736
            );
1737
        }
1738
1739
        if (isset($itemList['link'])) {
1740
            $this->build_links(
1741
                $sessionId,
1742
                $courseId,
1743
                true,
1744
                $itemList['link']
1745
            );
1746
        }
1747
1748
        if (isset($itemList['xapi']) && $this->isXapiEnabled) {
1749
            $this->build_xapi_tool(
1750
                $sessionId,
1751
                $courseId,
1752
                true,
1753
                $itemList['xapi']
1754
            );
1755
        }
1756
1757
        if (!empty($itemList['student_publication'])) {
1758
            $this->build_works(
1759
                $sessionId,
1760
                $courseId,
1761
                true,
1762
                $itemList['student_publication']
1763
            );
1764
        }
1765
    }
1766
1767
    /**
1768
     * Build the glossaries.
1769
     *
1770
     * @param int   $session_id      Internal session ID
1771
     * @param int   $courseId        Internal course ID
1772
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1773
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1774
     */
1775
    public function build_glossary(
1776
        $session_id = 0,
1777
        $courseId = 0,
1778
        $withBaseContent = false,
1779
        $id_list = []
1780
    ) {
1781
        $table_glossary = Database::get_course_table(TABLE_GLOSSARY);
1782
1783
        $courseId = (int) $courseId;
1784
1785
        if (!empty($session_id) && !empty($courseId)) {
1786
            $session_id = intval($session_id);
1787
            if ($withBaseContent) {
1788
                $sessionCondition = api_get_session_condition(
1789
                    $session_id,
1790
                    true,
1791
                    true
1792
                );
1793
            } else {
1794
                $sessionCondition = api_get_session_condition(
1795
                    $session_id,
1796
                    true
1797
                );
1798
            }
1799
1800
            //@todo check this queries are the same ...
1801
            if (!empty($this->course->type) && $this->course->type == 'partial') {
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1802
                $sql = 'SELECT * FROM '.$table_glossary.' g
1803
                        WHERE g.c_id = '.$courseId.' '.$sessionCondition;
1804
            } else {
1805
                $sql = 'SELECT * FROM '.$table_glossary.' g
1806
                        WHERE g.c_id = '.$courseId.' '.$sessionCondition;
1807
            }
1808
        } else {
1809
            $table_glossary = Database::get_course_table(TABLE_GLOSSARY);
1810
            //@todo check this queries are the same ... ayayay
1811
            if (!empty($this->course->type) && $this->course->type == 'partial') {
1812
                $sql = 'SELECT * FROM '.$table_glossary.' g
1813
                        WHERE g.c_id = '.$courseId.' AND (session_id = 0 OR session_id IS NULL)';
1814
            } else {
1815
                $sql = 'SELECT * FROM '.$table_glossary.' g
1816
                        WHERE g.c_id = '.$courseId.' AND (session_id = 0 OR session_id IS NULL)';
1817
            }
1818
        }
1819
        $db_result = Database::query($sql);
1820
        while ($obj = Database::fetch_object($db_result)) {
1821
            $doc = new Glossary(
1822
                $obj->glossary_id,
1823
                $obj->name,
1824
                $obj->description,
1825
                $obj->display_order
1826
            );
1827
            $this->course->add_resource($doc);
1828
        }
1829
    }
1830
1831
    /*
1832
     * Build session course by jhon
1833
     */
1834
    public function build_session_course()
1835
    {
1836
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
1837
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
1838
        $list_course = CourseManager::get_course_list();
1839
        $list = [];
1840
        foreach ($list_course as $_course) {
1841
            $this->course = new Course();
1842
            $this->course->code = $_course['code'];
1843
            $this->course->type = 'partial';
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1844
            $this->course->path = api_get_path(SYS_COURSE_PATH).$_course['directory'].'/';
1845
            $this->course->backup_path = api_get_path(SYS_COURSE_PATH).$_course['directory'];
1846
            $this->course->encoding = api_get_system_encoding(); //current platform encoding
1847
            $courseId = $_course['real_id'];
1848
            $sql = "SELECT s.id, name, c_id
1849
                    FROM $tbl_session_course sc
1850
                    INNER JOIN $tbl_session s
1851
                    ON sc.session_id = s.id
1852
                    WHERE sc.c_id = '$courseId' ";
1853
            $query_session = Database::query($sql);
1854
            while ($rows_session = Database::fetch_assoc($query_session)) {
1855
                $session = new CourseSession(
1856
                    $rows_session['id'],
1857
                    $rows_session['name']
1858
                );
1859
                $this->course->add_resource($session);
1860
            }
1861
            $list[] = $this->course;
1862
        }
1863
1864
        return $list;
1865
    }
1866
1867
    /**
1868
     * @param int   $session_id      Internal session ID
1869
     * @param int   $courseId        Internal course ID
1870
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1871
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1872
     */
1873
    public function build_wiki(
1874
        $session_id = 0,
1875
        $courseId = 0,
1876
        $withBaseContent = false,
1877
        $id_list = []
1878
    ) {
1879
        $tbl_wiki = Database::get_course_table(TABLE_WIKI);
1880
        $courseId = (int) $courseId;
1881
1882
        if (!empty($session_id) && !empty($courseId)) {
1883
            $session_id = intval($session_id);
1884
            if ($withBaseContent) {
1885
                $sessionCondition = api_get_session_condition(
1886
                    $session_id,
1887
                    true,
1888
                    true
1889
                );
1890
            } else {
1891
                $sessionCondition = api_get_session_condition(
1892
                    $session_id,
1893
                    true
1894
                );
1895
            }
1896
            $sql = 'SELECT * FROM '.$tbl_wiki.'
1897
                    WHERE c_id = '.$courseId.' '.$sessionCondition;
1898
        } else {
1899
            $tbl_wiki = Database::get_course_table(TABLE_WIKI);
1900
            $sql = 'SELECT * FROM '.$tbl_wiki.'
1901
                    WHERE c_id = '.$courseId.' AND (session_id = 0 OR session_id IS NULL)';
1902
        }
1903
        $db_result = Database::query($sql);
1904
        while ($obj = Database::fetch_object($db_result)) {
1905
            $wiki = new Wiki(
1906
                $obj->id,
1907
                $obj->page_id,
1908
                $obj->reflink,
1909
                $obj->title,
1910
                $obj->content,
1911
                $obj->user_id,
1912
                $obj->group_id,
1913
                $obj->dtime,
1914
                $obj->progress,
1915
                $obj->version
1916
            );
1917
            $this->course->add_resource($wiki);
1918
        }
1919
    }
1920
1921
    /**
1922
     * Build the xapi tool
1923
     */
1924
    public function build_xapi_tool(
1925
        $sessionId = 0,
1926
        $courseId = 0,
1927
        $withBaseContent = false,
1928
        $idList = []
1929
    ) {
1930
1931
        if (!$this->isXapiEnabled) {
1932
            return false;
1933
        }
1934
1935
        $courseId = (int) $courseId;
1936
        $sessionId = (int) $sessionId;
1937
        if ($withBaseContent) {
1938
            $sessionCondition = api_get_session_condition(
1939
                $sessionId,
1940
                true,
1941
                true
1942
            );
1943
        } else {
1944
            $sessionCondition = api_get_session_condition($sessionId, true);
1945
        }
1946
1947
        $idCondition = '';
1948
        if (!empty($idList)) {
1949
            $idList = array_map('intval', $idList);
1950
            $idCondition = ' AND id IN ("'.implode('","', $idList).'") ';
1951
        }
1952
1953
        $sql = "SELECT * FROM xapi_tool_launch WHERE c_id = $courseId $sessionCondition $idCondition";
1954
        $rs = Database::query($sql);
1955
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
1956
            $xapiTool = new XapiTool($row);
1957
            $this->course->add_resource($xapiTool);
1958
        }
1959
1960
    }
1961
1962
    /**
1963
     * Build the Surveys.
1964
     *
1965
     * @param int   $session_id      Internal session ID
1966
     * @param int   $courseId        Internal course ID
1967
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1968
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1969
     */
1970
    public function build_thematic(
1971
        $session_id = 0,
1972
        $courseId = 0,
1973
        $withBaseContent = false,
1974
        $id_list = []
1975
    ) {
1976
        $table_thematic = Database::get_course_table(TABLE_THEMATIC);
1977
        $table_thematic_advance = Database::get_course_table(TABLE_THEMATIC_ADVANCE);
1978
        $table_thematic_plan = Database::get_course_table(TABLE_THEMATIC_PLAN);
1979
        $courseId = (int) $courseId;
1980
1981
        $courseInfo = api_get_course_info_by_id($courseId);
1982
        $session_id = intval($session_id);
1983
        if ($withBaseContent) {
1984
            $sessionCondition = api_get_session_condition(
1985
                $session_id,
1986
                true,
1987
                true
1988
            );
1989
        } else {
1990
            $sessionCondition = api_get_session_condition($session_id, true);
1991
        }
1992
1993
        $sql = "SELECT * FROM $table_thematic
1994
                WHERE c_id = $courseId AND active = 1 $sessionCondition ";
1995
        $db_result = Database::query($sql);
1996
        while ($row = Database::fetch_array($db_result, 'ASSOC')) {
1997
            $thematic = new Thematic($row);
1998
            $sql = 'SELECT * FROM '.$table_thematic_advance.'
1999
                    WHERE c_id = '.$courseId.' AND thematic_id = '.$row['id'];
2000
2001
            $result = Database::query($sql);
2002
            while ($sub_row = Database::fetch_array($result, 'ASSOC')) {
2003
                $thematic->addThematicAdvance($sub_row);
2004
            }
2005
2006
            $items = api_get_item_property_by_tool(
2007
                'thematic_plan',
2008
                $courseInfo['code'],
2009
                $session_id
2010
            );
2011
2012
            $thematic_plan_id_list = [];
2013
            if (!empty($items)) {
2014
                foreach ($items as $item) {
2015
                    $thematic_plan_id_list[] = $item['ref'];
2016
                }
2017
            }
2018
            if (count($thematic_plan_id_list) > 0) {
2019
                $sql = "SELECT tp.*
2020
                        FROM $table_thematic_plan tp
2021
                            INNER JOIN $table_thematic t ON (t.id=tp.thematic_id)
2022
                        WHERE
2023
                            t.c_id = $courseId AND
2024
                            tp.c_id = $courseId AND
2025
                            thematic_id = {$row['id']}  AND
2026
                            tp.id IN (".implode(', ', $thematic_plan_id_list).") ";
2027
2028
                $result = Database::query($sql);
2029
                while ($sub_row = Database::fetch_array($result, 'ASSOC')) {
2030
                    $thematic->addThematicPlan($sub_row);
2031
                }
2032
            }
2033
            $this->course->add_resource($thematic);
2034
        }
2035
    }
2036
2037
    /**
2038
     * Build the attendances.
2039
     *
2040
     * @param int   $session_id      Internal session ID
2041
     * @param int   $courseId        Internal course ID
2042
     * @param bool  $withBaseContent Whether to include content from the course without session or not
2043
     * @param array $id_list         If you want to restrict the structure to only the given IDs
2044
     */
2045
    public function build_attendance(
2046
        $session_id = 0,
2047
        $courseId = 0,
2048
        $withBaseContent = false,
2049
        $id_list = []
2050
    ) {
2051
        $table_attendance = Database::get_course_table(TABLE_ATTENDANCE);
2052
        $table_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
2053
        $sessionCondition = api_get_session_condition($session_id, true, $withBaseContent);
2054
        $courseId = (int) $courseId;
2055
2056
        $sql = 'SELECT * FROM '.$table_attendance.'
2057
                WHERE c_id = '.$courseId.' '.$sessionCondition;
2058
        $db_result = Database::query($sql);
2059
        while ($row = Database::fetch_array($db_result, 'ASSOC')) {
2060
            $obj = new Attendance($row);
2061
            $sql = 'SELECT * FROM '.$table_attendance_calendar.'
2062
                    WHERE c_id = '.$courseId.' AND attendance_id = '.$row['id'];
2063
2064
            $result = Database::query($sql);
2065
            while ($sub_row = Database::fetch_array($result, 'ASSOC')) {
2066
                $obj->add_attendance_calendar($sub_row);
2067
            }
2068
            $this->course->add_resource($obj);
2069
        }
2070
    }
2071
2072
    /**
2073
     * Build the works (or "student publications", or "assignments").
2074
     *
2075
     * @param int   $session_id      Internal session ID
2076
     * @param int   $courseId        Internal course ID
2077
     * @param bool  $withBaseContent Whether to include content from the course without session or not
2078
     * @param array $idList          If you want to restrict the structure to only the given IDs
2079
     */
2080
    public function build_works(
2081
        $session_id = 0,
2082
        $courseId = 0,
2083
        $withBaseContent = false,
2084
        $idList = []
2085
    ) {
2086
        $table_work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
2087
        $sessionCondition = api_get_session_condition(
2088
            $session_id,
2089
            true,
2090
            $withBaseContent
2091
        );
2092
        $courseId = (int) $courseId;
2093
2094
        $idCondition = '';
2095
        if (!empty($idList)) {
2096
            $idList = array_map('intval', $idList);
2097
            $idCondition = ' AND iid IN ("'.implode('","', $idList).'") ';
2098
        }
2099
2100
        $sql = "SELECT * FROM $table_work
2101
                WHERE
2102
                    c_id = $courseId
2103
                    $sessionCondition AND
2104
                    filetype = 'folder' AND
2105
                    parent_id = 0 AND
2106
                    active = 1
2107
                    $idCondition
2108
                ";
2109
        $result = Database::query($sql);
2110
        while ($row = Database::fetch_array($result, 'ASSOC')) {
2111
            $obj = new Work($row);
2112
            $this->findAndSetDocumentsInText($row['description']);
2113
            $this->course->add_resource($obj);
2114
        }
2115
    }
2116
2117
    /**
2118
     * @param int  $session_id
2119
     * @param int  $courseId
2120
     * @param bool $withBaseContent
2121
     */
2122
    public function build_gradebook(
2123
        $session_id = 0,
2124
        $courseId = 0,
2125
        $withBaseContent = false
2126
    ) {
2127
        $courseInfo = api_get_course_info_by_id($courseId);
2128
        $courseCode = $courseInfo['code'];
2129
        $cats = Category:: load(
2130
            null,
2131
            null,
2132
            $courseCode,
2133
            null,
2134
            null,
2135
            $session_id
2136
        );
2137
2138
        if (!empty($cats)) {
2139
            /** @var Category $cat */
2140
            foreach ($cats as $cat) {
2141
                $cat->evaluations = $cat->get_evaluations(null, false);
2142
                $cat->links = $cat->get_links(null, false);
2143
                $cat->subCategories = $cat->get_subcategories(
2144
                    null,
2145
                    $courseCode,
2146
                    $session_id
2147
                );
2148
            }
2149
            $obj = new GradeBookBackup($cats);
2150
            $this->course->add_resource($obj);
2151
        }
2152
    }
2153
}
2154