Passed
Push — master ( 24029a...63a044 )
by
unknown
16:41 queued 08:01
created

CourseCategory::getCategoriesCanBeAddedInCourse()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 30
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

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