Passed
Push — master ( 8c8eae...511b66 )
by Julito
11:06
created

CourseCategory::edit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 5
dl 0
loc 22
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Asset;
6
use Chamilo\CoreBundle\Entity\User;
7
use Chamilo\CoreBundle\Framework\Container;
8
use Chamilo\CoreBundle\Entity\CourseCategory as CourseCategoryEntity;
9
use Doctrine\Common\Collections\Criteria;
10
use Symfony\Component\HttpFoundation\File\UploadedFile;
11
12
/**
13
 * Class CourseCategory.
14
 */
15
class CourseCategory
16
{
17
18
    /**
19
     * Get category details from a simple category code.
20
     *
21
     * @param string|null $categoryCode The literal category code
22
     *
23
     * @return array
24
     */
25
    public static function getCategory(string $categoryCode = null)
26
    {
27
        if (!empty($categoryCode)) {
28
            $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
29
            $categoryCode = Database::escape_string($categoryCode);
30
            $sql = "SELECT * FROM $table WHERE code ='$categoryCode'";
31
            $result = Database::query($sql);
32
33
            if (Database::num_rows($result)) {
34
                $category = Database::fetch_array($result, 'ASSOC');
35
                if ($category) {
36
                    // Get access url id
37
                    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
38
                    $sql = "SELECT * FROM $table WHERE course_category_id = ".$category['id'];
39
                    $result = Database::query($sql);
40
                    $result = Database::fetch_array($result);
41
                    if ($result) {
42
                        $category['access_url_id'] = $result['access_url_id'];
43
                    }
44
45
                    return $category;
46
                }
47
            }
48
        }
49
50
        return [];
51
    }
52
53
    /**
54
     * Returns the category fields from the database from an int ID.
55
     *
56
     * @param int $categoryId The category ID
57
     *
58
     * @return array
59
     */
60
    public static function getCategoryById($categoryId)
61
    {
62
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
63
        $categoryId = (int) $categoryId;
64
        $sql = "SELECT * FROM $table WHERE id = $categoryId";
65
        $result = Database::query($sql);
66
        if (Database::num_rows($result)) {
67
            $category = Database::fetch_array($result, 'ASSOC');
68
            if ($category) {
69
                // Get access url id
70
                $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
71
                $sql = "SELECT * FROM $table WHERE course_category_id = ".$category['id'];
72
                $result = Database::query($sql);
73
                $result = Database::fetch_array($result);
74
                if ($result) {
75
                    $category['access_url_id'] = $result['access_url_id'];
76
                }
77
78
                return $category;
79
            }
80
        }
81
82
        return [];
83
    }
84
85
    /**
86
     * Returns a flat list of all course categories in this URL. If the
87
     * allow_base_course_category option is true, then also show the
88
     * course categories of the base URL.
89
     *
90
     * @return array [id, name, code, parent_id, tree_pos, children_count, number_courses]
91
     */
92
    public static function getAllCategories()
93
    {
94
        $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
95
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
96
97
        $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
98
        $conditions = " INNER JOIN $table a ON (t1.id = a.course_category_id)";
99
        $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
100
        $allowBaseCategories = api_get_configuration_value('allow_base_course_category');
101
        if ($allowBaseCategories) {
102
            $whereCondition = " AND (a.access_url_id = ".api_get_current_access_url_id()." OR a.access_url_id = 1) ";
103
        }
104
105
        $sql = "SELECT
106
                t1.id,
107
                t1.name,
108
                t1.code,
109
                t1.parent_id,
110
                t1.tree_pos,
111
                t1.children_count,
112
                COUNT(DISTINCT t3.code) AS number_courses
113
                FROM $tbl_category t1
114
                $conditions
115
                LEFT JOIN $tbl_course t3
116
                ON t3.category_id=t1.id
117
                WHERE 1=1
118
                    $whereCondition
119
                GROUP BY
120
                    t1.name,
121
                    t1.code,
122
                    t1.parent_id,
123
                    t1.tree_pos,
124
                    t1.children_count
125
                ORDER BY t1.parent_id, t1.tree_pos";
126
127
        $result = Database::query($sql);
128
129
        return Database::store_result($result, 'ASSOC');
130
    }
131
132
    /**
133
     * @param string $code
134
     * @param string $name
135
     * @param string $canHaveCourses
136
     * @param null|int    $parentId
137
     */
138
    public static function add($code, $name, $canHaveCourses, $description, $parentId = null): ?CourseCategoryEntity
139
    {
140
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
141
        $code = trim($code);
142
        $name = trim($name);
143
        $parentId = (int) $parentId;
144
145
        $code = CourseManager::generate_course_code($code);
146
        $sql = "SELECT 1 FROM $table
147
                WHERE code = '".Database::escape_string($code)."'";
148
        $result = Database::query($sql);
149
        if (Database::num_rows($result)) {
150
            return null;
151
        }
152
        $result = Database::query("SELECT MAX(tree_pos) AS maxTreePos FROM $table");
153
        $row = Database::fetch_array($result);
154
        $tree_pos = $row['maxTreePos'] + 1;
155
        $parentId = empty($parentId) ? null : $parentId;
156
157
        $repo = Container::getCourseCategoryRepository();
158
        $category = new CourseCategoryEntity();
159
        $category
160
            ->setName($name)
161
            ->setCode($code)
162
            ->setDescription($description)
163
            ->setTreePos($tree_pos)
164
            ->setAuthCourseChild($canHaveCourses)
165
            ->setAuthCatChild('TRUE');
166
167
        if (!empty($parentId)) {
168
            $category->setParent($repo->find($parentId));
169
        }
170
171
        $repo->save($category);
172
173
        $categoryId = $category->getId();
174
        if ($categoryId) {
175
            self::updateParentCategoryChildrenCount($parentId, 1);
176
            UrlManager::addCourseCategoryListToUrl(
177
                [$categoryId],
178
                [api_get_current_access_url_id()]
179
            );
180
181
            return $category;
182
        }
183
184
        return null;
185
    }
186
187
    /**
188
     * Recursive function that updates the count of children in the parent.
189
     *
190
     * @param string $categoryId Category ID
191
     * @param int    $delta      The number to add or delete (1 to add one, -1 to remove one)
192
     */
193
    public static function updateParentCategoryChildrenCount($categoryId, $delta = 1)
194
    {
195
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
196
        $categoryId = Database::escape_string($categoryId);
197
        $delta = (int) $delta;
198
        // First get to the highest level possible in the tree
199
        $result = Database::query("SELECT parent_id FROM $table WHERE id = '$categoryId'");
200
        $row = Database::fetch_array($result);
201
        if (false !== $row && 0 != $row['parent_id']) {
202
            // if a parent was found, enter there to see if he's got one more parent
203
            self::updateParentCategoryChildrenCount($row['parent_id'], $delta);
204
        }
205
        // Now we're at the top, get back down to update each child
206
        $sql = "UPDATE $table SET children_count = (children_count - ".abs($delta).") WHERE id = '$categoryId'";
207
        if ($delta >= 0) {
208
            $sql = "UPDATE $table SET children_count = (children_count + $delta) WHERE id = '$categoryId'";
209
        }
210
        Database::query($sql);
211
    }
212
213
    public static function delete($categoryId): bool
214
    {
215
        $repo = Container::getCourseCategoryRepository();
216
        $category = $repo->find($categoryId);
217
        if (null === $category) {
218
            return false;
219
        }
220
221
        $repo->delete($category);
222
223
        return true;
224
225
        // @todo check that doctrine deletes all the connections.
226
        /*$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
227
        $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
228
        $node = Database::escape_string($node);
229
        $result = Database::query("SELECT parent_id, tree_pos FROM $tbl_category WHERE code='$node'");
230
231
        if ($row = Database::fetch_array($result)) {
232
            if (!empty($row['parent_id'])) {
233
                Database::query(
234
                    "UPDATE $tbl_course SET category_id = '".$row['parent_id']."' WHERE category_id = {$category['id']}"
235
                );
236
                Database::query("UPDATE $tbl_category SET parent_id='".$row['parent_id']."' WHERE parent_id='$node'");
237
            } else {
238
                Database::query("UPDATE $tbl_course SET category_id = NULL WHERE category_id = ".$category['id']);
239
                Database::query("UPDATE $tbl_category SET parent_id=NULL WHERE parent_id='$node'");
240
            }
241
242
            $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
243
            $sql = "DELETE FROM $table WHERE course_category_id = ".$category['id'];
244
245
            Database::query($sql);
246
            Database::query("UPDATE $tbl_category SET tree_pos=tree_pos-1 WHERE tree_pos > '".$row['tree_pos']."'");
247
            Database::query("DELETE FROM $tbl_category WHERE code='$node'");
248
249
            if (!empty($row['parent_id'])) {
250
                self::updateParentCategoryChildrenCount($row['parent_id'], -1);
251
            }
252
253
            return true;
254
        }*/
255
    }
256
257
    public static function edit($categoryId, $name, $canHaveCourses, $code, $description): CourseCategoryEntity
258
    {
259
        $name = trim(Database::escape_string($name));
260
        $canHaveCourses = Database::escape_string($canHaveCourses);
261
262
        $repo = Container::getCourseCategoryRepository();
263
        $category = $repo->find($categoryId);
264
265
        $category
266
            ->setCode($name)
267
            ->setName($name)
268
            ->setDescription($description)
269
            ->setAuthCourseChild($canHaveCourses);
270
271
        $repo->save($category);
272
273
        // Updating children
274
        /*$sql = "UPDATE $tbl_category SET parent_id = '$code'
275
            WHERE parent_id = '$old_code'";
276
        Database::query($sql);*/
277
278
        return $category;
279
    }
280
281
    /**
282
     * Move a node up on display.
283
     *
284
     * @param string $code
285
     * @param int    $tree_pos
286
     * @param string $parent_id
287
     *
288
     * @return bool
289
     */
290
    public static function moveNodeUp($code, $tree_pos, $parent_id)
291
    {
292
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
293
        $code = Database::escape_string($code);
294
        $tree_pos = (int) $tree_pos;
295
        $parent_id = Database::escape_string($parent_id);
296
297
        $parentIdCondition = " AND (parent_id IS NULL OR parent_id = '' )";
298
        if (!empty($parent_id)) {
299
            $parentIdCondition = " AND parent_id = '$parent_id' ";
300
        }
301
302
        $sql = "SELECT code,tree_pos
303
                FROM $table
304
                WHERE
305
                    tree_pos < $tree_pos
306
                    $parentIdCondition
307
                ORDER BY tree_pos DESC
308
                LIMIT 0,1";
309
310
        $result = Database::query($sql);
311
        if (!$row = Database::fetch_array($result)) {
312
            $sql = "SELECT code, tree_pos
313
                    FROM $table
314
                    WHERE
315
                        tree_pos > $tree_pos
316
                        $parentIdCondition
317
                    ORDER BY tree_pos DESC
318
                    LIMIT 0,1";
319
            $result2 = Database::query($sql);
320
            if (!$row = Database::fetch_array($result2)) {
321
                return false;
322
            }
323
        }
324
325
        $sql = "UPDATE $table
326
                SET tree_pos ='".$row['tree_pos']."'
327
                WHERE code='$code'";
328
        Database::query($sql);
329
330
        $sql = "UPDATE $table
331
                SET tree_pos = '$tree_pos'
332
                WHERE code= '".$row['code']."'";
333
        Database::query($sql);
334
335
        return true;
336
    }
337
338
    /**
339
     * @param string $categoryCode
340
     *
341
     * @return array
342
     */
343
    public static function getChildren($categoryCode)
344
    {
345
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
346
        $categoryCode = Database::escape_string($categoryCode);
347
        $sql = "SELECT code, id FROM $table
348
                WHERE parent_id = '$categoryCode'";
349
        $result = Database::query($sql);
350
        $children = [];
351
        while ($row = Database::fetch_array($result, 'ASSOC')) {
352
            $children[] = $row;
353
            $subChildren = self::getChildren($row['code']);
354
            $children = array_merge($children, $subChildren);
355
        }
356
357
        return $children;
358
    }
359
360
    /**
361
     * @param string $categoryCode
362
     *
363
     * @return string|null
364
     */
365
    public static function getParentsToString($categoryCode)
366
    {
367
        $parents = self::getParents($categoryCode);
368
369
        if (!empty($parents)) {
370
            $parents = array_reverse($parents);
371
            $categories = [];
372
            foreach ($parents as $category) {
373
                $categories[] = $category['code'];
374
            }
375
376
            return implode(' > ', $categories).' > ';
377
        }
378
379
        return null;
380
    }
381
382
    /**
383
     * @param string $categoryCode
384
     *
385
     * @return array
386
     */
387
    public static function getParents($categoryCode)
388
    {
389
        if (empty($categoryCode)) {
390
            return [];
391
        }
392
393
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
394
        $categoryCode = Database::escape_string($categoryCode);
395
        $sql = "SELECT code, parent_id
396
                FROM $table
397
                WHERE code = '$categoryCode'";
398
399
        $result = Database::query($sql);
400
        $children = [];
401
        while ($row = Database::fetch_array($result, 'ASSOC')) {
402
            $parent = self::getCategory($row['parent_id']);
403
            $children[] = $row;
404
            $subChildren = self::getParents($parent ? $parent['code'] : null);
405
            $children = array_merge($children, $subChildren);
406
        }
407
408
        return $children;
409
    }
410
411
    public static function listCategories(array $categorySource = []): string
412
    {
413
        $categories = self::getCategories($categorySource ? $categorySource['id'] : null);
414
        $categoryCode = $categorySource ? Security::remove_XSS($categorySource['code']) : '';
415
416
        if (count($categories) > 0) {
417
            $table = new HTML_Table(['class' => 'data_table']);
418
            $column = 0;
419
            $row = 0;
420
            $headers = [
421
                get_lang('Category'),
422
                get_lang('Sub-categories'),
423
                get_lang('Courses'),
424
                get_lang('Detail'),
425
            ];
426
            foreach ($headers as $header) {
427
                $table->setHeaderContents($row, $column, $header);
428
                $column++;
429
            }
430
            $row++;
431
            $mainUrl = api_get_path(WEB_CODE_PATH).'admin/course_category.php?category='.$categoryCode;
432
433
            $editIcon = Display::return_icon(
434
                'edit.png',
435
                get_lang('Edit this category'),
436
                null,
437
                ICON_SIZE_SMALL
438
            );
439
            $deleteIcon = Display::return_icon(
440
                'delete.png',
441
                get_lang('Delete this category'),
442
                null,
443
                ICON_SIZE_SMALL
444
            );
445
            $moveIcon = Display::return_icon(
446
                'up.png',
447
                get_lang('Up in same level'),
448
                null,
449
                ICON_SIZE_SMALL
450
            );
451
452
            $urlId = api_get_current_access_url_id();
453
            foreach ($categories as $category) {
454
                $categoryId = $category->getId();
455
                $code = $category->getCode();
456
                $editUrl = $mainUrl.'&id='.$categoryId.'&action=edit';
457
                $moveUrl = $mainUrl.'&id='.$categoryId.'&action=moveUp&tree_pos='.$category->getTreePos();
458
                $deleteUrl = $mainUrl.'&id='.$categoryId.'&action=delete';
459
460
                $actions = [];
461
                $criteria = Criteria::create();
462
                $criteria->where(Criteria::expr()->eq('status', User::STUDENT));
463
464
                $inUrl = $category->getUrls()->filter(
465
                    function ($entry) use ($urlId) {
466
                        return $entry->getUrl()->getId() === $urlId;
467
                    }
468
                );
469
470
                if ($inUrl->count() > 0) {
471
                    $actions[] = Display::url($editIcon, $editUrl);
472
                    $actions[] = Display::url($moveIcon, $moveUrl);
473
                    $actions[] = Display::url($deleteIcon, $deleteUrl);
474
                }
475
476
                $url = api_get_path(WEB_CODE_PATH).'admin/course_category.php?id='.$categoryId;
477
                $title = Display::url(
478
                    Display::return_icon(
479
                        'folder_document.gif',
480
                        get_lang('Open this category'),
481
                        null,
482
                        ICON_SIZE_SMALL
483
                    ).' '.$category->getName().' ('.$code.')',
484
                    $url
485
                );
486
487
                $countCourses = $category->getCourses()->count();
488
                $content = [
489
                    $title,
490
                    $category->getChildrenCount(),
491
                    $countCourses,
492
                    implode('', $actions),
493
                ];
494
                $column = 0;
495
                foreach ($content as $value) {
496
                    $table->setCellContents($row, $column, $value);
497
                    $column++;
498
                }
499
                $row++;
500
            }
501
502
            return $table->toHtml();
503
        }
504
505
        return Display::return_message(get_lang('There are no categories here'), 'warning');
506
    }
507
508
    /**
509
     * @param int|null $category Optional. Parent category ID.
510
     *
511
     * @return CourseCategoryEntity[]
512
     */
513
    public static function getCategories($category = null)
514
    {
515
        $repo = Container::getCourseCategoryRepository();
516
        $category = (int) $category;
517
518
        return $repo->findAllInAccessUrl(
519
            api_get_current_access_url_id(),
520
            api_get_configuration_value('allow_base_course_category'),
521
            $category
522
        );
523
524
        /*
525
        $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
526
        $conditions = " INNER JOIN $table a ON (t1.id = a.course_category_id)";
527
        $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
528
        $allowBaseCategories = api_get_configuration_value('allow_base_course_category');
529
        if ($allowBaseCategories) {
530
            $whereCondition = " AND (a.access_url_id = ".api_get_current_access_url_id()." OR a.access_url_id = 1) ";
531
        }
532
533
        $parentIdCondition = " AND (t1.parent_id IS NULL OR t1.parent_id = '' )";
534
535
        if ($category) {
536
            $parentIdCondition = " AND t1.parent_id = $category ";
537
        }
538
539
        $sql = "SELECT
540
                t1.name,
541
                t1.code,
542
                t1.parent_id,
543
                t1.tree_pos,
544
                t1.children_count,
545
                COUNT(DISTINCT t4.code) AS nbr_courses,
546
                a.access_url_id
547
                FROM $tbl_category t1
548
                $conditions
549
                LEFT JOIN $tbl_category t2
550
                ON t1.id = t2.parent_id
551
                LEFT JOIN $tbl_course_rel_category t3
552
                ON t1.id = t3.course_category_id
553
                LEFT JOIN $tbl_course t4
554
                ON t3.course_id = t4.id
555
                WHERE
556
                    1 = 1
557
                    $parentIdCondition
558
                    $whereCondition
559
                GROUP BY t1.name,
560
                         t1.code,
561
                         t1.parent_id,
562
                         t1.tree_pos,
563
                         t1.children_count
564
                ORDER BY t1.tree_pos
565
        ";
566
567
        $result = Database::query($sql);
568
569
        return Database::store_result($result, 'ASSOC');*/
570
    }
571
572
    /**
573
     * @return array
574
     */
575
    public static function getCategoriesToDisplayInHomePage()
576
    {
577
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
578
        $sql = "SELECT name FROM $table
579
                WHERE parent_id IS NULL
580
                ORDER BY tree_pos";
581
582
        return Database::store_result(Database::query($sql));
583
    }
584
585
    /**
586
     * @param string $categoryCode
587
     *
588
     * @return array
589
     */
590
    public static function getCategoriesCanBeAddedInCourse($categoryCode)
591
    {
592
        $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
593
        $conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
594
        $whereCondition = ' AND a.access_url_id = '.api_get_current_access_url_id();
595
596
        $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
597
        $sql = "SELECT c.id, c.code, name
598
                FROM $tbl_category c
599
                $conditions
600
                WHERE (auth_course_child = 'TRUE' OR code = '".Database::escape_string($categoryCode)."')
601
                $whereCondition
602
                ORDER BY tree_pos";
603
        $res = Database::query($sql);
604
605
        $categoryToAvoid = '';
606
        if (!api_is_platform_admin()) {
607
            $categoryToAvoid = api_get_configuration_value('course_category_code_to_use_as_model');
608
        }
609
        $categories[''] = '-';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$categories was never initialized. Although not strictly required by PHP, it is generally a good practice to add $categories = array(); before regardless.
Loading history...
610
        while ($cat = Database::fetch_array($res)) {
611
            $categoryCode = $cat['code'];
612
            if (!empty($categoryToAvoid) && $categoryToAvoid == $categoryCode) {
613
                continue;
614
            }
615
            $categories[$cat['id']] = '('.$cat['code'].') '.$cat['name'];
616
            ksort($categories);
617
        }
618
619
        return $categories;
620
    }
621
622
    /**
623
     * @param string $category_code
624
     * @param string $keyword
625
     *
626
     * @paran bool  $avoidCourses
627
     * @paran array $conditions
628
     *
629
     * @return int
630
     */
631
    public static function countCoursesInCategory(
632
        $category_code = '',
633
        $keyword = '',
634
        $avoidCourses = true,
635
        $conditions = []
636
    ) {
637
        return self::getCoursesInCategory($category_code, $keyword, $avoidCourses, $conditions, true);
638
    }
639
640
    public static function getCoursesInCategory(
641
        $category_code = '',
642
        $keyword = '',
643
        $avoidCourses = true,
644
        $conditions = [],
645
        $getCount = false
646
    ) {
647
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
648
        $tblCourseCategory = Database::get_main_table(TABLE_MAIN_CATEGORY);
649
        $keyword = Database::escape_string($keyword);
650
        $categoryCode = Database::escape_string($category_code);
651
        $avoidCoursesCondition = '';
652
        if ($avoidCourses) {
653
            $avoidCoursesCondition = CoursesAndSessionsCatalog::getAvoidCourseCondition();
654
        }
655
656
        $visibilityCondition = CourseManager::getCourseVisibilitySQLCondition('course', true);
657
658
        $sqlInjectJoins = '';
659
        $where = ' AND 1 = 1 ';
660
        $sqlInjectWhere = '';
661
        if (!empty($conditions)) {
662
            $sqlInjectJoins = $conditions['inject_joins'];
663
            $where = $conditions['where'];
664
            $sqlInjectWhere = $conditions['inject_where'];
665
        }
666
        $categoryFilter = '';
667
        if ('ALL' === $categoryCode || empty($categoryCode)) {
668
            // Nothing to do
669
        } elseif ('NONE' === $categoryCode) {
670
            $categoryFilter = ' AND course.category_id IS NULL ';
671
        } else {
672
            $categoryJoin = " INNER JOIN $tblCourseCategory cat ON course.category_id = cat.id ";
673
            $categoryFilter = ' AND cat.code = "'.$categoryCode.'" ';
674
        }
675
676
        $searchFilter = '';
677
        if (!empty($keyword)) {
678
            $searchFilter = ' AND (
679
                course.code LIKE "%'.$keyword.'%" OR
680
                course.title LIKE "%'.$keyword.'%" OR
681
                course.tutor_name LIKE "%'.$keyword.'%"
682
            ) ';
683
        }
684
685
        $urlCondition = ' url_rel_course.access_url_id = '.api_get_current_access_url_id().' AND';
686
        $tbl_url_rel_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
687
688
        $select = " DISTINCT course.id, course.code, course.title ";
689
        if ($getCount) {
690
            $select = "count(DISTINCT course.id) as count";
691
        }
692
        $sql = "SELECT $select
693
                FROM $tbl_course as course
694
                INNER JOIN $tbl_url_rel_course as url_rel_course
695
                ON (url_rel_course.c_id = course.id)
696
                $sqlInjectJoins
697
                $categoryJoin
698
                WHERE
699
                    $urlCondition
700
                    course.visibility != '0' AND
701
                    course.visibility != '4'
702
                    $categoryFilter
703
                    $searchFilter
704
                    $avoidCoursesCondition
705
                    $visibilityCondition
706
                    $where
707
                    $sqlInjectWhere
708
            ";
709
710
        $result = Database::query($sql);
711
        if ($getCount) {
712
            $row = Database::fetch_array($result);
713
714
            return (int) $row['count'];
715
        }
716
717
        return Database::store_result($result, 'ASSOC');
718
    }
719
720
    /**
721
     * @param array $list
722
     *
723
     * @return array
724
     */
725
    public static function getCourseCategoryNotInList($list)
726
    {
727
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
728
729
        if (empty($list)) {
730
            $sql = "SELECT * FROM $table
731
                    WHERE (parent_id IS NULL) ";
732
            $result = Database::query($sql);
733
734
            return Database::store_result($result, 'ASSOC');
735
        }
736
737
        $list = array_map('intval', $list);
738
        $listToString = implode("','", $list);
739
740
        $sql = "SELECT * FROM $table
741
                WHERE id NOT IN ('$listToString') AND (parent_id IS NULL) ";
742
        $result = Database::query($sql);
743
744
        return Database::store_result($result, 'ASSOC');
745
    }
746
747
    /**
748
     * @param string $keyword
749
     *
750
     * @return array|null
751
     */
752
    public static function searchCategoryByKeyword($keyword)
753
    {
754
        if (empty($keyword)) {
755
            return null;
756
        }
757
758
        $tableCategory = Database::get_main_table(TABLE_MAIN_CATEGORY);
759
        $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
760
        $conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
761
        $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
762
763
        $allowBaseCategories = api_get_configuration_value('allow_base_course_category');
764
        if ($allowBaseCategories) {
765
            $whereCondition = " AND (a.access_url_id = ".api_get_current_access_url_id()." OR a.access_url_id = 1) ";
766
        }
767
768
        $keyword = Database::escape_string($keyword);
769
770
        $sql = "SELECT c.*, c.name as text
771
                FROM $tableCategory c $conditions
772
                WHERE
773
                (
774
                    c.code LIKE '%$keyword%' OR name LIKE '%$keyword%'
775
                ) AND auth_course_child = 'TRUE'
776
                $whereCondition ";
777
        $result = Database::query($sql);
778
779
        return Database::store_result($result, 'ASSOC');
780
    }
781
782
    /**
783
     * Get Pagination HTML div.
784
     *
785
     * @param $pageCurrent
786
     * @param $pageLength
787
     * @param $pageTotal
788
     *
789
     * @return string
790
     */
791
    public static function getCatalogPagination($pageCurrent, $pageLength, $pageTotal)
792
    {
793
        // Start empty html
794
        $pageDiv = '';
795
        $html = '';
796
        $pageBottom = max(1, $pageCurrent - 3);
797
        $pageTop = min($pageTotal, $pageCurrent + 3);
798
799
        if ($pageBottom > 1) {
800
            $pageDiv .= self::getPageNumberItem(1, $pageLength);
801
            if ($pageBottom > 2) {
802
                $pageDiv .= self::getPageNumberItem(
803
                    $pageBottom - 1,
804
                    $pageLength,
805
                    null,
806
                    '...'
807
                );
808
            }
809
        }
810
811
        // For each page add its page button to html
812
        for ($i = $pageBottom; $i <= $pageTop; $i++) {
813
            if ($i === $pageCurrent) {
814
                $pageItemAttributes = ['class' => 'page-item active'];
815
            } else {
816
                $pageItemAttributes = ['class' => 'page-item'];
817
            }
818
            $pageDiv .= self::getPageNumberItem(
819
                $i,
820
                $pageLength,
821
                $pageItemAttributes
822
            );
823
        }
824
825
        // Check if current page is the last page
826
        if ($pageTop < $pageTotal) {
827
            if ($pageTop < ($pageTotal - 1)) {
828
                $pageDiv .= self::getPageNumberItem(
829
                    $pageTop + 1,
830
                    $pageLength,
831
                    null,
832
                    '...'
833
                );
834
            }
835
            $pageDiv .= self::getPageNumberItem($pageTotal, $pageLength);
836
        }
837
838
        // Complete pagination html
839
        $pageDiv = Display::tag('ul', $pageDiv, ['class' => 'pagination']);
840
        $html .= '<nav>'.$pageDiv.'</nav>';
841
842
        return $html;
843
    }
844
845
    /**
846
     * Get li HTML of page number.
847
     *
848
     * @param        $pageNumber
849
     * @param        $pageLength
850
     * @param array  $liAttributes
851
     * @param string $content
852
     *
853
     * @return string
854
     */
855
    public static function getPageNumberItem(
856
        $pageNumber,
857
        $pageLength,
858
        $liAttributes = [],
859
        $content = ''
860
    ) {
861
        // Get page URL
862
        $url = self::getCourseCategoryUrl(
863
            $pageNumber,
864
            $pageLength
865
        );
866
867
        // If is current page ('active' class) clear URL
868
        if (isset($liAttributes) && is_array($liAttributes) && isset($liAttributes['class'])) {
869
            if (false !== strpos('active', $liAttributes['class'])) {
870
                $url = '';
871
            }
872
        }
873
874
        $content = !empty($content) ? $content : $pageNumber;
875
876
        return Display::tag(
877
            'li',
878
            Display::url(
879
                $content,
880
                $url,
881
                ['class' => 'page-link']
882
            ),
883
            $liAttributes
884
        );
885
    }
886
887
    /**
888
     * Return URL to course catalog.
889
     *
890
     * @param int    $pageCurrent
891
     * @param int    $pageLength
892
     * @param string $categoryCode
893
     * @param int    $hiddenLinks
894
     * @param string $action
895
     *
896
     * @return string
897
     */
898
    public static function getCourseCategoryUrl(
899
        $pageCurrent,
900
        $pageLength,
901
        $categoryCode = null,
902
        $hiddenLinks = null,
903
        $action = null
904
    ) {
905
        $requestAction = isset($_REQUEST['action']) ? Security::remove_XSS($_REQUEST['action']) : null;
906
        $action = isset($action) ? Security::remove_XSS($action) : $requestAction;
907
        $searchTerm = isset($_REQUEST['search_term']) ? Security::remove_XSS($_REQUEST['search_term']) : null;
908
909
        if ('subscribe_user_with_password' === $action) {
910
            $action = 'subscribe';
911
        }
912
913
        $categoryCodeRequest = isset($_REQUEST['category_code']) ? Security::remove_XSS(
914
            $_REQUEST['category_code']
915
        ) : null;
916
        $categoryCode = isset($categoryCode) ? Security::remove_XSS($categoryCode) : $categoryCodeRequest;
917
        $hiddenLinksRequest = isset($_REQUEST['hidden_links']) ? Security::remove_XSS($_REQUEST['hidden_links']) : null;
918
        $hiddenLinks = isset($hiddenLinks) ? Security::remove_XSS($hiddenLinksRequest) : $categoryCodeRequest;
919
920
        // Start URL with params
921
        $pageUrl = api_get_self().
922
            '?action='.$action.
923
            '&category_code='.$categoryCode.
924
            '&hidden_links='.$hiddenLinks.
925
            '&pageCurrent='.$pageCurrent.
926
            '&pageLength='.$pageLength;
927
928
        switch ($action) {
929
            case 'subscribe':
930
                // for search
931
                $pageUrl .=
932
                    '&search_term='.$searchTerm.
933
                    '&search_course=1'.
934
                    '&sec_token='.Security::getTokenFromSession();
935
                break;
936
            case 'display_courses':
937
            default:
938
                break;
939
        }
940
941
        return $pageUrl;
942
    }
943
944
    /**
945
     * Return the name tool by action.
946
     *
947
     * @param string $action
948
     *
949
     * @return string
950
     */
951
    public static function getCourseCatalogNameTools($action)
952
    {
953
        $nameTools = get_lang('My courses');
954
        if (empty($action)) {
955
            return $nameTools; //should never happen
956
        }
957
958
        switch ($action) {
959
            case 'subscribe':
960
            case 'subscribe_user_with_password':
961
            case 'display_random_courses':
962
            case 'display_courses':
963
                $nameTools = get_lang('Courses catalog');
964
                break;
965
            case 'display_sessions':
966
                $nameTools = get_lang('Course sessions');
967
                break;
968
            default:
969
                // Nothing to do
970
                break;
971
        }
972
973
        return $nameTools;
974
    }
975
976
    public static function deleteImage(CourseCategoryEntity $category)
977
    {
978
        $assetRepo = Container::getAssetRepository();
979
        $assetId = $category->getImage();
980
        $asset = $assetRepo->find($assetId);
981
        $assetRepo->delete($asset);
982
983
        $category->setImage('');
984
        $repo = Container::getCourseCategoryRepository();
985
        $repo->save($category);
986
    }
987
988
    /**
989
     * Save image for a course category.
990
     *
991
     * @param array $fileData File data from $_FILES
992
     */
993
    public static function saveImage(CourseCategoryEntity $category, $fileData)
994
    {
995
        if (isset($fileData['tmp_name']) && !empty($fileData['tmp_name'])) {
996
            $categoryId = $category->getId();
997
            $extension = getextension($fileData['name']);
998
            $fileName = "cc_$categoryId.{$extension[0]}";
999
1000
            $repo = Container::getAssetRepository();
1001
            $asset = new Asset();
1002
            $asset
1003
                ->setCategory(Asset::COURSE_CATEGORY)
1004
                ->setTitle($fileName);
1005
            $asset = $repo->createFromRequest($asset, $fileData);
1006
1007
            $category->setImage($asset->getId());
1008
            $repo = Container::getCourseCategoryRepository();
1009
            $repo->save($category);
1010
        }
1011
1012
        /*
1013
        $categoryInfo = self::getCategoryById($categoryId);
1014
        if (empty($categoryInfo)) {
1015
            return;
1016
        }
1017
1018
        if (!empty($fileData['error'])) {
1019
            return;
1020
        }
1021
1022
        $extension = getextension($fileData['name']);
1023
        $dirName = 'course_category/';
1024
        $fileDir = api_get_path(SYS_UPLOAD_PATH).$dirName;
1025
        $fileName = "cc_$categoryId.{$extension[0]}";
1026
1027
        if (!file_exists($fileDir)) {
1028
            mkdir($fileDir, api_get_permissions_for_new_directories(), true);
1029
        }
1030
1031
        $image = new Image($fileData['tmp_name']);
1032
        $image->send_image($fileDir.$fileName);
1033
1034
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1035
        Database::update(
1036
            $table,
1037
            ['image' => $dirName.$fileName],
1038
            ['id = ?' => $categoryId]
1039
        );*/
1040
    }
1041
1042
    /**
1043
     * @param        $category
1044
     * @param string $description
1045
     *
1046
     * @return string
1047
     */
1048
    public static function saveDescription(CourseCategoryEntity $category, $description)
1049
    {
1050
        $repo = Container::getCourseCategoryRepository();
1051
        $category->setDescription($description);
1052
        $repo->save($category);
1053
    }
1054
}
1055