Passed
Push — master ( 1621b1...72e552 )
by Yannick
06:59 queued 13s
created

Link::showCategoryAdminTools()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 65
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 55
c 0
b 0
f 0
nc 4
nop 3
dl 0
loc 65
rs 8.9818

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Framework\Container;
6
use Chamilo\CourseBundle\Entity\CLink;
7
use Chamilo\CourseBundle\Entity\CLinkCategory;
8
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
9
use Chamilo\CoreBundle\Component\Utils\ObjectIcon;
10
use Chamilo\CoreBundle\Component\Utils\StateIcon;
11
12
/**
13
 * Function library for the links tool.
14
 *
15
 * This is a complete remake of the original link tool.
16
 * New features:
17
 * - Organize links into categories;
18
 * - favorites/bookmarks interface;
19
 * - move links up/down within a category;
20
 * - move categories up/down;
21
 * - expand/collapse all categories;
22
 * - add link to 'root' category => category-less link is always visible.
23
 *
24
 * @author Patrick Cool (December 2003 - January 2004)
25
 * @author René Haentjens, CSV file import (October 2004)
26
 */
27
class Link extends Model
28
{
29
    public $table;
30
    public $is_course_model = true;
31
    public $columns = [
32
        'id',
33
        'c_id',
34
        'url',
35
        'title',
36
        'description',
37
        'category_id',
38
        'display_order',
39
        'on_homepage',
40
        'target',
41
        'session_id',
42
    ];
43
    public array $required = ['url', 'title'];
44
    private $course;
45
46
    public function __construct()
47
    {
48
        $this->table = Database::get_course_table(TABLE_LINK);
49
    }
50
51
    /**
52
     * @param array $course
53
     */
54
    public function setCourse($course)
55
    {
56
        $this->course = $course;
57
    }
58
59
    /**
60
     * @return array
61
     */
62
    public function getCourse()
63
    {
64
        return !empty($this->course) ? $this->course : api_get_course_info();
65
    }
66
67
    /**
68
     * Organize the saving of a link, using the parent's save method and
69
     * updating the item_property table.
70
     *
71
     * @param array $params
72
     * @param bool  $showQuery Whether to show the query in logs when
73
     *                         calling parent's save method
74
     *
75
     * @return bool True if link could be saved, false otherwise
76
     */
77
    public function save($params, $showQuery = null, $showFlash = true)
78
    {
79
        $course_info = $this->getCourse();
80
        $course_id = $course_info['real_id'];
81
        $session_id = api_get_session_id();
82
83
        $title = stripslashes($params['title']);
84
        $urllink = $params['url'];
85
        $description = $params['description'];
86
        $categoryId = (int) $params['category_id'];
87
88
        $onhomepage = 0;
89
        if (isset($params['on_homepage'])) {
90
            $onhomepage = Security::remove_XSS($params['on_homepage']);
91
        }
92
93
        $target = '_self'; // Default target.
94
        if (!empty($params['target'])) {
95
            $target = Security::remove_XSS($params['target']);
96
        }
97
98
        $urllink = trim($urllink);
99
        $title = trim($title);
100
        $description = trim($description);
101
102
        // We ensure URL to be absolute.
103
        if (false === strpos($urllink, '://')) {
104
            $urllink = 'http://'.$urllink;
105
        }
106
107
        // If the title is empty, we use the URL as title.
108
        if ('' == $title) {
109
            $title = $urllink;
110
        }
111
112
        // If the URL is invalid, an error occurs.
113
        if (!api_valid_url($urllink, true)) {
114
            // A check against an absolute URL
115
            Display::addFlash(
116
                Display::return_message(get_lang('Please give the link URL, it should be valid.'), 'error')
117
            );
118
119
            return false;
120
        } else {
121
            $category = null;
122
            $repoCategory = Container::getLinkCategoryRepository();
123
            if (!empty($categoryId)) {
124
                /** @var CLinkCategory $category */
125
                $category = $repoCategory->find($categoryId);
126
            }
127
128
            // Looking for the largest order number for this category.
129
            $link = new CLink();
130
            $link
131
                ->setUrl($urllink)
132
                ->setTitle($title)
133
                ->setDescription($description)
134
                ->setTarget($target)
135
                ->setCategory($category)
136
            ;
137
138
            $repo = Container::getLinkRepository();
139
            $courseEntity = api_get_course_entity($course_id);
140
            if (empty($category)) {
141
                $link
142
                    ->setParent($courseEntity)
143
                    ->addCourseLink($courseEntity, api_get_session_entity($session_id))
144
                ;
145
            } else {
146
                $link
147
                    ->setParent($category)
148
                    ->addCourseLink($courseEntity, api_get_session_entity($session_id))
149
                ;
150
            }
151
152
            $repo->create($link);
153
            $link_id = $link->getIid();
154
155
            if (('true' === api_get_setting('search_enabled')) &&
156
                $link_id && extension_loaded('xapian')
157
            ) {
158
                $courseCode = $course_info['code'];
159
                $specific_fields = get_specific_field_list();
160
                $ic_slide = new IndexableChunk();
161
162
                // Add all terms to db.
163
                $all_specific_terms = '';
164
                foreach ($specific_fields as $specific_field) {
165
                    if (isset($_REQUEST[$specific_field['code']])) {
166
                        $sterms = trim($_REQUEST[$specific_field['code']]);
167
                        if (!empty($sterms)) {
168
                            $all_specific_terms .= ' '.$sterms;
169
                            $sterms = explode(',', $sterms);
170
                            foreach ($sterms as $sterm) {
171
                                $ic_slide->addTerm(
172
                                    trim($sterm),
173
                                    $specific_field['code']
174
                                );
175
                                add_specific_field_value(
176
                                    $specific_field['id'],
177
                                    $courseCode,
178
                                    TOOL_LINK,
179
                                    $link_id,
180
                                    $sterm
181
                                );
182
                            }
183
                        }
184
                    }
185
                }
186
187
                // Build the chunk to index.
188
                $ic_slide->addValue('title', $title);
189
                $ic_slide->addCourseId($courseCode);
190
                $ic_slide->addToolId(TOOL_LINK);
191
                $xapian_data = [
192
                    SE_COURSE_ID => $courseCode,
193
                    SE_TOOL_ID => TOOL_LINK,
194
                    SE_DATA => [
195
                        'link_id' => $link_id,
196
                    ],
197
                    SE_USER => (int) api_get_user_id(),
198
                ];
199
                $ic_slide->xapian_data = serialize($xapian_data);
200
                $description = $all_specific_terms.' '.$description;
201
                $ic_slide->addValue('content', $description);
202
203
                // Add category name if set.
204
                if (isset($categoryId) && $categoryId > 0) {
205
                    $table_link_category = Database::get_course_table(
206
                        TABLE_LINK_CATEGORY
207
                    );
208
                    $sql_cat = 'SELECT * FROM %s WHERE id=%d AND c_id = %d LIMIT 1';
209
                    $sql_cat = sprintf(
210
                        $sql_cat,
211
                        $table_link_category,
212
                        $categoryId,
213
                        $course_id
214
                    );
215
                    $result = Database:: query($sql_cat);
216
                    if (1 == Database:: num_rows($result)) {
217
                        $row = Database:: fetch_array($result);
218
                        $ic_slide->addValue(
219
                            'category',
220
                            $row['category_title']
221
                        );
222
                    }
223
                }
224
225
                $di = new ChamiloIndexer();
226
                isset($params['language']) ? $lang = Database:: escape_string(
227
                    $params['language']
228
                ) : $lang = 'english';
229
                $di->connectDb(null, null, $lang);
230
                $di->addChunk($ic_slide);
231
232
                // Index and return search engine document id.
233
                $did = $di->index();
234
                if ($did) {
235
                    // Save it to db.
236
                    $tbl_se_ref = Database::get_main_table(
237
                        TABLE_MAIN_SEARCH_ENGINE_REF
238
                    );
239
                    $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
240
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
241
                    $sql = sprintf(
242
                        $sql,
243
                        $tbl_se_ref,
244
                        $course_id,
245
                        $courseCode,
246
                        TOOL_LINK,
247
                        $link_id,
248
                        $did
249
                    );
250
                    Database:: query($sql);
251
                }
252
            }
253
            if ($showFlash) {
254
                Display::addFlash(Display::return_message(get_lang('The link has been added.')));
255
            }
256
257
            return $link_id;
258
        }
259
    }
260
261
    /**
262
     * Update a link in the database.
263
     *
264
     * @param int    $linkId    The ID of the link to update
265
     * @param string $linkUrl   The new URL to be saved
266
     * @param int    $courseId
267
     * @param int    $sessionId
268
     *
269
     * @return bool
270
     */
271
    public function updateLink(
272
        $linkId,
273
        $linkUrl,
274
        $courseId = null,
275
        $sessionId = null
276
    ) {
277
        $tblLink = Database::get_course_table(TABLE_LINK);
278
        $linkUrl = Database::escape_string($linkUrl);
279
        $linkId = (int) $linkId;
280
        if ('' != $linkUrl) {
281
            $sql = "UPDATE $tblLink SET
282
                    url = '$linkUrl'
283
                    WHERE iid = $linkId ";
284
            $resLink = Database::query($sql);
285
286
            return $resLink;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $resLink also could return the type Doctrine\DBAL\Result which is incompatible with the documented return type boolean.
Loading history...
287
        }
288
289
        return false;
290
    }
291
292
    public static function addCategory()
293
    {
294
        $_course = api_get_course_info();
295
        $course_id = $_course['real_id'];
296
        $category_title = trim($_POST['category_title']);
297
        $description = trim($_POST['description']);
298
299
        if (empty($category_title)) {
300
            echo Display::return_message(get_lang('Please give the category name'), 'error');
301
302
            return false;
303
        }
304
305
        // Looking for the largest order number for this category.
306
        /*$result = Database:: query(
307
            "SELECT MAX(display_order) FROM  $tbl_categories
308
            WHERE c_id = $course_id "
309
        );
310
        [$orderMax] = Database:: fetch_row($result);
311
        $order = $orderMax + 1;
312
        $order = (int) $order;*/
313
        $session_id = api_get_session_id();
314
315
        $repo = Container::getLinkCategoryRepository();
316
        $courseEntity = api_get_course_entity($course_id);
317
        $sessionEntity = api_get_session_entity($session_id);
318
319
        $category = (new CLinkCategory())
320
            ->setCategoryTitle($category_title)
321
            ->setDescription($description)
322
         //   ->setDisplayOrder($order)
323
            ->setParent($courseEntity)
324
            ->addCourseLink($courseEntity, $sessionEntity)
325
        ;
326
327
        $repo->create($category);
328
329
        Display::addFlash(Display::return_message(get_lang('Category added')));
330
331
        return $category;
332
    }
333
334
    public static function deleteCategory($id)
335
    {
336
        $repo = Container::getLinkCategoryRepository();
337
        /** @var CLinkCategory $category */
338
        $category = $repo->find($id);
339
        if ($category) {
0 ignored issues
show
introduced by
$category is of type Chamilo\CourseBundle\Entity\CLinkCategory, thus it always evaluated to true.
Loading history...
340
            $repo->delete($category);
341
            Display::addFlash(Display::return_message(get_lang('The category has been deleted.')));
342
343
            return true;
344
        }
345
346
        return false;
347
    }
348
349
    /**
350
     * Used to delete a link.
351
     *
352
     * @param int $id
353
     *
354
     * @return bool
355
     */
356
    public static function deleteLink($id)
357
    {
358
        $repo = Container::getLinkRepository();
359
        $link = $repo->find($id);
360
        if ($link) {
361
            $repo->delete($link);
362
            self::delete_link_from_search_engine(api_get_course_id(), $id);
363
            SkillModel::deleteSkillsFromItem($id, ITEM_TYPE_LINK);
364
            Display::addFlash(Display::return_message(get_lang('The link has been deleted')));
365
366
            return true;
367
        }
368
369
        return false;
370
    }
371
372
    /**
373
     * Removes a link from search engine database.
374
     *
375
     * @param string $course_id Course code
376
     * @param int    $link_id   Document id to delete
377
     */
378
    public static function delete_link_from_search_engine($course_id, $link_id)
379
    {
380
        // Remove from search engine if enabled.
381
        if ('true' === api_get_setting('search_enabled')) {
382
            $tbl_se_ref = Database::get_main_table(
383
                TABLE_MAIN_SEARCH_ENGINE_REF
384
            );
385
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
386
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
387
            $res = Database:: query($sql);
388
            if (Database:: num_rows($res) > 0) {
389
                $row = Database::fetch_array($res);
390
                $di = new ChamiloIndexer();
391
                $di->remove_document($row['search_did']);
392
            }
393
            $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
394
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
395
            Database:: query($sql);
396
397
            // Remove terms from db.
398
            delete_all_values_for_item($course_id, TOOL_DOCUMENT, $link_id);
399
        }
400
    }
401
402
    /**
403
     * Get link info.
404
     *
405
     * @param int $id
406
     *
407
     * @return array link info
408
     */
409
    public static function getLinkInfo($id)
410
    {
411
        $tbl_link = Database::get_course_table(TABLE_LINK);
412
        $course_id = api_get_course_int_id();
413
        $id = (int) $id;
414
415
        if (empty($id) || empty($course_id)) {
416
            return [];
417
        }
418
419
        $sql = "SELECT * FROM $tbl_link
420
                WHERE iid= $id ";
421
        $result = Database::query($sql);
422
        $data = [];
423
        if (Database::num_rows($result)) {
424
            $data = Database::fetch_array($result);
425
        }
426
427
        return $data;
428
    }
429
430
    /**
431
     * @param int   $id
432
     * @param array $values
433
     */
434
    public static function editLink($id, $values = [])
435
    {
436
        $_course = api_get_course_info();
437
        $course_id = $_course['real_id'];
438
        $id = (int) $id;
439
440
        $values['url'] = trim($values['url']);
441
        $values['title'] = trim($values['title']);
442
        $values['description'] = trim($values['description']);
443
        $values['target'] = empty($values['target']) ? '_self' : $values['target'];
444
        $values['on_homepage'] = isset($values['on_homepage']) ? $values['on_homepage'] : '';
445
446
        $categoryId = (int) $values['category_id'];
447
448
        // We ensure URL to be absolute.
449
        if (false === strpos($values['url'], '://')) {
450
            $values['url'] = 'http://'.$_POST['url'];
451
        }
452
453
        // If the title is empty, we use the URL as title.
454
        if ('' == $values['title']) {
455
            $values['title'] = $values['url'];
456
        }
457
458
        // If the URL is invalid, an error occurs.
459
        if (!api_valid_url($values['url'], true)) {
460
            Display::addFlash(
461
                Display::return_message(get_lang('Please give the link URL, it should be valid.'), 'error')
462
            );
463
464
            return false;
465
        }
466
467
        if (empty($id) || empty($course_id)) {
468
            return false;
469
        }
470
471
        $repo = Container::getLinkRepository();
472
        /** @var CLink $link */
473
        $link = $repo->find($id);
474
475
        if (null === $link) {
476
            return false;
477
        }
478
479
        /*if ($link->getCategory() != $values['category_id']) {
480
            $sql = "SELECT MAX(display_order)
481
                    FROM $tbl_link
482
                    WHERE
483
                        category_id='".intval($values['category_id'])."'";
484
            $result = Database:: query($sql);
485
            [$max_display_order] = Database:: fetch_row($result);
486
            $max_display_order++;
487
        } else {
488
            $max_display_order = $row['display_order'];
489
        }*/
490
491
        $link
492
            ->setUrl($values['url'])
493
            ->setTitle($values['title'])
494
            ->setDescription($values['description'])
495
            ->setTarget($values['target'])
496
        ;
497
498
        $courseEntity = api_get_course_entity($course_id);
499
500
        if ($categoryId) {
501
            $repoCategory = Container::getLinkCategoryRepository();
502
            /** @var CLinkCategory $category */
503
            $category = $repoCategory->find($categoryId);
504
            $link
505
                ->setCategory($category)
506
                ->setParent($category);
507
        } else {
508
            $link
509
                ->setCategory(null)
510
                ->setParent($courseEntity);
511
        }
512
513
        $repo->updateNodeForResource($link);
514
        $repo->update($link);
515
516
        // Update search enchine and its values table if enabled.
517
        if ('true' === api_get_setting('search_enabled')) {
518
            $course_int_id = api_get_course_int_id();
519
            $course_id = api_get_course_id();
520
            $link_title = Database:: escape_string($values['title']);
521
            $link_description = Database:: escape_string($values['description']);
522
523
            // Actually, it consists on delete terms from db,
524
            // insert new ones, create a new search engine document, and remove the old one.
525
            // Get search_did.
526
            $tbl_se_ref = Database::get_main_table(
527
                TABLE_MAIN_SEARCH_ENGINE_REF
528
            );
529
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
530
            $sql = sprintf(
531
                $sql,
532
                $tbl_se_ref,
533
                $course_id,
534
                TOOL_LINK,
535
                $id
536
            );
537
            $res = Database:: query($sql);
538
539
            if (Database:: num_rows($res) > 0) {
540
                $se_ref = Database:: fetch_array($res);
541
                $specific_fields = get_specific_field_list();
542
                $ic_slide = new IndexableChunk();
543
544
                $all_specific_terms = '';
545
                foreach ($specific_fields as $specific_field) {
546
                    delete_all_specific_field_value(
547
                        $course_id,
548
                        $specific_field['id'],
549
                        TOOL_LINK,
550
                        $id
551
                    );
552
                    if (isset($_REQUEST[$specific_field['code']])) {
553
                        $sterms = trim(
554
                            $_REQUEST[$specific_field['code']]
555
                        );
556
                        if (!empty($sterms)) {
557
                            $all_specific_terms .= ' '.$sterms;
558
                            $sterms = explode(',', $sterms);
559
                            foreach ($sterms as $sterm) {
560
                                $ic_slide->addTerm(
561
                                    trim($sterm),
562
                                    $specific_field['code']
563
                                );
564
                                add_specific_field_value(
565
                                    $specific_field['id'],
566
                                    $course_id,
567
                                    TOOL_LINK,
568
                                    $id,
569
                                    $sterm
570
                                );
571
                            }
572
                        }
573
                    }
574
                }
575
576
                // Build the chunk to index.
577
                $ic_slide->addValue("title", $link_title);
578
                $ic_slide->addCourseId($course_id);
579
                $ic_slide->addToolId(TOOL_LINK);
580
                $xapian_data = [
581
                    SE_COURSE_ID => $course_id,
582
                    SE_TOOL_ID => TOOL_LINK,
583
                    SE_DATA => [
584
                        'link_id' => $id,
585
                    ],
586
                    SE_USER => (int) api_get_user_id(),
587
                ];
588
                $ic_slide->xapian_data = serialize($xapian_data);
589
                $link_description = $all_specific_terms.' '.$link_description;
590
                $ic_slide->addValue('content', $link_description);
591
592
                // Add category name if set.
593
                if (isset($categoryId) && $categoryId > 0) {
594
                    $table_link_category = Database::get_course_table(
595
                        TABLE_LINK_CATEGORY
596
                    );
597
                    $sql_cat = 'SELECT * FROM %s WHERE id=%d and c_id = %d LIMIT 1';
598
                    $sql_cat = sprintf(
599
                        $sql_cat,
600
                        $table_link_category,
601
                        $categoryId,
602
                        $course_int_id
603
                    );
604
                    $result = Database:: query($sql_cat);
605
                    if (1 == Database:: num_rows($result)) {
606
                        $row = Database:: fetch_array($result);
607
                        $ic_slide->addValue(
608
                            'category',
609
                            $row['category_title']
610
                        );
611
                    }
612
                }
613
614
                $di = new ChamiloIndexer();
615
                isset($_POST['language']) ? $lang = Database:: escape_string($_POST['language']) : $lang = 'english';
616
                $di->connectDb(null, null, $lang);
617
                $di->remove_document($se_ref['search_did']);
618
                $di->addChunk($ic_slide);
619
620
                // Index and return search engine document id.
621
                $did = $di->index();
622
                if ($did) {
623
                    // Save it to db.
624
                    $sql = 'DELETE FROM %s
625
                            WHERE course_code=\'%s\'
626
                            AND tool_id=\'%s\'
627
                            AND ref_id_high_level=\'%s\'';
628
                    $sql = sprintf(
629
                        $sql,
630
                        $tbl_se_ref,
631
                        $course_id,
632
                        TOOL_LINK,
633
                        $id
634
                    );
635
                    Database:: query($sql);
636
                    $sql = 'INSERT INTO %s (c_id, id, course_code, tool_id, ref_id_high_level, search_did)
637
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
638
                    $sql = sprintf(
639
                        $sql,
640
                        $tbl_se_ref,
641
                        $course_int_id,
642
                        $course_id,
643
                        TOOL_LINK,
644
                        $id,
645
                        $did
646
                    );
647
                    Database:: query($sql);
648
                }
649
            }
650
        }
651
652
        Display::addFlash(Display::return_message(get_lang('The link has been modified.')));
653
    }
654
655
    /**
656
     * @param int   $id
657
     * @param array $values
658
     *
659
     * @return bool
660
     */
661
    public static function editCategory($id, $values)
662
    {
663
        $repo = Container::getLinkCategoryRepository();
664
        /** @var CLinkCategory $category */
665
        $category = $repo->find($id);
666
        $category
667
            ->setCategoryTitle($values['category_title'])
668
            ->setDescription($values['description'])
669
        ;
670
671
        $repo->update($category);
672
673
        Display::addFlash(Display::return_message(get_lang('The category has been modified.')));
674
675
        return true;
676
    }
677
678
    /**
679
     * Changes the visibility of a link.
680
     */
681
    public static function setVisible($id, $scope)
682
    {
683
        if (TOOL_LINK == $scope) {
684
            /*api_item_property_update(
685
                $_course,
686
                TOOL_LINK,
687
                $id,
688
                $_GET['action'],
689
                $_user['user_id']
690
            );*/
691
            $repo = Container::getLinkRepository();
692
            /** @var CLink $link */
693
            $link = $repo->find($id);
694
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
695
                $repo->setVisibilityPublished($link);
696
            }
697
        } elseif (TOOL_LINK_CATEGORY == $scope) {
698
            $repo = Container::getLinkCategoryRepository();
699
            /** @var CLink $link */
700
            $link = $repo->find($id);
701
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
702
                $repo->setVisibilityPublished($link);
703
            }
704
            /*api_item_property_update(
705
                $_course,
706
                TOOL_LINK_CATEGORY,
707
                $id,
708
                $_GET['action'],
709
                $_user['user_id']
710
            );*/
711
        }
712
        Display::addFlash(Display::return_message(get_lang('The visibility has been changed.')));
713
    }
714
715
    public static function setInvisible($id, $scope)
716
    {
717
        if (TOOL_LINK == $scope) {
718
            $repo = Container::getLinkRepository();
719
            /** @var CLink $link */
720
            $link = $repo->find($id);
721
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
722
                $repo->setVisibilityDraft($link);
723
            }
724
        } elseif (TOOL_LINK_CATEGORY == $scope) {
725
            $repo = Container::getLinkCategoryRepository();
726
            /** @var CLinkCategory $link */
727
            $link = $repo->find($id);
728
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLinkCategory, thus it always evaluated to true.
Loading history...
729
                $repo->setVisibilityDraft($link);
730
            }
731
        }
732
        Display::addFlash(Display::return_message(get_lang('The visibility has been changed.')));
733
    }
734
735
    /**
736
     * Generate SQL to select all the links categories in the current course and
737
     * session.
738
     *
739
     * @param int  $courseId
740
     * @param int  $sessionId
741
     * @param bool $withBaseContent
742
     *
743
     * @return CLinkCategory[]
744
     */
745
    public static function getLinkCategories($courseId, $sessionId, $withBaseContent = true)
746
    {
747
        $repo = Container::getLinkCategoryRepository();
748
749
        $courseEntity = api_get_course_entity($courseId);
750
        $sessionEntity = api_get_session_entity($sessionId);
751
752
        $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity);
753
754
        return $qb->getQuery()->getResult();
755
        /*
756
        $tblLinkCategory = Database::get_course_table(TABLE_LINK_CATEGORY);
757
        $tblItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
758
        $courseId = (int) $courseId;
759
        $courseInfo = api_get_course_info_by_id($courseId);
760
761
        // Condition for the session.
762
        $sessionCondition = api_get_session_condition(
763
            $sessionId,
764
            true,
765
            $withBaseContent,
766
            'linkcat.session_id'
767
        );
768
769
        // Getting links
770
        $sql = "SELECT *, linkcat.id
771
                FROM $tblLinkCategory linkcat
772
                WHERE
773
                    linkcat.c_id = $courseId
774
                    $sessionCondition
775
                ORDER BY linkcat.display_order DESC";
776
777
        $result = Database::query($sql);
778
        $categories = Database::store_result($result);
779
780
        $sql = "SELECT *, linkcat.id
781
                FROM $tblLinkCategory linkcat
782
                INNER JOIN $tblItemProperty ip
783
                ON (linkcat.id = ip.ref AND linkcat.c_id = ip.c_id)
784
                WHERE
785
                    ip.tool = '".TOOL_LINK_CATEGORY."' AND
786
                    (ip.visibility = '0' OR ip.visibility = '1')
787
                    $sessionCondition AND
788
                    linkcat.c_id = ".$courseId."
789
                ORDER BY linkcat.display_order DESC";
790
791
        $result = Database::query($sql);
792
793
        $categoryInItemProperty = [];
794
        if (Database::num_rows($result)) {
795
            while ($row = Database::fetch_array($result, 'ASSOC')) {
796
                $categoryInItemProperty[$row['id']] = $row;
797
            }
798
        }
799
800
        foreach ($categories as &$category) {
801
            if (!isset($categoryInItemProperty[$category['id']])) {
802
                api_item_property_update(
803
                    $courseInfo,
804
                    TOOL_LINK_CATEGORY,
805
                    $category['id'],
806
                    'LinkCategoryAdded',
807
                    api_get_user_id()
808
                );
809
            }
810
        }
811
812
        $sql = "SELECT DISTINCT linkcat.*, visibility
813
                FROM $tblLinkCategory linkcat
814
                INNER JOIN $tblItemProperty ip
815
                ON (linkcat.id = ip.ref AND linkcat.c_id = ip.c_id)
816
                WHERE
817
                    ip.tool = '".TOOL_LINK_CATEGORY."' AND
818
                    (ip.visibility = '0' OR ip.visibility = '1')
819
                    $sessionCondition AND
820
                    linkcat.c_id = ".$courseId."
821
                ORDER BY linkcat.display_order DESC
822
                ";
823
        $result = Database::query($sql);
824
825
        return Database::store_result($result, 'ASSOC');*/
826
    }
827
828
    /**
829
     * @param int $categoryId
830
     * @param $courseId
831
     * @param $sessionId
832
     * @param bool $withBaseContent
833
     *
834
     * @return CLink[]|null
835
     */
836
    public static function getLinksPerCategory(
837
        $categoryId,
838
        $courseId,
839
        $sessionId,
840
        $withBaseContent = true
841
    ) {
842
        $courseEntity = api_get_course_entity($courseId);
843
        $sessionEntity = api_get_session_entity($sessionId);
844
845
        if (empty($categoryId)) {
846
            $repo = Container::getLinkRepository();
847
            $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity, null, $courseEntity->getResourceNode());
848
849
            return $qb->getQuery()->getResult();
850
        }
851
852
        $repo = Container::getLinkCategoryRepository();
853
        /** @var CLinkCategory $category */
854
        $category = $repo->find($categoryId);
855
        if ($category) {
0 ignored issues
show
introduced by
$category is of type Chamilo\CourseBundle\Entity\CLinkCategory, thus it always evaluated to true.
Loading history...
856
            $repo = Container::getLinkRepository();
857
            $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity, null, $category->getResourceNode());
858
859
            return $qb->getQuery()->getResult();
860
        }
861
862
        return null;
863
    }
864
865
    /**
866
     * Displays all the links of a given category.
867
     *
868
     * @param int  $categoryId
869
     * @param int  $courseId
870
     * @param int  $sessionId
871
     * @param bool $showActionLinks
872
     *
873
     * @return string
874
     */
875
    public static function showLinksPerCategory($categoryId, $courseId, $sessionId, $showActionLinks = true)
876
    {
877
        global $token;
878
        $links = self::getLinksPerCategory($categoryId, $courseId, $sessionId);
879
        $content = '';
880
        $numberOfLinks = count($links);
881
        if (!empty($links)) {
882
            $courseEntity = api_get_course_entity($courseId);
883
            $sessionEntity = api_get_session_entity($sessionId);
884
            $user = api_get_user_entity();
885
            $i = 1;
886
            $linksAdded = [];
887
            $iconLink = Display::getMdiIcon(ActionIcon::LINK, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Link'));
0 ignored issues
show
Bug introduced by
The constant Chamilo\CoreBundle\Compo...\Utils\ActionIcon::LINK was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
888
            foreach ($links as $link) {
889
                $linkId = $link->getIid();
890
                $resourceLink = $link->getFirstResourceLink();
891
892
                if (in_array($linkId, $linksAdded)) {
893
                    continue;
894
                }
895
896
                $visibility = (int) $link->isVisible($courseEntity, $sessionEntity);
897
898
                $linksAdded[] = $linkId;
899
                $categoryId = 0;
900
                if ($link->getCategory()) {
901
                    $categoryId = $link->getCategory()->getIid();
902
                }
903
904
                // Validation when belongs to a session.
905
                $session_img = '';
906
                $session = $resourceLink->getSession();
907
                if ($session) {
908
                    $session_img = api_get_session_image($session->getId(), $user);
909
                }
910
911
                $toolbar = '';
912
                $link_validator = '';
913
                if (api_is_allowed_to_edit(null, true)) {
914
                    $toolbar .= Display::toolbarButton(
915
                        '',
916
                        'javascript:void(0);',
917
                        'check-circle',
918
                        'secondary btn-sm',
919
                        [
920
                            'onclick' => "check_url('".$linkId."', '".addslashes($link->getUrl())."');",
921
                            'title' => get_lang('Check link'),
922
                        ]
923
                    );
924
925
                    $link_validator .= Display::span(
926
                        '',
927
                        [
928
                        'id' => 'url_id_'.$linkId,
929
                        'class' => 'check-link',
930
                        ]
931
                    );
932
933
                    if ($session === $sessionEntity) {
934
                        $url = api_get_self().'?'.api_get_cidreq().'&action=editlink&id='.$linkId;
935
                        $title = get_lang('Edit');
936
                        $toolbar .= Display::toolbarButton(
937
                            '',
938
                            $url,
939
                            'pencil',
940
                            'secondary btn-sm',
941
                            [
942
                                'title' => $title,
943
                            ]
944
                        );
945
                    }
946
947
                    $urlVisibility = api_get_self().'?'.api_get_cidreq().
948
                            '&sec_token='.$token.
949
                            '&id='.$linkId.
950
                            '&scope=link&category_id='.$categoryId;
951
952
                    switch ($visibility) {
953
                        case 1:
954
                            $urlVisibility .= '&action=invisible';
955
                            $title = get_lang('Make invisible');
956
                            $toolbar .= Display::toolbarButton(
957
                                '',
958
                                $urlVisibility,
959
                                'eye',
960
                                'secondary btn-sm',
961
                                [
962
                                    'title' => $title,
963
                                ]
964
                            );
965
                            break;
966
                        case 0:
967
                            $urlVisibility .= '&action=visible';
968
                            $title = get_lang('Make Visible');
969
                            $toolbar .= Display::toolbarButton(
970
                                '',
971
                                $urlVisibility,
972
                                'eye-off',
973
                                'secondary btn-sm',
974
                                [
975
                                    'title' => $title,
976
                                ]
977
                            );
978
                            break;
979
                    }
980
981
                    if ($session === $sessionEntity) {
982
                        $moveLinkParams = [
983
                            'id' => $linkId,
984
                            'scope' => 'category',
985
                            'category_id' => $categoryId,
986
                            'action' => 'move_link_up',
987
                        ];
988
989
                        $toolbar .= Display::toolbarButton(
990
                            get_lang('Move up'),
991
                            api_get_self().'?'.api_get_cidreq().'&'.http_build_query($moveLinkParams),
992
                            'level-up-alt',
993
                            'secondary',
994
                            ['class' => 'btn-sm '.(1 === $i ? 'disabled' : '')],
995
                            false
996
                        );
997
998
                        $moveLinkParams['action'] = 'move_link_down';
999
                        $toolbar .= Display::toolbarButton(
1000
                            get_lang('Move down'),
1001
                            api_get_self().'?'.api_get_cidreq().'&'.http_build_query($moveLinkParams),
1002
                            'level-down-alt',
1003
                            'secondary',
1004
                            ['class' => 'btn-sm '.($i === $numberOfLinks ? 'disabled' : '')],
1005
                            false
1006
                        );
1007
1008
                        $url = api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=deletelink&id='.$linkId.'&category_id='.$categoryId;
1009
                        $event = "javascript: if(!confirm('".get_lang('Do you want to delete this link?')."'))return false;";
1010
                        $title = get_lang('Delete');
1011
1012
                        $toolbar .= Display::toolbarButton(
1013
                            '',
1014
                            $url,
1015
                            'delete',
1016
                            'secondary btn-sm',
1017
                            [
1018
                                'onclick' => $event,
1019
                                'title' => $title,
1020
                            ]
1021
                        );
1022
                    }
1023
                }
1024
1025
                $showLink = false;
1026
                $titleClass = '';
1027
                if ($visibility) {
1028
                    $showLink = true;
1029
                } else {
1030
                    if (api_is_allowed_to_edit(null, true)) {
1031
                        $showLink = true;
1032
                        $titleClass = 'text-muted';
1033
                    }
1034
                }
1035
1036
                if ($showLink) {
1037
                    $url = api_get_path(WEB_CODE_PATH).'link/link_goto.php?'.api_get_cidreq().'&link_id='.$linkId.'&link_url='.urlencode($link->getUrl());
1038
                    $actions = '';
1039
                    if ($showActionLinks) {
1040
                        $actions .= $toolbar;
1041
                    }
1042
1043
                    $title = $iconLink;
1044
                    $title .= Display::tag(
1045
                        'a',
1046
                        Security::remove_XSS($link->getTitle()),
1047
                        [
1048
                            'href' => $url,
1049
                            'target' => $link->getTarget(),
1050
                            'class' => $titleClass,
1051
                        ]
1052
                    );
1053
                    $title .= $link_validator;
1054
                    $title .= $session_img;
1055
                    $content .= Display::panel(null, $title, null, null, null, null, null, $actions);
1056
                }
1057
                $i++;
1058
            }
1059
        }
1060
1061
        return $content;
1062
    }
1063
1064
    /**
1065
     * Displays the edit, delete and move icons.
1066
     *
1067
     * @param int   Category ID
1068
     * @param int $currentCategory
1069
     * @param int $countCategories
1070
     *
1071
     * @return string
1072
     *
1073
     * @author Patrick Cool <[email protected]>, Ghent University
1074
     */
1075
    public static function showCategoryAdminTools(CLinkCategory $category, $currentCategory, $countCategories)
1076
    {
1077
        $categoryId = $category->getIid();
1078
        $token = null;
1079
        $tools = '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=editcategory&id='.$categoryId.'&category_id='.$categoryId.'" title='.get_lang('Edit').'">'.
1080
            Display::getMdiIcon(
1081
                ActionIcon::EDIT,
1082
                'ch-tool-icon',
1083
                null,
1084
                ICON_SIZE_SMALL,
1085
                get_lang('Edit')
1086
            ).'</a>';
1087
1088
        // DISPLAY MOVE UP COMMAND only if it is not the top link.
1089
        if (0 != $currentCategory) {
1090
            $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=up&up='.$categoryId.'&category_id='.$categoryId.'" title="'.get_lang('Up').'">'.
1091
                Display::getMdiIcon(
1092
                    ActionIcon::UP,
1093
                    'ch-tool-icon',
1094
                    null,
1095
                    ICON_SIZE_SMALL,
1096
                    get_lang('Up')
1097
                ).'</a>';
1098
        } else {
1099
            $tools .= Display::getMdiIcon(
1100
                ActionIcon::UP,
1101
                'ch-tool-icon-disabled',
1102
                null,
1103
                ICON_SIZE_SMALL,
1104
                get_lang('Up')
1105
            ).'</a>';
1106
        }
1107
1108
        // DISPLAY MOVE DOWN COMMAND only if it is not the bottom link.
1109
        if ($currentCategory < $countCategories - 1) {
1110
            $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=down&down='.$categoryId.'&category_id='.$categoryId.'">'.
1111
                Display::getMdiIcon(
1112
                    ActionIcon::DOWN,
1113
                    'ch-tool-icon',
1114
                    null,
1115
                    ICON_SIZE_SMALL,
1116
                    get_lang('down')
1117
                ).'</a>';
1118
        } else {
1119
            $tools .= Display::getMdiIcon(
1120
                ActionIcon::DOWN,
1121
                'ch-tool-icon-disabled',
1122
                null,
1123
                ICON_SIZE_SMALL,
1124
                get_lang('down')
1125
                ).'</a>';
1126
        }
1127
1128
        $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=deletecategory&id='.$categoryId."&category_id=$categoryId\"
1129
            onclick=\"javascript: if(!confirm('".get_lang('When deleting a category, all links of this category are also deleted.
1130
Do you really want to delete this category and its links ?')."')) return false;\">".
1131
            Display::getMdiIcon(
1132
                ActionIcon::DELETE,
1133
                'ch-tool-icon',
1134
                null,
1135
                ICON_SIZE_SMALL,
1136
                get_lang('Delete')
1137
            ).'</a>';
1138
1139
        return $tools;
1140
    }
1141
1142
    /**
1143
     * move a link or a linkcategory up or down.
1144
     *
1145
     * @param   int Category ID
1146
     * @param   int Course ID
1147
     * @param   int Session ID
1148
     *
1149
     * @author Patrick Cool <[email protected]>, Ghent University
1150
     *
1151
     * @todo support sessions
1152
     */
1153
    public static function movecatlink($action, $catlinkid, $courseId = null, $sessionId = null)
1154
    {
1155
        $tbl_categories = Database::get_course_table(TABLE_LINK_CATEGORY);
1156
1157
        if (is_null($courseId)) {
1158
            $courseId = api_get_course_int_id();
1159
        }
1160
        $courseId = intval($courseId);
1161
        if (is_null($sessionId)) {
1162
            $sessionId = api_get_session_id();
1163
        }
1164
        $sessionId = intval($sessionId);
1165
        $thiscatlinkId = intval($catlinkid);
1166
1167
        if ('down' == $action) {
1168
            $sortDirection = 'DESC';
1169
        }
1170
1171
        if ('up' == $action) {
1172
            $sortDirection = 'ASC';
1173
        }
1174
1175
        $movetable = $tbl_categories;
1176
1177
        if (!empty($sortDirection)) {
1178
            if (!in_array(trim(strtoupper($sortDirection)), ['ASC', 'DESC'])) {
1179
                $sortDirection = 'ASC';
1180
            }
1181
1182
            $sql = "SELECT id, display_order FROM $tbl_categories
1183
                    WHERE c_id = $courseId
1184
                    ORDER BY display_order $sortDirection";
1185
            $linkresult = Database:: query($sql);
1186
            $thislinkOrder = 1;
1187
            while ($sortrow = Database:: fetch_array($linkresult)) {
1188
                // STEP 2 : FOUND THE NEXT LINK ID AND ORDER, COMMIT SWAP
1189
                // This part seems unlogic, but it isn't . We first look for the current link with the querystring ID
1190
                // and we know the next iteration of the while loop is the next one. These should be swapped.
1191
                if (isset($thislinkFound) && $thislinkFound) {
1192
                    $nextlinkId = $sortrow['id'];
1193
                    $nextlinkOrder = $sortrow['display_order'];
1194
1195
                    Database:: query(
1196
                        "UPDATE ".$movetable."
1197
                        SET display_order = '$nextlinkOrder'
1198
                        WHERE c_id = $courseId  AND id =  '$thiscatlinkId'"
1199
                    );
1200
                    Database:: query(
1201
                        "UPDATE ".$movetable."
1202
                        SET display_order = '$thislinkOrder'
1203
                        WHERE c_id = $courseId  AND id =  '$nextlinkId'"
1204
                    );
1205
1206
                    break;
1207
                }
1208
                if ($sortrow['id'] == $thiscatlinkId) {
1209
                    $thislinkOrder = $sortrow['display_order'];
1210
                    $thislinkFound = true;
1211
                }
1212
            }
1213
        }
1214
1215
        Display::addFlash(Display::return_message(get_lang('LinksMoved')));
1216
    }
1217
1218
    /**
1219
     * This function checks if the url is a vimeo link.
1220
     *
1221
     * @author Julio Montoya
1222
     *
1223
     * @version 1.0
1224
     */
1225
    public static function isVimeoLink($url)
1226
    {
1227
        $isLink = strrpos($url, 'vimeo.com');
1228
1229
        return $isLink;
1230
    }
1231
1232
    /**
1233
     * Get vimeo id from URL.
1234
     *
1235
     * @param string $url
1236
     *
1237
     * @return bool|mixed
1238
     */
1239
    public static function getVimeoLinkId($url)
1240
    {
1241
        $possibleUrls = [
1242
            'http://www.vimeo.com/',
1243
            'http://vimeo.com/',
1244
            'https://www.vimeo.com/',
1245
            'https://vimeo.com/',
1246
        ];
1247
        $url = str_replace($possibleUrls, '', $url);
1248
1249
        if (is_numeric($url)) {
1250
            return $url;
1251
        }
1252
1253
        return false;
1254
    }
1255
1256
    /**
1257
     * This function checks if the url is a youtube link.
1258
     *
1259
     * @author Jorge Frisancho
1260
     * @author Julio Montoya - Fixing code
1261
     *
1262
     * @version 1.0
1263
     */
1264
    public static function is_youtube_link($url)
1265
    {
1266
        $is_youtube_link = strrpos($url, 'youtube') || strrpos(
1267
            $url,
1268
            'youtu.be'
1269
        );
1270
1271
        return $is_youtube_link;
1272
    }
1273
1274
    /**
1275
     * This function checks if the url is a PDF File link.
1276
     *
1277
     * @author Jorge Frisancho
1278
     * @author Alex Aragón - Fixing code
1279
     *
1280
     * @version 1.0
1281
     */
1282
    public static function isPdfLink($url)
1283
    {
1284
        $isPdfLink = strrpos(strtolower($url), '.pdf');
1285
1286
        return $isPdfLink;
1287
    }
1288
1289
    /**
1290
     * Get youtube id from an URL.
1291
     *
1292
     * @param string $url
1293
     *
1294
     * @return string
1295
     */
1296
    public static function get_youtube_video_id($url)
1297
    {
1298
        // This is the length of YouTube's video IDs
1299
        $len = 11;
1300
1301
        // The ID string starts after "v=", which is usually right after
1302
        // "youtube.com/watch?" in the URL
1303
        $pos = strpos($url, "v=");
1304
        $id = '';
1305
1306
        //If false try other options
1307
        if (false === $pos) {
1308
            $url_parsed = parse_url($url);
1309
1310
            //Youtube shortener
1311
            //http://youtu.be/ID
1312
            $pos = strpos($url, "youtu.be");
1313
1314
            if (false == $pos) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $pos of type integer to the boolean false. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
1315
                $id = '';
1316
            } else {
1317
                return substr($url_parsed['path'], 1);
1318
            }
1319
1320
            //if empty try the youtube.com/embed/ID
1321
            if (empty($id)) {
1322
                $pos = strpos($url, "embed");
1323
                if (false === $pos) {
1324
                    return '';
1325
                } else {
1326
                    return substr($url_parsed['path'], 7);
1327
                }
1328
            }
1329
        } else {
1330
            // Offset the start location to match the beginning of the ID string
1331
            $pos += 2;
1332
            // Get the ID string and return it
1333
            $id = substr($url, $pos, $len);
1334
1335
            return $id;
1336
        }
1337
    }
1338
1339
    /**
1340
     * @param int    $courseId
1341
     * @param int    $sessionId
1342
     * @param int    $categoryId
1343
     * @param string $show
1344
     * @param null   $token
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $token is correct as it would always require null to be passed?
Loading history...
1345
     * @param bool   $showActionLinks
1346
     * @param bool   $forceOpenCategories
1347
     *
1348
     * @return string
1349
     */
1350
    public static function listLinksAndCategories(
1351
        $courseId,
1352
        $sessionId,
1353
        $categoryId,
1354
        $show = 'none',
1355
        $token = null,
1356
        $showActionLinks = true,
1357
        $forceOpenCategories = false
1358
    ) {
1359
        $categoryId = (int) $categoryId;
1360
        $content = '';
1361
        $toolbar = '';
1362
        $categories = self::getLinkCategories($courseId, $sessionId);
1363
        $countCategories = count($categories);
1364
        $linksPerCategory = self::showLinksPerCategory(0, $courseId, $sessionId, $showActionLinks);
1365
1366
        if ($showActionLinks) {
1367
            /*	Action Links */
1368
            $actions = '';
1369
            if (api_is_allowed_to_edit(null, true)) {
1370
                $actions .= '<a
1371
                    href="'.api_get_self().'?'.api_get_cidreq().'&action=addlink&category_id='.$categoryId.'">'.
1372
                    Display::getMdiIcon(ActionIcon::ADD, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Add a link')).'</a>';
1373
                $actions .= '<a
1374
                    href="'.api_get_self().'?'.api_get_cidreq().'&action=addcategory&category_id='.$categoryId.'">'.
1375
                    Display::getMdiIcon(ActionIcon::CREATE_CATEGORY, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Add a category')).'</a>';
1376
            }
1377
1378
            if (!empty($countCategories)) {
1379
                $actions .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=list&show=none">';
1380
                $actions .= Display::getMdiIcon(StateIcon::LIST_VIEW, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('List View')).' </a>';
1381
1382
                $actions .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=list&show=all">';
1383
                $actions .= Display::getMdiIcon(StateIcon::NESTED_VIEW, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Nested View')).'</a>';
1384
            }
1385
            $actions .= Display::url(
1386
                Display::getMdiIcon(ActionIcon::EXPORT_PDF, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Export to PDF')),
1387
                api_get_self().'?'.api_get_cidreq().'&action=export'
1388
            );
1389
            $toolbar = Display::toolbarAction('toolbar', [$actions]);
1390
        }
1391
1392
        if (empty($countCategories)) {
1393
            $content .= $linksPerCategory;
1394
        } else {
1395
            if (!empty($linksPerCategory)) {
1396
                $content .= Display::panel($linksPerCategory, get_lang('General'));
1397
            }
1398
        }
1399
1400
        $counter = 0;
1401
        $courseEntity = api_get_course_entity($courseId);
1402
        $sessionEntity = api_get_session_entity($sessionId);
1403
        $allowToEdit = api_is_allowed_to_edit(null, true);
1404
1405
        foreach ($categories as $category) {
1406
            $categoryItemId = $category->getIid();
1407
            $isVisible = $category->isVisible($courseEntity, $sessionEntity);
1408
            // Student don't see invisible categories.
1409
            if (!$allowToEdit) {
1410
                if (!$isVisible) {
1411
                    continue;
1412
                }
1413
            }
1414
1415
            // Validation when belongs to a session
1416
            $showChildren = $categoryId === $categoryItemId || 'all' === $show;
1417
            if ($forceOpenCategories) {
1418
                $showChildren = true;
1419
            }
1420
1421
            $strVisibility = '';
1422
            $visibilityClass = null;
1423
            if ($isVisible) {
1424
                $strVisibility = '<a
1425
                    href="link.php?'.api_get_cidreq().'&sec_token='.$token.'&action=invisible&id='.$categoryItemId.'&scope='.TOOL_LINK_CATEGORY.'"
1426
                    title="'.get_lang('Hide').'">'.
1427
                    Display::getMdiIcon(StateIcon::ACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Hide')).'</a>';
1428
            } elseif (!$isVisible) {
1429
                $visibilityClass = 'text-muted';
1430
                $strVisibility = ' <a
1431
                    href="link.php?'.api_get_cidreq().'&sec_token='.$token.'&action=visible&id='.$categoryItemId.'&scope='.TOOL_LINK_CATEGORY.'"
1432
                    title="'.get_lang('Show').'">'.
1433
                    Display::getMdiIcon(StateIcon::INACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Show')).'</a>';
1434
            }
1435
1436
            $header = '';
1437
            if ($showChildren) {
1438
                $header .= '<a
1439
                    class="'.$visibilityClass.'" href="'.api_get_self().'?'.api_get_cidreq().'&category_id=">';
1440
                $header .= Display::getMdiIcon(StateIcon::NESTED_VIEW, 'ch-tool-icon', null, ICON_SIZE_SMALL);
1441
            } else {
1442
                $header .= '<a
1443
                    class="'.$visibilityClass.'"
1444
                    href="'.api_get_self().'?'.api_get_cidreq().'&category_id='.$categoryItemId.'">';
1445
                $header .= Display::getMdiIcon(StateIcon::LIST_VIEW, 'ch-tool-icon', null, ICON_SIZE_SMALL);
1446
            }
1447
            $header .= Security::remove_XSS($category->getCategoryTitle()).'</a>';
0 ignored issues
show
Bug introduced by
Are you sure Security::remove_XSS($ca...ry->getCategoryTitle()) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

1447
            $header .= /** @scrutinizer ignore-type */ Security::remove_XSS($category->getCategoryTitle()).'</a>';
Loading history...
1448
1449
            if ($showActionLinks) {
1450
                if ($allowToEdit) {
1451
                    if ($category->getFirstResourceLink() &&
1452
                        $sessionEntity === $category->getFirstResourceLink()->getSession()
1453
                    ) {
1454
                        $header .= $strVisibility;
1455
                        $header .= self::showCategoryAdminTools($category, $counter, count($categories));
1456
                    } else {
1457
                        $header .= get_lang('Edition not available from the session, please edit from the basic course.');
1458
                    }
1459
                }
1460
            }
1461
1462
            $childrenContent = '';
1463
            if ($showChildren) {
1464
                $childrenContent = self::showLinksPerCategory(
1465
                    $categoryItemId,
1466
                    api_get_course_int_id(),
1467
                    api_get_session_id()
1468
                );
1469
            }
1470
1471
            $content .= Display::panel($category->getDescription().$childrenContent, $header);
1472
            $counter++;
1473
        }
1474
1475
        if (empty($content) && api_is_allowed_to_edit()) {
1476
            $content .= Display::noDataView(
1477
                get_lang('Links'),
1478
                Display::getMdiIcon(ObjectIcon::LINK, 'ch-tool-icon', null, ICON_SIZE_BIG),
1479
                get_lang('Add links'),
1480
                api_get_self().'?'.api_get_cidreq().'&'.http_build_query(['action' => 'addlink'])
1481
            );
1482
        }
1483
1484
        return $toolbar.$content;
1485
    }
1486
1487
    /**
1488
     * @param int    $linkId
1489
     * @param string $action
1490
     * @param null   $token
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $token is correct as it would always require null to be passed?
Loading history...
1491
     *
1492
     * @return FormValidator
1493
     */
1494
    public static function getLinkForm($linkId, $action, $token = null)
1495
    {
1496
        $courseId = api_get_course_int_id();
1497
        $sessionId = api_get_session_id();
1498
        $linkInfo = self::getLinkInfo($linkId);
1499
        $categoryId = isset($linkInfo['category_id']) ? $linkInfo['category_id'] : '';
1500
        $lpId = isset($_GET['lp_id']) ? Security::remove_XSS($_GET['lp_id']) : null;
1501
1502
        $form = new FormValidator(
1503
            'link',
1504
            'post',
1505
            api_get_self().'?action='.$action.
1506
            '&category_id='.$categoryId.
1507
            '&'.api_get_cidreq().
1508
            '&id='.$linkId.
1509
            '&sec_token='.$token
1510
        );
1511
1512
        if ('addlink' === $action) {
1513
            $form->addHeader(get_lang('Add a link'));
1514
        } else {
1515
            $form->addHeader(get_lang('Edit link'));
1516
        }
1517
1518
        $target_link = '_blank';
1519
        $title = '';
1520
        $category = '';
1521
        $onhomepage = '';
1522
        $description = '';
1523
1524
        if (!empty($linkInfo)) {
1525
            $urllink = $linkInfo['url'];
1526
            $title = $linkInfo['title'];
1527
            $description = $linkInfo['description'];
1528
            $category = $linkInfo['category_id'];
1529
            if (isset($linkInfo['on_homepage']) && 0 != $linkInfo['on_homepage']) {
1530
                $onhomepage = 1;
1531
            }
1532
            $target_link = $linkInfo['target'];
1533
        }
1534
1535
        $form->addHidden('id', $linkId);
1536
        $form->addText('url', 'URL');
1537
        $form->addRule('url', get_lang('Please give the link URL, it should be valid.'), 'url');
1538
        $form->addText('title', get_lang('Link name'));
1539
        $form->addHtmlEditor(
1540
            'description',
1541
            get_lang('Description'),
1542
            false,
1543
            false,
1544
            ['ToolbarSet' => 'Profile', 'Width' => '100%', 'Height' => '130']
1545
        );
1546
1547
        $resultcategories = self::getLinkCategories($courseId, $sessionId);
1548
        $options = ['0' => '--'];
1549
        if (!empty($resultcategories)) {
1550
            foreach ($resultcategories as $myrow) {
1551
                $options[$myrow->getIid()] = $myrow->getCategoryTitle();
1552
            }
1553
        }
1554
1555
        $form->addSelect('category_id', get_lang('Category'), $options);
1556
        $form->addCheckBox('on_homepage', null, get_lang('Show link on course homepage'));
1557
1558
        $targets = [
1559
            '_self' => get_lang('Open self'),
1560
            '_blank' => get_lang('Open blank'),
1561
            '_parent' => get_lang('Open parent'),
1562
            '_top' => get_lang('Open top'),
1563
        ];
1564
1565
        $form->addSelect(
1566
            'target',
1567
            [
1568
                get_lang('Link\'s target'),
1569
                get_lang('Select the target which shows the link on the homepage of the course'),
1570
            ],
1571
            $targets
1572
        );
1573
1574
        $defaults = [
1575
            'url' => empty($urllink) ? 'http://' : Security::remove_XSS($urllink),
1576
            'title' => Security::remove_XSS($title),
1577
            'category_id' => $category,
1578
            'on_homepage' => $onhomepage,
1579
            'description' => $description,
1580
            'target' => $target_link,
1581
        ];
1582
1583
        if ('true' === api_get_setting('search_enabled')) {
1584
            $specific_fields = get_specific_field_list();
1585
            $form->addCheckBox('index_document', get_lang('Index link title and description?s'), get_lang('Yes'));
1586
1587
            foreach ($specific_fields as $specific_field) {
1588
                $default_values = '';
1589
                if ('editlink' === $action) {
1590
                    $filter = [
1591
                        'field_id' => $specific_field['id'],
1592
                        'ref_id' => intval($_GET['id']),
1593
                        'tool_id' => '\''.TOOL_LINK.'\'',
1594
                    ];
1595
                    $values = get_specific_field_values_list($filter, ['value']);
1596
                    if (!empty($values)) {
1597
                        $arr_str_values = [];
1598
                        foreach ($values as $value) {
1599
                            $arr_str_values[] = $value['value'];
1600
                        }
1601
                        $default_values = implode(', ', $arr_str_values);
1602
                    }
1603
                }
1604
                $form->addText($specific_field['name'], $specific_field['code']);
1605
                $defaults[$specific_field['name']] = $default_values;
1606
            }
1607
        }
1608
1609
        $skillList = SkillModel::addSkillsToForm($form, ITEM_TYPE_LINK, $linkId);
1610
        $form->addHidden('lp_id', $lpId);
1611
        $form->addButtonSave(get_lang('Save links'), 'submitLink');
1612
        $defaults['skills'] = array_keys($skillList);
1613
        $form->setDefaults($defaults);
1614
1615
        return $form;
1616
    }
1617
1618
    /**
1619
     * @param int    $id
1620
     * @param string $action
1621
     *
1622
     * @return FormValidator
1623
     */
1624
    public static function getCategoryForm($id, $action)
1625
    {
1626
        $id = (int) $id;
1627
        $action = Security::remove_XSS($action);
1628
1629
        $form = new FormValidator(
1630
            'category',
1631
            'post',
1632
            api_get_self().'?action='.$action.'&'.api_get_cidreq()
0 ignored issues
show
Bug introduced by
Are you sure $action of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

1632
            api_get_self().'?action='./** @scrutinizer ignore-type */ $action.'&'.api_get_cidreq()
Loading history...
1633
        );
1634
1635
        $defaults = [];
1636
        if ('addcategory' === $action) {
1637
            $form->addHeader(get_lang('Add a category'));
1638
            $my_cat_title = get_lang('Add a category');
1639
        } else {
1640
            $form->addHeader(get_lang('Edit Category'));
1641
            $my_cat_title = get_lang('Edit Category');
1642
            $defaults = self::getCategory($id);
1643
        }
1644
        $form->addHidden('id', $id);
1645
        $form->addText('category_title', get_lang('Category name'));
1646
        $form->addHtmlEditor(
1647
            'description',
1648
            get_lang('Description'),
1649
            false,
1650
            false,
1651
            ['ToolbarSet' => 'Profile', 'Width' => '100%', 'Height' => '130']
1652
        );
1653
        $form->addButtonSave($my_cat_title, 'submitCategory');
1654
        $form->setDefaults($defaults);
1655
1656
        return $form;
1657
    }
1658
1659
    /**
1660
     * @param int $id
1661
     *
1662
     * @return array
1663
     */
1664
    public static function getCategory($id)
1665
    {
1666
        $table = Database::get_course_table(TABLE_LINK_CATEGORY);
1667
        $id = (int) $id;
1668
        $courseId = api_get_course_int_id();
1669
1670
        if (empty($id) || empty($courseId)) {
1671
            return [];
1672
        }
1673
        $sql = "SELECT * FROM $table
1674
                WHERE iid = $id";
1675
        $result = Database::query($sql);
1676
1677
        return Database::fetch_array($result, 'ASSOC');
1678
    }
1679
1680
    /**
1681
     * Move a link up in its category.
1682
     *
1683
     * @param int $id
1684
     *
1685
     * @return bool
1686
     */
1687
    public static function moveLinkUp($id)
1688
    {
1689
        return self::moveLinkDisplayOrder($id, 'ASC');
1690
    }
1691
1692
    /**
1693
     * Move a link down in its category.
1694
     *
1695
     * @param int $id
1696
     *
1697
     * @return bool
1698
     */
1699
    public static function moveLinkDown($id)
1700
    {
1701
        return self::moveLinkDisplayOrder($id, 'DESC');
1702
    }
1703
1704
    /**
1705
     * @param string $url
1706
     *
1707
     * @return bool
1708
     */
1709
    public static function checkUrl($url)
1710
    {
1711
        // Check if curl is available.
1712
        if (!in_array('curl', get_loaded_extensions())) {
1713
            return false;
1714
        }
1715
1716
        // set URL and other appropriate options
1717
        $defaults = [
1718
            CURLOPT_URL => $url,
1719
            CURLOPT_FOLLOWLOCATION => true, // follow redirects accept youtube.com
1720
            CURLOPT_HEADER => 0,
1721
            CURLOPT_RETURNTRANSFER => true,
1722
            CURLOPT_TIMEOUT => 4,
1723
        ];
1724
1725
        $proxySettings = api_get_setting('platform.proxy_settings', true);
1726
1727
        if (!empty($proxySettings) &&
1728
            isset($proxySettings['curl_setopt_array'])
1729
        ) {
1730
            $defaults[CURLOPT_PROXY] = $proxySettings['curl_setopt_array']['CURLOPT_PROXY'];
1731
            $defaults[CURLOPT_PROXYPORT] = $proxySettings['curl_setopt_array']['CURLOPT_PROXYPORT'];
1732
        }
1733
1734
        // Create a new cURL resource
1735
        $ch = curl_init();
1736
        curl_setopt_array($ch, $defaults);
1737
1738
        // grab URL and pass it to the browser
1739
        ob_start();
1740
        $result = curl_exec($ch);
1741
        ob_get_clean();
1742
1743
        // close cURL resource, and free up system resources
1744
        curl_close($ch);
1745
1746
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type string which is incompatible with the documented return type boolean.
Loading history...
1747
    }
1748
1749
    /**
1750
     * Move a link inside its category (display_order field).
1751
     *
1752
     * @param int    $id        The link ID
1753
     * @param string $direction The direction to sort the links
1754
     *
1755
     * @return bool
1756
     */
1757
    private static function moveLinkDisplayOrder($id, $direction)
1758
    {
1759
        $em = Database::getManager();
1760
        $repo = Container::getLinkRepository();
1761
1762
        /** @var CLink $link */
1763
        $link = $repo->find($id);
1764
1765
        if (!$link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
1766
            return false;
1767
        }
1768
1769
        $compareLinks = $repo
1770
            ->findBy(
1771
                [
1772
                    'categoryId' => $link->getCategory() ? $link->getCategory()->getIid() : 0,
1773
                ],
1774
                ['displayOrder' => $direction]
1775
            );
1776
1777
        /** @var CLink $prevLink */
1778
        $prevLink = null;
1779
1780
        /** @var CLink $compareLink */
1781
        foreach ($compareLinks as $compareLink) {
1782
            if ($compareLink->getIid() !== $link->getIid()) {
1783
                $prevLink = $compareLink;
1784
1785
                continue;
1786
            }
1787
1788
            if (!$prevLink) {
1789
                return false;
1790
            }
1791
1792
            $newPrevLinkDisplayOrder = $link->getDisplayOrder();
1793
            $newLinkDisplayOrder = $prevLink->getDisplayOrder();
1794
1795
            $link->setDisplayOrder($newLinkDisplayOrder);
1796
            $prevLink->setDisplayOrder($newPrevLinkDisplayOrder);
1797
1798
            $em->persist($prevLink);
1799
            $em->persist($link);
1800
            break;
1801
        }
1802
1803
        $em->flush();
1804
1805
        return true;
1806
    }
1807
}
1808