Completed
Push — master ( 4d7dee...e76cd5 )
by Julito
10:42 queued 17s
created

CourseBuilder::build_forum_posts()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 8
nop 4
dl 0
loc 25
rs 9.4555
c 0
b 0
f 0
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\Entity\CLpCategory;
36
use CourseManager;
37
use Database;
38
use Link as LinkManager;
39
use TestCategory;
40
41
/**
42
 * Class CourseBuilder
43
 * Builds a course-object from a Chamilo-course.
44
 *
45
 * @author Bart Mollet <[email protected]>
46
 *
47
 * @package chamilo.backup
48
 */
49
class CourseBuilder
50
{
51
    /** @var Course */
52
    public $course;
53
54
    /* With this array you can filter the tools you want to be parsed by
55
    default all tools are included */
56
    public $tools_to_build = [
57
        'announcements',
58
        'attendance',
59
        'course_descriptions',
60
        'documents',
61
        'events',
62
        'forum_category',
63
        'forums',
64
        'forum_topics',
65
        'glossary',
66
        'quizzes',
67
        'test_category',
68
        'learnpath_category',
69
        'learnpaths',
70
        'links',
71
        'surveys',
72
        'tool_intro',
73
        'thematic',
74
        'wiki',
75
        'works',
76
        'gradebook',
77
    ];
78
79
    public $toolToName = [
80
        'announcements' => RESOURCE_ANNOUNCEMENT,
81
        'attendance' => RESOURCE_ATTENDANCE,
82
        'course_descriptions' => RESOURCE_COURSEDESCRIPTION,
83
        'documents' => RESOURCE_DOCUMENT,
84
        'events' => RESOURCE_EVENT,
85
        'forum_category' => RESOURCE_FORUMCATEGORY,
86
        'forums' => RESOURCE_FORUM,
87
        'forum_topics' => RESOURCE_FORUMTOPIC,
88
        'glossary' => RESOURCE_GLOSSARY,
89
        'quizzes' => RESOURCE_QUIZ,
90
        'test_category' => RESOURCE_TEST_CATEGORY,
91
        'learnpath_category' => RESOURCE_LEARNPATH_CATEGORY,
92
        'learnpaths' => RESOURCE_LEARNPATH,
93
        'links' => RESOURCE_LINK,
94
        'surveys' => RESOURCE_SURVEY,
95
        'tool_intro' => RESOURCE_TOOL_INTRO,
96
        'thematic' => RESOURCE_THEMATIC,
97
        'wiki' => RESOURCE_WIKI,
98
        'works' => RESOURCE_WORK,
99
        'gradebook' => RESOURCE_GRADEBOOK,
100
    ];
101
102
    /* With this array you can filter wich elements of the tools are going
103
    to be added in the course obj (only works with LPs) */
104
    public $specific_id_list = [];
105
    public $documentsAddedInText = [];
106
107
    /**
108
     * Create a new CourseBuilder.
109
     *
110
     * @param string $type
111
     * @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...
112
     */
113
    public function __construct($type = '', $course = null)
114
    {
115
        $_course = api_get_course_info();
116
117
        if (!empty($course['official_code'])) {
118
            $_course = $course;
119
        }
120
121
        $this->course = new Course();
122
        $this->course->code = $_course['code'];
123
        $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...
124
        $this->course->path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/';
125
        $this->course->backup_path = api_get_path(SYS_COURSE_PATH).$_course['path'];
0 ignored issues
show
Bug Best Practice introduced by
The property backup_path does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
126
        $this->course->encoding = api_get_system_encoding();
127
        $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...
128
    }
129
130
    /**
131
     * @param array $list
132
     */
133
    public function addDocumentList($list)
134
    {
135
        foreach ($list as $item) {
136
            if (!in_array($item[0], $this->documentsAddedInText)) {
137
                $this->documentsAddedInText[$item[0]] = $item;
138
            }
139
        }
140
    }
141
142
    /**
143
     * @param string $text
144
     */
145
    public function findAndSetDocumentsInText($text)
146
    {
147
        $documentList = \DocumentManager::get_resources_from_source_html($text);
148
        $this->addDocumentList($documentList);
149
    }
150
151
    /**
152
     * Parse documents added in the documentsAddedInText variable.
153
     */
154
    public function restoreDocumentsFromList()
155
    {
156
        if (!empty($this->documentsAddedInText)) {
157
            $list = [];
158
            $courseInfo = api_get_course_info();
159
            foreach ($this->documentsAddedInText as $item) {
160
                // Get information about source url
161
                $url = $item[0]; // url
162
                $scope = $item[1]; // scope (local, remote)
163
                $type = $item[2]; // type (rel, abs, url)
164
165
                $origParseUrl = parse_url($url);
166
                $realOrigPath = isset($origParseUrl['path']) ? $origParseUrl['path'] : null;
167
168
                if ($scope == 'local') {
169
                    if ($type == 'abs' || $type == 'rel') {
170
                        $documentFile = strstr($realOrigPath, 'document');
171
                        if (strpos($realOrigPath, $documentFile) !== false) {
172
                            $documentFile = str_replace('document', '', $documentFile);
173
                            $itemDocumentId = \DocumentManager::get_document_id($courseInfo, $documentFile);
174
                            // Document found! Add it to the list
175
                            if ($itemDocumentId) {
176
                                $list[] = $itemDocumentId;
177
                            }
178
                        }
179
                    }
180
                }
181
            }
182
183
            $this->build_documents(
184
                api_get_session_id(),
185
                api_get_course_int_id(),
186
                true,
187
                $list
188
            );
189
        }
190
    }
191
192
    /**
193
     * @param array $array
194
     */
195
    public function set_tools_to_build($array)
196
    {
197
        $this->tools_to_build = $array;
198
    }
199
200
    /**
201
     * @param array $array
202
     */
203
    public function set_tools_specific_id_list($array)
204
    {
205
        $this->specific_id_list = $array;
206
    }
207
208
    /**
209
     * Get the created course.
210
     *
211
     * @return course The course
212
     */
213
    public function get_course()
214
    {
215
        return $this->course;
216
    }
217
218
    /**
219
     * Build the course-object.
220
     *
221
     * @param int    $session_id
222
     * @param string $courseCode
223
     * @param bool   $withBaseContent   true if you want to get the elements that exists in the course and
224
     *                                  in the session, (session_id = 0 or session_id = X)
225
     * @param array  $parseOnlyToolList
226
     * @param array  $toolsFromPost
227
     *
228
     * @return Course The course object structure
229
     */
230
    public function build(
231
        $session_id = 0,
232
        $courseCode = '',
233
        $withBaseContent = false,
234
        $parseOnlyToolList = [],
235
        $toolsFromPost = []
236
    ) {
237
        $course = api_get_course_info($courseCode);
238
        $courseId = $course['real_id'];
239
        foreach ($this->tools_to_build as $tool) {
240
            if (!empty($parseOnlyToolList) && !in_array($this->toolToName[$tool], $parseOnlyToolList)) {
241
                continue;
242
            }
243
            $function_build = 'build_'.$tool;
244
            $specificIdList = isset($this->specific_id_list[$tool]) ? $this->specific_id_list[$tool] : null;
245
            $buildOrphanQuestions = true;
246
            if ($tool === 'quizzes') {
247
                if (!isset($toolsFromPost[RESOURCE_QUIZ][-1])) {
248
                    $buildOrphanQuestions = false;
249
                }
250
251
                // Force orphan load
252
                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...
253
                    $buildOrphanQuestions = true;
254
                }
255
256
                $this->build_quizzes(
257
                    $session_id,
258
                    $courseId,
259
                    $withBaseContent,
260
                    $specificIdList,
261
                    $buildOrphanQuestions
262
                );
263
            } else {
264
                $this->$function_build(
265
                    $session_id,
266
                    $courseId,
267
                    $withBaseContent,
268
                    $specificIdList
269
                );
270
            }
271
        }
272
273
        // Add asset
274
        if ($course['course_image_source'] && basename($course['course_image_source']) !== 'course.png') {
275
            // Add course image courses/XXX/course-pic85x85.png
276
            $asset = new Asset(
277
                $course['course_image_source'],
278
                basename($course['course_image_source']),
279
                basename($course['course_image_source'])
280
            );
281
            $this->course->add_resource($asset);
282
283
            $asset = new Asset(
284
                $course['course_image_large_source'],
285
                basename($course['course_image_large_source']),
286
                basename($course['course_image_large_source'])
287
            );
288
            $this->course->add_resource($asset);
289
        }
290
291
        // Once we've built the resources array a bit more, try to get items
292
        // from the item_property table and order them in the "resources" array
293
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
294
        foreach ($this->course->resources as $type => $resources) {
295
            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...
296
                continue;
297
            }
298
            foreach ($resources as $id => $resource) {
299
                if ($resource) {
300
                    $tool = $resource->get_tool();
301
                    if ($tool != null) {
302
                        $sql = "SELECT * FROM $table
303
                                WHERE
304
                                    c_id = $courseId AND
305
                                    tool = '".$tool."' AND
306
                                    ref = '".$resource->get_id()."'";
307
                        $res = Database::query($sql);
308
                        $properties = [];
309
                        while ($property = Database::fetch_array($res)) {
310
                            $properties[] = $property;
311
                        }
312
                        $this->course->resources[$type][$id]->item_properties = $properties;
313
                    }
314
                }
315
            }
316
        }
317
318
        return $this->course;
319
    }
320
321
    /**
322
     * Build the documents.
323
     *
324
     * @param int   $session_id
325
     * @param int   $courseId
326
     * @param bool  $withBaseContent
327
     * @param array $idList
328
     */
329
    public function build_documents(
330
        $session_id = 0,
331
        $courseId = 0,
332
        $withBaseContent = false,
333
        $idList = []
334
    ) {
335
        $table_doc = Database::get_course_table(TABLE_DOCUMENT);
336
        $table_prop = Database::get_course_table(TABLE_ITEM_PROPERTY);
337
338
        // Remove chat_files and shared_folder files
339
        $avoid_paths = " path NOT LIKE '/shared_folder%' AND
340
                         path NOT LIKE '/chat_files%' ";
341
342
        $documentCondition = '';
343
        if (!empty($idList)) {
344
            $idList = array_unique($idList);
345
            $idList = array_map('intval', $idList);
346
            $documentCondition = ' d.iid IN ("'.implode('","', $idList).'") AND ';
347
        }
348
349
        if (!empty($courseId) && !empty($session_id)) {
350
            $session_id = (int) $session_id;
351
            if ($withBaseContent) {
352
                $session_condition = api_get_session_condition(
353
                    $session_id,
354
                    true,
355
                    true,
356
                    'd.session_id'
357
                );
358
            } else {
359
                $session_condition = api_get_session_condition(
360
                    $session_id,
361
                    true,
362
                    false,
363
                    'd.session_id'
364
                );
365
            }
366
367
            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...
368
                $sql = "SELECT d.iid, d.path, d.comment, d.title, d.filetype, d.size
369
                        FROM $table_doc d 
370
                        INNER JOIN $table_prop p
371
                        ON (p.ref = d.id AND d.c_id = p.c_id)
372
                        WHERE
373
                            d.c_id = $courseId AND
374
                            p.c_id = $courseId AND
375
                            tool = '".TOOL_DOCUMENT."' AND
376
                            $documentCondition
377
                            p.visibility != 2 AND
378
                            path NOT LIKE '/images/gallery%' AND
379
                            $avoid_paths
380
                            $session_condition
381
                        ORDER BY path";
382
            } else {
383
                $sql = "SELECT d.iid, d.path, d.comment, d.title, d.filetype, d.size
384
                        FROM $table_doc d 
385
                        INNER JOIN $table_prop p
386
                        ON (p.ref = d.id AND d.c_id = p.c_id)
387
                        WHERE
388
                            d.c_id = $courseId AND
389
                            p.c_id = $courseId AND
390
                            tool = '".TOOL_DOCUMENT."' AND
391
                            $documentCondition
392
                            $avoid_paths AND
393
                            p.visibility != 2 $session_condition
394
                        ORDER BY path";
395
            }
396
397
            $db_result = Database::query($sql);
398
            while ($obj = Database::fetch_object($db_result)) {
399
                $doc = new Document(
400
                    $obj->iid,
401
                    $obj->path,
402
                    $obj->comment,
403
                    $obj->title,
404
                    $obj->filetype,
405
                    $obj->size
406
                );
407
                $this->course->add_resource($doc);
408
            }
409
        } else {
410
            if (!empty($this->course->type) && $this->course->type == 'partial') {
411
                $sql = "SELECT d.iid, d.path, d.comment, d.title, d.filetype, d.size
412
                        FROM $table_doc d 
413
                        INNER JOIN $table_prop p
414
                        ON (p.ref = d.id AND d.c_id = p.c_id)
415
                        WHERE
416
                            d.c_id = $courseId AND
417
                            p.c_id = $courseId AND
418
                            tool = '".TOOL_DOCUMENT."' AND
419
                            $documentCondition
420
                            p.visibility != 2 AND
421
                            path NOT LIKE '/images/gallery%' AND
422
                            $avoid_paths AND
423
                            (d.session_id = 0 OR d.session_id IS NULL)
424
                        ORDER BY path";
425
            } else {
426
                $sql = "SELECT d.iid, d.path, d.comment, d.title, d.filetype, d.size
427
                        FROM $table_doc d 
428
                        INNER JOIN $table_prop p
429
                        ON (p.ref = d.id AND d.c_id = p.c_id)
430
                        WHERE
431
                            d.c_id = $courseId AND
432
                            p.c_id = $courseId AND
433
                            tool = '".TOOL_DOCUMENT."' AND
434
                            $documentCondition
435
                            p.visibility != 2 AND
436
                            $avoid_paths AND
437
                            (d.session_id = 0 OR d.session_id IS NULL)
438
                        ORDER BY path";
439
            }
440
441
            $result = Database::query($sql);
442
            while ($obj = Database::fetch_object($result)) {
443
                $doc = new Document(
444
                    $obj->iid,
445
                    $obj->path,
446
                    $obj->comment,
447
                    $obj->title,
448
                    $obj->filetype,
449
                    $obj->size
450
                );
451
                $this->course->add_resource($doc);
452
            }
453
        }
454
    }
455
456
    /**
457
     * Build the forums.
458
     *
459
     * @param int   $session_id      Internal session ID
460
     * @param int   $courseId        Internal course ID
461
     * @param bool  $withBaseContent Whether to include content from the course without session or not
462
     * @param array $idList          If you want to restrict the structure to only the given IDs
463
     */
464
    public function build_forums(
465
        $session_id = 0,
466
        $courseId = 0,
467
        $withBaseContent = false,
468
        $idList = []
469
    ) {
470
        $table = Database::get_course_table(TABLE_FORUM);
471
        $sessionCondition = api_get_session_condition(
472
            $session_id,
473
            true,
474
            $withBaseContent
475
        );
476
477
        $idCondition = '';
478
        if (!empty($idList)) {
479
            $idList = array_unique($idList);
480
            $idList = array_map('intval', $idList);
481
            $idCondition = ' AND iid IN ("'.implode('","', $idList).'") ';
482
        }
483
484
        $sql = "SELECT * FROM $table WHERE c_id = $courseId $sessionCondition $idCondition";
485
        $sql .= " ORDER BY forum_title, forum_category";
486
        $db_result = Database::query($sql);
487
        while ($obj = Database::fetch_object($db_result)) {
488
            $forum = new Forum($obj);
489
            $this->course->add_resource($forum);
490
        }
491
    }
492
493
    /**
494
     * Build a forum-category.
495
     *
496
     * @param int   $session_id      Internal session ID
497
     * @param int   $courseId        Internal course ID
498
     * @param bool  $withBaseContent Whether to include content from the course without session or not
499
     * @param array $idList          If you want to restrict the structure to only the given IDs
500
     */
501
    public function build_forum_category(
502
        $session_id = 0,
503
        $courseId = 0,
504
        $withBaseContent = false,
505
        $idList = []
506
    ) {
507
        $table = Database::get_course_table(TABLE_FORUM_CATEGORY);
508
509
        $sessionCondition = api_get_session_condition(
510
            $session_id,
511
            true,
512
            $withBaseContent
513
        );
514
515
        $idCondition = '';
516
        if (!empty($idList)) {
517
            $idList = array_unique($idList);
518
            $idList = array_map('intval', $idList);
519
            $idCondition = ' AND iid IN ("'.implode('","', $idList).'") ';
520
        }
521
522
        $sql = "SELECT * FROM $table
523
                WHERE c_id = $courseId $sessionCondition $idCondition
524
                ORDER BY cat_title";
525
526
        $result = Database::query($sql);
527
        while ($obj = Database::fetch_object($result)) {
528
            $forumCategory = new ForumCategory($obj);
529
            $this->course->add_resource($forumCategory);
530
        }
531
    }
532
533
    /**
534
     * Build the forum-topics.
535
     *
536
     * @param int   $session_id      Internal session ID
537
     * @param int   $courseId        Internal course ID
538
     * @param bool  $withBaseContent Whether to include content from the course without session or not
539
     * @param array $idList          If you want to restrict the structure to only the given IDs
540
     */
541
    public function build_forum_topics(
542
        $session_id = 0,
543
        $courseId = 0,
544
        $withBaseContent = false,
545
        $idList = []
546
    ) {
547
        $table = Database::get_course_table(TABLE_FORUM_THREAD);
548
549
        $sessionCondition = api_get_session_condition(
550
            $session_id,
551
            true,
552
            $withBaseContent
553
        );
554
555
        $idCondition = '';
556
        if (!empty($idList)) {
557
            $idList = array_map('intval', $idList);
558
            $idCondition = ' AND iid IN ("'.implode('","', $idList).'") ';
559
        }
560
561
        $sql = "SELECT * FROM $table WHERE c_id = $courseId
562
                $sessionCondition
563
                $idCondition
564
                ORDER BY thread_title ";
565
        $result = Database::query($sql);
566
567
        while ($obj = Database::fetch_object($result)) {
568
            $forumTopic = new ForumTopic($obj);
569
            $this->course->add_resource($forumTopic);
570
            $this->build_forum_posts($courseId, $obj->thread_id, $obj->forum_id);
571
        }
572
    }
573
574
    /**
575
     * Build the forum-posts
576
     * TODO: All tree structure of posts should be built, attachments for example.
577
     *
578
     * @param int   $courseId  Internal course ID
579
     * @param int   $thread_id Internal thread ID
580
     * @param int   $forum_id  Internal forum ID
581
     * @param array $idList
582
     */
583
    public function build_forum_posts(
584
        $courseId = 0,
585
        $thread_id = null,
586
        $forum_id = null,
587
        $idList = []
588
    ) {
589
        $table = Database::get_course_table(TABLE_FORUM_POST);
590
        $courseId = (int) $courseId;
591
        $sql = "SELECT * FROM $table WHERE c_id = $courseId ";
592
        if (!empty($thread_id) && !empty($forum_id)) {
593
            $forum_id = intval($forum_id);
594
            $thread_id = intval($thread_id);
595
            $sql .= " AND thread_id = $thread_id AND forum_id = $forum_id ";
596
        }
597
598
        if (!empty($idList)) {
599
            $idList = array_map('intval', $idList);
600
            $sql .= ' AND iid IN ("'.implode('","', $idList).'") ';
601
        }
602
603
        $sql .= " ORDER BY post_id ASC LIMIT 1";
604
        $db_result = Database::query($sql);
605
        while ($obj = Database::fetch_object($db_result)) {
606
            $forum_post = new ForumPost($obj);
607
            $this->course->add_resource($forum_post);
608
        }
609
    }
610
611
    /**
612
     * Build the links.
613
     *
614
     * @param int   $session_id      Internal session ID
615
     * @param int   $courseId        Internal course ID
616
     * @param bool  $withBaseContent Whether to include content from the course without session or not
617
     * @param array $idList          If you want to restrict the structure to only the given IDs
618
     */
619
    public function build_links(
620
        $session_id = 0,
621
        $courseId = 0,
622
        $withBaseContent = false,
623
        $idList = []
624
    ) {
625
        $categories = LinkManager::getLinkCategories(
626
            $courseId,
627
            $session_id,
628
            $withBaseContent
629
        );
630
631
        // Adding empty category
632
        $categories[] = ['id' => 0];
633
634
        foreach ($categories as $category) {
635
            $this->build_link_category($category);
636
637
            $links = LinkManager::getLinksPerCategory(
638
                $category['id'],
639
                $courseId,
640
                $session_id,
641
                $withBaseContent
642
            );
643
644
            foreach ($links as $item) {
645
                if (!empty($idList)) {
646
                    if (!in_array($item['id'], $idList)) {
647
                        continue;
648
                    }
649
                }
650
651
                $link = new Link(
652
                    $item['id'],
653
                    $item['title'],
654
                    $item['url'],
655
                    $item['description'],
656
                    $item['category_id'],
657
                    $item['on_homepage']
658
                );
659
                $link->target = $item['target'];
660
                $this->course->add_resource($link);
661
                $this->course->resources[RESOURCE_LINK][$item['id']]->add_linked_resource(
662
                    RESOURCE_LINKCATEGORY,
663
                    $item['category_id']
664
                );
665
            }
666
        }
667
    }
668
669
    /**
670
     * Build tool intro.
671
     *
672
     * @param int   $session_id      Internal session ID
673
     * @param int   $courseId        Internal course ID
674
     * @param bool  $withBaseContent Whether to include content from the course without session or not
675
     * @param array $idList          If you want to restrict the structure to only the given IDs
676
     */
677
    public function build_tool_intro(
678
        $session_id = 0,
679
        $courseId = 0,
680
        $withBaseContent = false,
681
        $idList = []
682
    ) {
683
        $table = Database::get_course_table(TABLE_TOOL_INTRO);
684
685
        $sessionCondition = api_get_session_condition(
686
            $session_id,
687
            true,
688
            $withBaseContent
689
        );
690
691
        $courseId = (int) $courseId;
692
693
        $sql = "SELECT * FROM $table
694
                WHERE c_id = $courseId $sessionCondition";
695
696
        $db_result = Database::query($sql);
697
        while ($obj = Database::fetch_object($db_result)) {
698
            $tool_intro = new ToolIntro($obj->id, $obj->intro_text);
699
            $this->course->add_resource($tool_intro);
700
        }
701
    }
702
703
    /**
704
     * Build a link category.
705
     *
706
     * @param int $id       Internal link ID
707
     * @param int $courseId Internal course ID
708
     *
709
     * @return int
710
     */
711
    public function build_link_category($category)
712
    {
713
        if (empty($category) || empty($category['category_title'])) {
714
            return 0;
715
        }
716
717
        $linkCategory = new LinkCategory(
718
            $category['id'],
719
            $category['category_title'],
720
            $category['description'],
721
            $category['display_order']
722
        );
723
        $this->course->add_resource($linkCategory);
724
725
        return $category['id'];
726
    }
727
728
    /**
729
     * Build the Quizzes.
730
     *
731
     * @param int   $session_id           Internal session ID
732
     * @param int   $courseId             Internal course ID
733
     * @param bool  $withBaseContent      Whether to include content from the course without session or not
734
     * @param array $idList               If you want to restrict the structure to only the given IDs
735
     * @param bool  $buildOrphanQuestions
736
     */
737
    public function build_quizzes(
738
        $session_id = 0,
739
        $courseId = 0,
740
        $withBaseContent = false,
741
        $idList = [],
742
        $buildOrphanQuestions = true
743
    ) {
744
        $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
745
        $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
746
        $table_doc = Database::get_course_table(TABLE_DOCUMENT);
747
748
        $courseId = (int) $courseId;
749
        $idCondition = '';
750
        if (!empty($idList)) {
751
            $idList = array_map('intval', $idList);
752
            $idCondition = ' iid IN ("'.implode('","', $idList).'") AND ';
753
        }
754
755
        if (!empty($courseId) && !empty($session_id)) {
756
            $session_id = (int) $session_id;
757
            if ($withBaseContent) {
758
                $sessionCondition = api_get_session_condition(
759
                    $session_id,
760
                    true,
761
                    true
762
                );
763
            } else {
764
                $sessionCondition = api_get_session_condition(
765
                    $session_id,
766
                    true
767
                );
768
            }
769
770
            // Select only quizzes with active = 0 or 1 (not -1 which is for deleted quizzes)
771
            $sql = "SELECT * FROM $table_qui
772
                    WHERE 
773
                      c_id = $courseId AND 
774
                      $idCondition
775
                      active >=0 
776
                      $sessionCondition ";
777
        } else {
778
            // Select only quizzes with active = 0 or 1 (not -1 which is for deleted quizzes)
779
            $sql = "SELECT * FROM $table_qui
780
                    WHERE 
781
                      c_id = $courseId AND 
782
                      $idCondition
783
                      active >=0 AND 
784
                      (session_id = 0 OR session_id IS NULL)";
785
        }
786
787
        $sql .= ' ORDER BY title';
788
        $db_result = Database::query($sql);
789
        $questionList = [];
790
        while ($obj = Database::fetch_object($db_result)) {
791
            if (strlen($obj->sound) > 0) {
792
                $sql = "SELECT id FROM $table_doc
793
                        WHERE c_id = $courseId AND path = '/audio/".$obj->sound."'";
794
                $res = Database::query($sql);
795
                $doc = Database::fetch_object($res);
796
                $obj->sound = $doc->id;
797
            }
798
            $this->findAndSetDocumentsInText($obj->description);
799
800
            $quiz = new Quiz($obj);
801
            $sql = 'SELECT * FROM '.$table_rel.'
802
                    WHERE c_id = '.$courseId.' AND exercice_id = '.$obj->id;
803
            $db_result2 = Database::query($sql);
804
            while ($obj2 = Database::fetch_object($db_result2)) {
805
                $quiz->add_question($obj2->question_id, $obj2->question_order);
806
                $questionList[] = $obj2->question_id;
807
            }
808
            $this->course->add_resource($quiz);
809
        }
810
811
        if (!empty($courseId)) {
812
            $this->build_quiz_questions($courseId, $questionList, $buildOrphanQuestions);
813
        } else {
814
            $this->build_quiz_questions(0, $questionList, $buildOrphanQuestions);
815
        }
816
    }
817
818
    /**
819
     * Build the Quiz-Questions.
820
     *
821
     * @param int   $courseId             Internal course ID
822
     * @param array $questionList
823
     * @param bool  $buildOrphanQuestions
824
     */
825
    public function build_quiz_questions($courseId = 0, $questionList = [], $buildOrphanQuestions = true)
826
    {
827
        $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
828
        $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
829
        $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION);
830
        $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER);
831
        $courseId = (int) $courseId;
832
        $questionListToString = implode("','", $questionList);
833
834
        // Building normal tests (many queries)
835
        $sql = "SELECT * FROM $table_que
836
                WHERE c_id = $courseId AND id IN ('$questionListToString')";
837
        $result = Database::query($sql);
838
839
        while ($obj = Database::fetch_object($result)) {
840
            // find the question category
841
            // @todo : need to be adapted for multi category questions in 1.10
842
            $question_category_id = TestCategory::getCategoryForQuestion(
843
                $obj->id,
844
                $courseId
845
            );
846
847
            $this->findAndSetDocumentsInText($obj->description);
848
849
            // build the backup resource question object
850
            $question = new QuizQuestion(
851
                $obj->id,
852
                $obj->question,
853
                $obj->description,
854
                $obj->ponderation,
855
                $obj->type,
856
                $obj->position,
857
                $obj->picture,
858
                $obj->level,
859
                $obj->extra,
860
                $question_category_id
861
            );
862
            $question->addPicture($this);
863
864
            $sql = 'SELECT * FROM '.$table_ans.'
865
                    WHERE c_id = '.$courseId.' AND question_id = '.$obj->id;
866
            $db_result2 = Database::query($sql);
867
            while ($obj2 = Database::fetch_object($db_result2)) {
868
                $question->add_answer(
869
                    $obj2->id,
870
                    $obj2->answer,
871
                    $obj2->correct,
872
                    $obj2->comment,
873
                    $obj2->ponderation,
874
                    $obj2->position,
875
                    $obj2->hotspot_coordinates,
876
                    $obj2->hotspot_type
877
                );
878
879
                $this->findAndSetDocumentsInText($obj2->answer);
880
                $this->findAndSetDocumentsInText($obj2->comment);
881
882
                if ($obj->type == MULTIPLE_ANSWER_TRUE_FALSE) {
883
                    $table_options = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
884
                    $sql = 'SELECT * FROM '.$table_options.'
885
                            WHERE c_id = '.$courseId.' AND question_id = '.$obj->id;
886
                    $db_result3 = Database::query($sql);
887
                    while ($obj3 = Database::fetch_object($db_result3)) {
888
                        $question_option = new QuizQuestionOption($obj3);
889
                        $question->add_option($question_option);
890
                    }
891
                }
892
            }
893
            $this->course->add_resource($question);
894
        }
895
896
        if ($buildOrphanQuestions) {
897
            // Building a fictional test for collecting orphan questions.
898
            // When a course is emptied this option should be activated (true).
899
            //$build_orphan_questions = !empty($_POST['recycle_option']);
900
901
            // 1st union gets the orphan questions from deleted exercises
902
            // 2nd union gets the orphan questions from question that were deleted in a exercise.
903
            $sql = " (
904
                        SELECT question_id, q.* FROM $table_que q
905
                        INNER JOIN $table_rel r
906
                        ON (q.c_id = r.c_id AND q.id = r.question_id)
907
                        INNER JOIN $table_qui ex
908
                        ON (ex.id = r.exercice_id AND ex.c_id = r.c_id)
909
                        WHERE ex.c_id = $courseId AND ex.active = '-1'
910
                    )
911
                    UNION
912
                     (
913
                        SELECT question_id, q.* FROM $table_que q
914
                        left OUTER JOIN $table_rel r
915
                        ON (q.c_id = r.c_id AND q.id = r.question_id)
916
                        WHERE q.c_id = $courseId AND r.question_id is null
917
                     )
918
                     UNION
919
                     (
920
                        SELECT question_id, q.* FROM $table_que q
921
                        INNER JOIN $table_rel r
922
                        ON (q.c_id = r.c_id AND q.id = r.question_id)
923
                        WHERE r.c_id = $courseId AND (r.exercice_id = '-1' OR r.exercice_id = '0')
924
                     )
925
                 ";
926
927
            $result = Database::query($sql);
928
            if (Database::num_rows($result) > 0) {
929
                $orphanQuestionIds = [];
930
                while ($obj = Database::fetch_object($result)) {
931
                    // Orphan questions
932
                    if (!empty($obj->question_id)) {
933
                        $obj->id = $obj->question_id;
934
                    }
935
936
                    // Avoid adding the same question twice
937
                    if (!isset($this->course->resources[$obj->id])) {
938
                        // find the question category
939
                        // @todo : need to be adapted for multi category questions in 1.10
940
                        $question_category_id = TestCategory::getCategoryForQuestion($obj->id, $courseId);
941
                        $question = new QuizQuestion(
942
                            $obj->id,
943
                            $obj->question,
944
                            $obj->description,
945
                            $obj->ponderation,
946
                            $obj->type,
947
                            $obj->position,
948
                            $obj->picture,
949
                            $obj->level,
950
                            $obj->extra,
951
                            $question_category_id
952
                        );
953
                        $question->addPicture($this);
954
                        $sql = "SELECT * FROM $table_ans
955
                                WHERE c_id = $courseId AND question_id = ".$obj->id;
956
                        $db_result2 = Database::query($sql);
957
                        if (Database::num_rows($db_result2)) {
958
                            while ($obj2 = Database::fetch_object($db_result2)) {
959
                                $question->add_answer(
960
                                    $obj2->id,
961
                                    $obj2->answer,
962
                                    $obj2->correct,
963
                                    $obj2->comment,
964
                                    $obj2->ponderation,
965
                                    $obj2->position,
966
                                    $obj2->hotspot_coordinates,
967
                                    $obj2->hotspot_type
968
                                );
969
                            }
970
                            $orphanQuestionIds[] = $obj->id;
971
                        }
972
                        $this->course->add_resource($question);
973
                    }
974
                }
975
            }
976
        }
977
978
        $obj = [
979
            'id' => -1,
980
            'title' => get_lang('OrphanQuestions'),
981
            'type' => 2,
982
        ];
983
        $newQuiz = new Quiz((object) $obj);
984
        if (!empty($orphanQuestionIds)) {
985
            foreach ($orphanQuestionIds as $index => $orphanId) {
986
                $order = $index + 1;
987
                $newQuiz->add_question($orphanId, $order);
988
            }
989
        }
990
        $this->course->add_resource($newQuiz);
991
    }
992
993
    /**
994
     * @deprecated
995
     * Build the orphan questions
996
     */
997
    public function build_quiz_orphan_questions()
998
    {
999
        $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
1000
        $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
1001
        $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION);
1002
        $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER);
1003
1004
        $courseId = api_get_course_int_id();
1005
1006
        $sql = 'SELECT *
1007
                FROM '.$table_que.' as questions
1008
                LEFT JOIN '.$table_rel.' as quizz_questions
1009
                ON questions.id=quizz_questions.question_id
1010
                LEFT JOIN '.$table_qui.' as exercises
1011
                ON quizz_questions.exercice_id = exercises.id
1012
                WHERE
1013
                    questions.c_id = quizz_questions.c_id AND
1014
                    questions.c_id = exercises.c_id AND
1015
                    exercises.c_id = '.$courseId.' AND
1016
                    (quizz_questions.exercice_id IS NULL OR
1017
                    exercises.active = -1)';
1018
1019
        $db_result = Database::query($sql);
1020
        if (Database::num_rows($db_result) > 0) {
1021
            // This is the fictional test for collecting orphan questions.
1022
            $orphan_questions = new Quiz(
1023
                -1,
1024
                get_lang('OrphanQuestions', ''),
1025
                '',
1026
                0,
1027
                0,
1028
                1,
1029
                '',
1030
                0
1031
            );
1032
1033
            $this->course->add_resource($orphan_questions);
1034
            while ($obj = Database::fetch_object($db_result)) {
1035
                $question = new QuizQuestion(
1036
                    $obj->id,
1037
                    $obj->question,
1038
                    $obj->description,
1039
                    $obj->ponderation,
1040
                    $obj->type,
1041
                    $obj->position,
1042
                    $obj->picture,
1043
                    $obj->level,
1044
                    $obj->extra
1045
                );
1046
                $question->addPicture($this);
1047
1048
                $sql = 'SELECT * FROM '.$table_ans.' WHERE question_id = '.$obj->id;
1049
                $db_result2 = Database::query($sql);
1050
                while ($obj2 = Database::fetch_object($db_result2)) {
1051
                    $question->add_answer(
1052
                        $obj2->id,
1053
                        $obj2->answer,
1054
                        $obj2->correct,
1055
                        $obj2->comment,
1056
                        $obj2->ponderation,
1057
                        $obj2->position,
1058
                        $obj2->hotspot_coordinates,
1059
                        $obj2->hotspot_type
1060
                    );
1061
                }
1062
                $this->course->add_resource($question);
1063
            }
1064
        }
1065
    }
1066
1067
    /**
1068
     * Build the test category.
1069
     *
1070
     * @param int   $sessionId       Internal session ID
1071
     * @param int   $courseId        Internal course ID
1072
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1073
     * @param array $idList          If you want to restrict the structure to only the given IDs
1074
     *
1075
     * @todo add course session
1076
     */
1077
    public function build_test_category(
1078
        $sessionId = 0,
1079
        $courseId = 0,
1080
        $withBaseContent = false,
1081
        $idList = []
1082
    ) {
1083
        // get all test category in course
1084
        $categories = TestCategory::getCategoryListInfo('', $courseId);
1085
        foreach ($categories as $category) {
1086
            $this->findAndSetDocumentsInText($category->description);
1087
1088
            /** @var TestCategory $category */
1089
            $courseCopyTestCategory = new CourseCopyTestCategory(
1090
                $category->id,
1091
                $category->name,
1092
                $category->description
1093
            );
1094
            $this->course->add_resource($courseCopyTestCategory);
1095
        }
1096
    }
1097
1098
    /**
1099
     * Build the Surveys.
1100
     *
1101
     * @param int   $session_id      Internal session ID
1102
     * @param int   $courseId        Internal course ID
1103
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1104
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1105
     */
1106
    public function build_surveys(
1107
        $session_id = 0,
1108
        $courseId = 0,
1109
        $withBaseContent = false,
1110
        $id_list = []
1111
    ) {
1112
        $table_survey = Database::get_course_table(TABLE_SURVEY);
1113
        $table_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1114
1115
        $courseId = (int) $courseId;
1116
1117
        $sessionCondition = api_get_session_condition(
1118
            $session_id,
1119
            true,
1120
            $withBaseContent
1121
        );
1122
1123
        $sql = 'SELECT * FROM '.$table_survey.'
1124
                WHERE c_id = '.$courseId.' '.$sessionCondition;
1125
        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...
1126
            $sql .= " AND iid IN (".implode(', ', $id_list).")";
1127
        }
1128
        $db_result = Database::query($sql);
1129
        while ($obj = Database::fetch_object($db_result)) {
1130
            $survey = new Survey(
1131
                $obj->survey_id,
1132
                $obj->code,
1133
                $obj->title,
1134
                $obj->subtitle,
1135
                $obj->author,
1136
                $obj->lang,
1137
                $obj->avail_from,
1138
                $obj->avail_till,
1139
                $obj->is_shared,
1140
                $obj->template,
1141
                $obj->intro,
1142
                $obj->surveythanks,
1143
                $obj->creation_date,
1144
                $obj->invited,
1145
                $obj->answered,
1146
                $obj->invite_mail,
1147
                $obj->reminder_mail,
1148
                $obj->one_question_per_page,
1149
                $obj->shuffle
1150
            );
1151
            $sql = 'SELECT * FROM '.$table_question.'
1152
                    WHERE c_id = '.$courseId.' AND survey_id = '.$obj->survey_id;
1153
            $db_result2 = Database::query($sql);
1154
            while ($obj2 = Database::fetch_object($db_result2)) {
1155
                $survey->add_question($obj2->question_id);
1156
            }
1157
            $this->course->add_resource($survey);
1158
        }
1159
        $this->build_survey_questions($courseId);
1160
    }
1161
1162
    /**
1163
     * Build the Survey Questions.
1164
     *
1165
     * @param int $courseId Internal course ID
1166
     */
1167
    public function build_survey_questions($courseId)
1168
    {
1169
        $table_que = Database::get_course_table(TABLE_SURVEY_QUESTION);
1170
        $table_opt = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1171
1172
        $courseId = (int) $courseId;
1173
        $idList = isset($this->specific_id_list['surveys']) ? $this->specific_id_list['surveys'] : [];
1174
1175
        $sql = 'SELECT * FROM '.$table_que.' WHERE c_id = '.$courseId.'  ';
1176
1177
        if (!empty($idList)) {
1178
            $sql .= " AND survey_id IN (".implode(', ', $idList).")";
1179
        }
1180
1181
        $db_result = Database::query($sql);
1182
        $is_required = 0;
1183
        while ($obj = Database::fetch_object($db_result)) {
1184
            if (api_get_configuration_value('allow_required_survey_questions')) {
1185
                if (isset($obj->is_required)) {
1186
                    $is_required = $obj->is_required;
1187
                }
1188
            }
1189
            $question = new SurveyQuestion(
1190
                $obj->question_id,
1191
                $obj->survey_id,
1192
                $obj->survey_question,
1193
                $obj->survey_question_comment,
1194
                $obj->type,
1195
                $obj->display,
1196
                $obj->sort,
1197
                $obj->shared_question_id,
1198
                $obj->max_value,
1199
                $is_required
1200
            );
1201
            $sql = 'SELECT * FROM '.$table_opt.'
1202
                    WHERE c_id = '.$courseId.' AND question_id = '.$obj->question_id;
1203
            $db_result2 = Database::query($sql);
1204
            while ($obj2 = Database::fetch_object($db_result2)) {
1205
                $question->add_answer($obj2->option_text, $obj2->sort);
1206
            }
1207
            $this->course->add_resource($question);
1208
        }
1209
    }
1210
1211
    /**
1212
     * Build the announcements.
1213
     *
1214
     * @param int   $session_id      Internal session ID
1215
     * @param int   $courseId        Internal course ID
1216
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1217
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1218
     */
1219
    public function build_announcements(
1220
        $session_id = 0,
1221
        $courseId = 0,
1222
        $withBaseContent = false,
1223
        $id_list = []
1224
    ) {
1225
        $table = Database::get_course_table(TABLE_ANNOUNCEMENT);
1226
1227
        $sessionCondition = api_get_session_condition(
1228
            $session_id,
1229
            true,
1230
            $withBaseContent
1231
        );
1232
1233
        $courseId = (int) $courseId;
1234
1235
        $sql = 'SELECT * FROM '.$table.'
1236
                WHERE c_id = '.$courseId.' '.$sessionCondition;
1237
        $db_result = Database::query($sql);
1238
        $table_attachment = Database::get_course_table(
1239
            TABLE_ANNOUNCEMENT_ATTACHMENT
1240
        );
1241
        while ($obj = Database::fetch_object($db_result)) {
1242
            if (empty($obj->id)) {
1243
                continue;
1244
            }
1245
            $sql = 'SELECT path, comment, filename, size
1246
                    FROM '.$table_attachment.'
1247
                    WHERE c_id = '.$courseId.' AND announcement_id = '.$obj->id.'';
1248
            $result = Database::query($sql);
1249
            $attachment_obj = Database::fetch_object($result);
1250
            $att_path = $att_filename = $att_size = $atth_comment = '';
1251
1252
            if (!empty($attachment_obj)) {
1253
                $att_path = $attachment_obj->path;
1254
                $att_filename = $attachment_obj->filename;
1255
                $att_size = $attachment_obj->size;
1256
                $atth_comment = $attachment_obj->comment;
1257
            }
1258
1259
            $announcement = new Announcement(
1260
                $obj->id,
1261
                $obj->title,
1262
                $obj->content,
1263
                $obj->end_date,
1264
                $obj->display_order,
1265
                $obj->email_sent,
1266
                $att_path,
1267
                $att_filename,
1268
                $att_size,
1269
                $atth_comment
1270
            );
1271
            $this->course->add_resource($announcement);
1272
        }
1273
    }
1274
1275
    /**
1276
     * Build the events.
1277
     *
1278
     * @param int   $session_id      Internal session ID
1279
     * @param int   $courseId        Internal course ID
1280
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1281
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1282
     */
1283
    public function build_events(
1284
        $session_id = 0,
1285
        $courseId = 0,
1286
        $withBaseContent = false,
1287
        $id_list = []
1288
    ) {
1289
        $table = Database::get_course_table(TABLE_AGENDA);
1290
1291
        $sessionCondition = api_get_session_condition(
1292
            $session_id,
1293
            true,
1294
            $withBaseContent
1295
        );
1296
1297
        $courseId = (int) $courseId;
1298
1299
        $sql = 'SELECT * FROM '.$table.'
1300
                WHERE c_id = '.$courseId.' '.$sessionCondition;
1301
        $db_result = Database::query($sql);
1302
        while ($obj = Database::fetch_object($db_result)) {
1303
            $table_attachment = Database::get_course_table(
1304
                TABLE_AGENDA_ATTACHMENT
1305
            );
1306
            $sql = 'SELECT path, comment, filename, size
1307
                    FROM '.$table_attachment.'
1308
                    WHERE c_id = '.$courseId.' AND agenda_id = '.$obj->id.'';
1309
            $result = Database::query($sql);
1310
1311
            $attachment_obj = Database::fetch_object($result);
1312
            $att_path = $att_filename = $att_size = $atth_comment = '';
1313
            if (!empty($attachment_obj)) {
1314
                $att_path = $attachment_obj->path;
1315
                $att_filename = $attachment_obj->filename;
1316
                $att_size = $attachment_obj->size;
1317
                $atth_comment = $attachment_obj->comment;
1318
            }
1319
            $event = new CalendarEvent(
1320
                $obj->id,
1321
                $obj->title,
1322
                $obj->content,
1323
                $obj->start_date,
1324
                $obj->end_date,
1325
                $att_path,
1326
                $att_filename,
1327
                $att_size,
1328
                $atth_comment,
1329
                $obj->all_day
1330
            );
1331
            $this->course->add_resource($event);
1332
        }
1333
    }
1334
1335
    /**
1336
     * Build the course-descriptions.
1337
     *
1338
     * @param int   $session_id      Internal session ID
1339
     * @param int   $courseId        Internal course ID
1340
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1341
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1342
     */
1343
    public function build_course_descriptions(
1344
        $session_id = 0,
1345
        $courseId = 0,
1346
        $withBaseContent = false,
1347
        $id_list = []
1348
    ) {
1349
        $table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
1350
        $courseId = (int) $courseId;
1351
1352
        if (!empty($session_id) && !empty($courseId)) {
1353
            $session_id = intval($session_id);
1354
            if ($withBaseContent) {
1355
                $sessionCondition = api_get_session_condition(
1356
                    $session_id,
1357
                    true,
1358
                    true
1359
                );
1360
            } else {
1361
                $sessionCondition = api_get_session_condition(
1362
                    $session_id,
1363
                    true
1364
                );
1365
            }
1366
            $sql = 'SELECT * FROM '.$table.'
1367
                    WHERE c_id = '.$courseId.' '.$sessionCondition;
1368
        } else {
1369
            $table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
1370
            $sql = 'SELECT * FROM '.$table.'
1371
                    WHERE c_id = '.$courseId.'  AND session_id = 0';
1372
        }
1373
1374
        $db_result = Database::query($sql);
1375
        while ($obj = Database::fetch_object($db_result)) {
1376
            $cd = new CourseDescription(
1377
                $obj->id,
1378
                $obj->title,
1379
                $obj->content,
1380
                $obj->description_type
1381
            );
1382
            $this->course->add_resource($cd);
1383
        }
1384
    }
1385
1386
    /**
1387
     * @param int   $session_id
1388
     * @param int   $courseId
1389
     * @param bool  $withBaseContent
1390
     * @param array $idList
1391
     */
1392
    public function build_learnpath_category($session_id = 0, $courseId = 0, $withBaseContent = false, $idList = [])
1393
    {
1394
        $categories = \learnpath::getCategories($courseId);
1395
1396
        /** @var CLpCategory $item */
1397
        foreach ($categories as $item) {
1398
            $categoryId = $item->getId();
1399
            if (!empty($idList)) {
1400
                if (!in_array($categoryId, $idList)) {
1401
                    continue;
1402
                }
1403
            }
1404
            $category = new LearnPathCategory($categoryId, $item);
1405
            $this->course->add_resource($category);
1406
        }
1407
    }
1408
1409
    /**
1410
     * Build the learnpaths.
1411
     *
1412
     * @param int   $session_id      Internal session ID
1413
     * @param int   $courseId        Internal course ID
1414
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1415
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1416
     * @param bool  $addScormFolder
1417
     */
1418
    public function build_learnpaths(
1419
        $session_id = 0,
1420
        $courseId = 0,
1421
        $withBaseContent = false,
1422
        $id_list = [],
1423
        $addScormFolder = true
1424
    ) {
1425
        $table_main = Database::get_course_table(TABLE_LP_MAIN);
1426
        $table_item = Database::get_course_table(TABLE_LP_ITEM);
1427
        $table_tool = Database::get_course_table(TABLE_TOOL_LIST);
1428
1429
        $courseId = (int) $courseId;
1430
1431
        if (!empty($session_id) && !empty($courseId)) {
1432
            $session_id = intval($session_id);
1433
            if ($withBaseContent) {
1434
                $sessionCondition = api_get_session_condition(
1435
                    $session_id,
1436
                    true,
1437
                    true
1438
                );
1439
            } else {
1440
                $sessionCondition = api_get_session_condition(
1441
                    $session_id,
1442
                    true
1443
                );
1444
            }
1445
            $sql = 'SELECT * FROM '.$table_main.'
1446
                    WHERE c_id = '.$courseId.'  '.$sessionCondition;
1447
        } else {
1448
            $sql = 'SELECT * FROM '.$table_main.'
1449
                    WHERE c_id = '.$courseId.' AND (session_id = 0 OR session_id IS NULL)';
1450
        }
1451
1452
        if (!empty($id_list)) {
1453
            $id_list = array_map('intval', $id_list);
1454
            $sql .= " AND id IN (".implode(', ', $id_list).") ";
1455
        }
1456
1457
        $result = Database::query($sql);
1458
        if ($result) {
0 ignored issues
show
introduced by
$result is of type Doctrine\DBAL\Driver\Statement, thus it always evaluated to true.
Loading history...
1459
            while ($obj = Database::fetch_object($result)) {
1460
                $items = [];
1461
                $sql = "SELECT * FROM $table_item
1462
                        WHERE c_id = '$courseId' AND lp_id = ".$obj->id;
1463
                $resultItem = Database::query($sql);
1464
                while ($obj_item = Database::fetch_object($resultItem)) {
1465
                    $item['id'] = $obj_item->iid;
1466
                    $item['item_type'] = $obj_item->item_type;
1467
                    $item['ref'] = $obj_item->ref;
1468
                    $item['title'] = $obj_item->title;
1469
                    $item['description'] = $obj_item->description;
1470
                    $item['path'] = $obj_item->path;
1471
                    $item['min_score'] = $obj_item->min_score;
1472
                    $item['max_score'] = $obj_item->max_score;
1473
                    $item['mastery_score'] = $obj_item->mastery_score;
1474
                    $item['parent_item_id'] = $obj_item->parent_item_id;
1475
                    $item['previous_item_id'] = $obj_item->previous_item_id;
1476
                    $item['next_item_id'] = $obj_item->next_item_id;
1477
                    $item['display_order'] = $obj_item->display_order;
1478
                    $item['prerequisite'] = $obj_item->prerequisite;
1479
                    $item['parameters'] = $obj_item->parameters;
1480
                    $item['launch_data'] = $obj_item->launch_data;
1481
                    $item['audio'] = $obj_item->audio;
1482
                    $items[] = $item;
1483
                }
1484
1485
                $sql = "SELECT id FROM $table_tool
1486
                        WHERE
1487
                            c_id = $courseId AND
1488
                            (link LIKE '%lp_controller.php%lp_id=".$obj->id."%' AND image='scormbuilder.gif') AND
1489
                            visibility = '1' ";
1490
                $db_tool = Database::query($sql);
1491
                $visibility = '0';
1492
                if (Database::num_rows($db_tool)) {
1493
                    $visibility = '1';
1494
                }
1495
1496
                $lp = new CourseCopyLearnpath(
1497
                    $obj->id,
1498
                    $obj->lp_type,
1499
                    $obj->name,
1500
                    $obj->path,
1501
                    $obj->ref,
1502
                    $obj->description,
1503
                    $obj->content_local,
1504
                    $obj->default_encoding,
1505
                    $obj->default_view_mod,
1506
                    $obj->prevent_reinit,
1507
                    $obj->force_commit,
1508
                    $obj->content_maker,
1509
                    $obj->display_order,
1510
                    $obj->js_lib,
1511
                    $obj->content_license,
1512
                    $obj->debug,
1513
                    $visibility,
1514
                    $obj->author,
1515
                    $obj->preview_image,
1516
                    $obj->use_max_score,
1517
                    $obj->autolaunch,
1518
                    $obj->created_on,
1519
                    $obj->modified_on,
1520
                    $obj->publicated_on,
1521
                    $obj->expired_on,
1522
                    $obj->session_id,
1523
                    $obj->category_id,
1524
                    $items
1525
                );
1526
1527
                $this->course->add_resource($lp);
1528
1529
                if (!empty($obj->preview_image)) {
1530
                    // Add LP teacher image
1531
                    $asset = new Asset(
1532
                        $obj->preview_image,
1533
                        '/upload/learning_path/images/'.$obj->preview_image,
1534
                        '/upload/learning_path/images/'.$obj->preview_image
1535
                    );
1536
                    $this->course->add_resource($asset);
1537
                }
1538
            }
1539
        }
1540
1541
        // Save scorm directory (previously build_scorm_documents())
1542
        if ($addScormFolder) {
1543
            $i = 1;
1544
            if ($dir = @opendir($this->course->backup_path.'/scorm')) {
1545
                while ($file = readdir($dir)) {
1546
                    if (is_dir($this->course->backup_path.'/scorm/'.$file) &&
1547
                        !in_array($file, ['.', '..'])
1548
                    ) {
1549
                        $doc = new ScormDocument($i++, '/'.$file, $file);
1550
                        $this->course->add_resource($doc);
1551
                    }
1552
                }
1553
                closedir($dir);
1554
            }
1555
        }
1556
    }
1557
1558
    /**
1559
     * Build the glossaries.
1560
     *
1561
     * @param int   $session_id      Internal session ID
1562
     * @param int   $courseId        Internal course ID
1563
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1564
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1565
     */
1566
    public function build_glossary(
1567
        $session_id = 0,
1568
        $courseId = 0,
1569
        $withBaseContent = false,
1570
        $id_list = []
1571
    ) {
1572
        $table_glossary = Database::get_course_table(TABLE_GLOSSARY);
1573
1574
        $courseId = (int) $courseId;
1575
1576
        if (!empty($session_id) && !empty($courseId)) {
1577
            $session_id = intval($session_id);
1578
            if ($withBaseContent) {
1579
                $sessionCondition = api_get_session_condition(
1580
                    $session_id,
1581
                    true,
1582
                    true
1583
                );
1584
            } else {
1585
                $sessionCondition = api_get_session_condition(
1586
                    $session_id,
1587
                    true
1588
                );
1589
            }
1590
1591
            //@todo check this queries are the same ...
1592
            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...
1593
                $sql = 'SELECT * FROM '.$table_glossary.' g
1594
                        WHERE g.c_id = '.$courseId.' '.$sessionCondition;
1595
            } else {
1596
                $sql = 'SELECT * FROM '.$table_glossary.' g
1597
                        WHERE g.c_id = '.$courseId.' '.$sessionCondition;
1598
            }
1599
        } else {
1600
            $table_glossary = Database::get_course_table(TABLE_GLOSSARY);
1601
            //@todo check this queries are the same ... ayayay
1602
            if (!empty($this->course->type) && $this->course->type == 'partial') {
1603
                $sql = 'SELECT * FROM '.$table_glossary.' g
1604
                        WHERE g.c_id = '.$courseId.' AND (session_id = 0 OR session_id IS NULL)';
1605
            } else {
1606
                $sql = 'SELECT * FROM '.$table_glossary.' g
1607
                        WHERE g.c_id = '.$courseId.' AND (session_id = 0 OR session_id IS NULL)';
1608
            }
1609
        }
1610
        $db_result = Database::query($sql);
1611
        while ($obj = Database::fetch_object($db_result)) {
1612
            $doc = new Glossary(
1613
                $obj->glossary_id,
1614
                $obj->name,
1615
                $obj->description,
1616
                $obj->display_order
1617
            );
1618
            $this->course->add_resource($doc);
1619
        }
1620
    }
1621
1622
    /*
1623
     * Build session course by jhon
1624
     */
1625
    public function build_session_course()
1626
    {
1627
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
1628
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
1629
        $list_course = CourseManager::get_course_list();
1630
        $list = [];
1631
        foreach ($list_course as $_course) {
1632
            $this->course = new Course();
1633
            $this->course->code = $_course['code'];
1634
            $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...
1635
            $this->course->path = api_get_path(SYS_COURSE_PATH).$_course['directory'].'/';
1636
            $this->course->backup_path = api_get_path(SYS_COURSE_PATH).$_course['directory'];
0 ignored issues
show
Bug Best Practice introduced by
The property backup_path does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
1637
            $this->course->encoding = api_get_system_encoding(); //current platform encoding
1638
            $courseId = $_course['real_id'];
1639
            $sql = "SELECT s.id, name, c_id
1640
                    FROM $tbl_session_course sc
1641
                    INNER JOIN $tbl_session s
1642
                    ON sc.session_id = s.id
1643
                    WHERE sc.c_id = '$courseId' ";
1644
            $query_session = Database::query($sql);
1645
            while ($rows_session = Database::fetch_assoc($query_session)) {
1646
                $session = new CourseSession(
1647
                    $rows_session['id'],
1648
                    $rows_session['name']
1649
                );
1650
                $this->course->add_resource($session);
1651
            }
1652
            $list[] = $this->course;
1653
        }
1654
1655
        return $list;
1656
    }
1657
1658
    /**
1659
     * @param int   $session_id      Internal session ID
1660
     * @param int   $courseId        Internal course ID
1661
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1662
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1663
     */
1664
    public function build_wiki(
1665
        $session_id = 0,
1666
        $courseId = 0,
1667
        $withBaseContent = false,
1668
        $id_list = []
1669
    ) {
1670
        $tbl_wiki = Database::get_course_table(TABLE_WIKI);
1671
        $courseId = (int) $courseId;
1672
1673
        if (!empty($session_id) && !empty($courseId)) {
1674
            $session_id = intval($session_id);
1675
            if ($withBaseContent) {
1676
                $sessionCondition = api_get_session_condition(
1677
                    $session_id,
1678
                    true,
1679
                    true
1680
                );
1681
            } else {
1682
                $sessionCondition = api_get_session_condition(
1683
                    $session_id,
1684
                    true
1685
                );
1686
            }
1687
            $sql = 'SELECT * FROM '.$tbl_wiki.'
1688
                    WHERE c_id = '.$courseId.' '.$sessionCondition;
1689
        } else {
1690
            $tbl_wiki = Database::get_course_table(TABLE_WIKI);
1691
            $sql = 'SELECT * FROM '.$tbl_wiki.'
1692
                    WHERE c_id = '.$courseId.' AND (session_id = 0 OR session_id IS NULL)';
1693
        }
1694
        $db_result = Database::query($sql);
1695
        while ($obj = Database::fetch_object($db_result)) {
1696
            $wiki = new Wiki(
1697
                $obj->id,
1698
                $obj->page_id,
1699
                $obj->reflink,
1700
                $obj->title,
1701
                $obj->content,
1702
                $obj->user_id,
1703
                $obj->group_id,
1704
                $obj->dtime,
1705
                $obj->progress,
1706
                $obj->version
1707
            );
1708
            $this->course->add_resource($wiki);
1709
        }
1710
    }
1711
1712
    /**
1713
     * Build the Surveys.
1714
     *
1715
     * @param int   $session_id      Internal session ID
1716
     * @param int   $courseId        Internal course ID
1717
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1718
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1719
     */
1720
    public function build_thematic(
1721
        $session_id = 0,
1722
        $courseId = 0,
1723
        $withBaseContent = false,
1724
        $id_list = []
1725
    ) {
1726
        $table_thematic = Database::get_course_table(TABLE_THEMATIC);
1727
        $table_thematic_advance = Database::get_course_table(TABLE_THEMATIC_ADVANCE);
1728
        $table_thematic_plan = Database::get_course_table(TABLE_THEMATIC_PLAN);
1729
        $courseId = (int) $courseId;
1730
1731
        $courseInfo = api_get_course_info_by_id($courseId);
1732
        $session_id = intval($session_id);
1733
        if ($withBaseContent) {
1734
            $sessionCondition = api_get_session_condition(
1735
                $session_id,
1736
                true,
1737
                true
1738
            );
1739
        } else {
1740
            $sessionCondition = api_get_session_condition($session_id, true);
1741
        }
1742
1743
        $sql = "SELECT * FROM $table_thematic
1744
                WHERE c_id = $courseId $sessionCondition ";
1745
        $db_result = Database::query($sql);
1746
        while ($row = Database::fetch_array($db_result, 'ASSOC')) {
1747
            $thematic = new Thematic($row);
1748
            $sql = 'SELECT * FROM '.$table_thematic_advance.'
1749
                    WHERE c_id = '.$courseId.' AND thematic_id = '.$row['id'];
1750
1751
            $result = Database::query($sql);
1752
            while ($sub_row = Database::fetch_array($result, 'ASSOC')) {
1753
                $thematic->addThematicAdvance($sub_row);
1754
            }
1755
1756
            $items = api_get_item_property_by_tool(
1757
                'thematic_plan',
1758
                $courseInfo['code'],
1759
                $session_id
1760
            );
1761
1762
            $thematic_plan_id_list = [];
1763
            if (!empty($items)) {
1764
                foreach ($items as $item) {
1765
                    $thematic_plan_id_list[] = $item['ref'];
1766
                }
1767
            }
1768
            if (count($thematic_plan_id_list) > 0) {
1769
                $sql = "SELECT tp.*
1770
                        FROM $table_thematic_plan tp
1771
                            INNER JOIN $table_thematic t ON (t.id=tp.thematic_id)
1772
                        WHERE
1773
                            t.c_id = $courseId AND
1774
                            tp.c_id = $courseId AND
1775
                            thematic_id = {$row['id']}  AND
1776
                            tp.id IN (".implode(', ', $thematic_plan_id_list).") ";
1777
1778
                $result = Database::query($sql);
1779
                while ($sub_row = Database::fetch_array($result, 'ASSOC')) {
1780
                    $thematic->addThematicPlan($sub_row);
1781
                }
1782
            }
1783
            $this->course->add_resource($thematic);
1784
        }
1785
    }
1786
1787
    /**
1788
     * Build the attendances.
1789
     *
1790
     * @param int   $session_id      Internal session ID
1791
     * @param int   $courseId        Internal course ID
1792
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1793
     * @param array $id_list         If you want to restrict the structure to only the given IDs
1794
     */
1795
    public function build_attendance(
1796
        $session_id = 0,
1797
        $courseId = 0,
1798
        $withBaseContent = false,
1799
        $id_list = []
1800
    ) {
1801
        $table_attendance = Database::get_course_table(TABLE_ATTENDANCE);
1802
        $table_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1803
        $sessionCondition = api_get_session_condition($session_id, true, $withBaseContent);
1804
        $courseId = (int) $courseId;
1805
1806
        $sql = 'SELECT * FROM '.$table_attendance.'
1807
                WHERE c_id = '.$courseId.' '.$sessionCondition;
1808
        $db_result = Database::query($sql);
1809
        while ($row = Database::fetch_array($db_result, 'ASSOC')) {
1810
            $obj = new Attendance($row);
1811
            $sql = 'SELECT * FROM '.$table_attendance_calendar.'
1812
                    WHERE c_id = '.$courseId.' AND attendance_id = '.$row['id'];
1813
1814
            $result = Database::query($sql);
1815
            while ($sub_row = Database::fetch_array($result, 'ASSOC')) {
1816
                $obj->add_attendance_calendar($sub_row);
1817
            }
1818
            $this->course->add_resource($obj);
1819
        }
1820
    }
1821
1822
    /**
1823
     * Build the works (or "student publications", or "assignments").
1824
     *
1825
     * @param int   $session_id      Internal session ID
1826
     * @param int   $courseId        Internal course ID
1827
     * @param bool  $withBaseContent Whether to include content from the course without session or not
1828
     * @param array $idList          If you want to restrict the structure to only the given IDs
1829
     */
1830
    public function build_works(
1831
        $session_id = 0,
1832
        $courseId = 0,
1833
        $withBaseContent = false,
1834
        $idList = []
1835
    ) {
1836
        $table_work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1837
        $sessionCondition = api_get_session_condition(
1838
            $session_id,
1839
            true,
1840
            $withBaseContent
1841
        );
1842
        $courseId = (int) $courseId;
1843
1844
        $idCondition = '';
1845
        if (!empty($idList)) {
1846
            $idList = array_map('intval', $idList);
1847
            $idCondition = ' AND iid IN ("'.implode('","', $idList).'") ';
1848
        }
1849
1850
        $sql = "SELECT * FROM $table_work
1851
                WHERE
1852
                    c_id = $courseId                    
1853
                    $sessionCondition AND                    
1854
                    filetype = 'folder' AND
1855
                    parent_id = 0 AND
1856
                    active = 1
1857
                    $idCondition
1858
                ";
1859
        $result = Database::query($sql);
1860
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1861
            $obj = new Work($row);
1862
            $this->course->add_resource($obj);
1863
        }
1864
    }
1865
1866
    /**
1867
     * @param int  $session_id
1868
     * @param int  $courseId
1869
     * @param bool $withBaseContent
1870
     */
1871
    public function build_gradebook(
1872
        $session_id = 0,
1873
        $courseId = 0,
1874
        $withBaseContent = false
1875
    ) {
1876
        $courseInfo = api_get_course_info_by_id($courseId);
1877
        $courseCode = $courseInfo['code'];
1878
        $cats = Category:: load(
1879
            null,
1880
            null,
1881
            $courseCode,
1882
            null,
1883
            null,
1884
            $session_id
1885
        );
1886
1887
        if (!empty($cats)) {
1888
            /** @var Category $cat */
1889
            foreach ($cats as $cat) {
1890
                $cat->evaluations = $cat->get_evaluations(null, false);
1891
                $cat->links = $cat->get_links(null, false);
1892
                $cat->subCategories = $cat->get_subcategories(
1893
                    null,
1894
                    $courseCode,
1895
                    $session_id
1896
                );
1897
            }
1898
            $obj = new GradeBookBackup($cats);
1899
            $this->course->add_resource($obj);
1900
        }
1901
    }
1902
}
1903