Passed
Push — master ( 44ae74...4bbff2 )
by Julito
10:31
created

Link::is_youtube_link()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
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
9
/**
10
 * Function library for the links tool.
11
 *
12
 * This is a complete remake of the original link tool.
13
 * New features:
14
 * - Organize links into categories;
15
 * - favorites/bookmarks interface;
16
 * - move links up/down within a category;
17
 * - move categories up/down;
18
 * - expand/collapse all categories;
19
 * - add link to 'root' category => category-less link is always visible.
20
 *
21
 * @author Patrick Cool (December 2003 - January 2004)
22
 * @author René Haentjens, CSV file import (October 2004)
23
 */
24
class Link extends Model
25
{
26
    public $table;
27
    public $is_course_model = true;
28
    public $columns = [
29
        'id',
30
        'c_id',
31
        'url',
32
        'title',
33
        'description',
34
        'category_id',
35
        'display_order',
36
        'on_homepage',
37
        'target',
38
        'session_id',
39
    ];
40
    public $required = ['url', 'title'];
41
    private $course;
42
43
    /**
44
     * Link constructor.
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(Display::return_message(get_lang('Please give the link URL, it should be valid.'), 'error'));
116
117
            return false;
118
        } else {
119
            $category = null;
120
            $repoCategory = Container::getLinkCategoryRepository();
121
            if (!empty($categoryId)) {
122
                /** @var CLinkCategory $category */
123
                $category = $repoCategory->find($categoryId);
124
            }
125
126
            // Looking for the largest order number for this category.
127
            $link = new CLink();
128
            $link
129
                ->setUrl($urllink)
130
                ->setTitle($title)
131
                ->setDescription($description)
132
                ->setOnHomepage($onhomepage)
133
                ->setTarget($target)
134
                ->setCategory($category)
135
            ;
136
137
            $repo = Container::getLinkRepository();
138
            $courseEntity = api_get_course_entity($course_id);
139
            if (empty($category)) {
140
                $link
141
                    ->setParent($courseEntity)
142
                    ->addCourseLink($courseEntity, api_get_session_entity($session_id))
143
                ;
144
            } else {
145
                $link
146
                    ->setParent($category)
147
                    ->addCourseLink($courseEntity, api_get_session_entity($session_id))
148
                ;
149
            }
150
151
            $repo->create($link);
152
            $link_id = $link->getIid();
153
154
            if (('true' === api_get_setting('search_enabled')) &&
155
                $link_id && extension_loaded('xapian')
156
            ) {
157
                $courseCode = $course_info['code'];
158
                $specific_fields = get_specific_field_list();
159
                $ic_slide = new IndexableChunk();
160
161
                // Add all terms to db.
162
                $all_specific_terms = '';
163
                foreach ($specific_fields as $specific_field) {
164
                    if (isset($_REQUEST[$specific_field['code']])) {
165
                        $sterms = trim($_REQUEST[$specific_field['code']]);
166
                        if (!empty($sterms)) {
167
                            $all_specific_terms .= ' '.$sterms;
168
                            $sterms = explode(',', $sterms);
169
                            foreach ($sterms as $sterm) {
170
                                $ic_slide->addTerm(
171
                                    trim($sterm),
172
                                    $specific_field['code']
173
                                );
174
                                add_specific_field_value(
175
                                    $specific_field['id'],
176
                                    $courseCode,
177
                                    TOOL_LINK,
178
                                    $link_id,
179
                                    $sterm
180
                                );
181
                            }
182
                        }
183
                    }
184
                }
185
186
                // Build the chunk to index.
187
                $ic_slide->addValue('title', $title);
188
                $ic_slide->addCourseId($courseCode);
189
                $ic_slide->addToolId(TOOL_LINK);
190
                $xapian_data = [
191
                    SE_COURSE_ID => $courseCode,
192
                    SE_TOOL_ID => TOOL_LINK,
193
                    SE_DATA => [
194
                        'link_id' => $link_id,
195
                    ],
196
                    SE_USER => (int) api_get_user_id(),
197
                ];
198
                $ic_slide->xapian_data = serialize($xapian_data);
199
                $description = $all_specific_terms.' '.$description;
200
                $ic_slide->addValue('content', $description);
201
202
                // Add category name if set.
203
                if (isset($categoryId) && $categoryId > 0) {
204
                    $table_link_category = Database::get_course_table(
205
                        TABLE_LINK_CATEGORY
206
                    );
207
                    $sql_cat = 'SELECT * FROM %s WHERE id=%d AND c_id = %d LIMIT 1';
208
                    $sql_cat = sprintf(
209
                        $sql_cat,
210
                        $table_link_category,
211
                        $categoryId,
212
                        $course_id
213
                    );
214
                    $result = Database:: query($sql_cat);
215
                    if (1 == Database:: num_rows($result)) {
216
                        $row = Database:: fetch_array($result);
217
                        $ic_slide->addValue(
218
                            'category',
219
                            $row['category_title']
220
                        );
221
                    }
222
                }
223
224
                $di = new ChamiloIndexer();
225
                isset($params['language']) ? $lang = Database:: escape_string(
226
                    $params['language']
227
                ) : $lang = 'english';
228
                $di->connectDb(null, null, $lang);
229
                $di->addChunk($ic_slide);
230
231
                // Index and return search engine document id.
232
                $did = $di->index();
233
                if ($did) {
234
                    // Save it to db.
235
                    $tbl_se_ref = Database::get_main_table(
236
                        TABLE_MAIN_SEARCH_ENGINE_REF
237
                    );
238
                    $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
239
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
240
                    $sql = sprintf(
241
                        $sql,
242
                        $tbl_se_ref,
243
                        $course_id,
244
                        $courseCode,
245
                        TOOL_LINK,
246
                        $link_id,
247
                        $did
248
                    );
249
                    Database:: query($sql);
250
                }
251
            }
252
            if ($showFlash) {
253
                Display::addFlash(Display::return_message(get_lang('The link has been added.')));
254
            }
255
256
            return $link_id;
257
        }
258
    }
259
260
    /**
261
     * Update a link in the database.
262
     *
263
     * @param int    $linkId    The ID of the link to update
264
     * @param string $linkUrl   The new URL to be saved
265
     * @param int    $courseId
266
     * @param int    $sessionId
267
     *
268
     * @return bool
269
     */
270
    public function updateLink(
271
        $linkId,
272
        $linkUrl,
273
        $courseId = null,
274
        $sessionId = null
275
    ) {
276
        $tblLink = Database::get_course_table(TABLE_LINK);
277
        $linkUrl = Database::escape_string($linkUrl);
278
        $linkId = (int) $linkId;
279
        if (is_null($courseId)) {
280
            $courseId = api_get_course_int_id();
281
        }
282
        $courseId = (int) $courseId;
283
        if (is_null($sessionId)) {
284
            $sessionId = api_get_session_id();
285
        }
286
        $sessionId = (int) $sessionId;
287
        if ('' != $linkUrl) {
288
            $sql = "UPDATE $tblLink SET
289
                    url = '$linkUrl'
290
                    WHERE iid = $linkId ";
291
            $resLink = Database::query($sql);
292
293
            return $resLink;
294
        }
295
296
        return false;
297
    }
298
299
    public static function addCategory()
300
    {
301
        $_course = api_get_course_info();
302
        $course_id = $_course['real_id'];
303
        $category_title = trim($_POST['category_title']);
304
        $description = trim($_POST['description']);
305
306
        if (empty($category_title)) {
307
            echo Display::return_message(get_lang('Please give the category name'), 'error');
308
309
            return false;
310
        }
311
312
        // Looking for the largest order number for this category.
313
        /*$result = Database:: query(
314
            "SELECT MAX(display_order) FROM  $tbl_categories
315
            WHERE c_id = $course_id "
316
        );
317
        [$orderMax] = Database:: fetch_row($result);
318
        $order = $orderMax + 1;
319
        $order = (int) $order;*/
320
        $session_id = api_get_session_id();
321
322
        $repo = Container::getLinkCategoryRepository();
323
        $courseEntity = api_get_course_entity($course_id);
324
        $sessionEntity = api_get_session_entity($session_id);
325
326
        $category = new CLinkCategory();
327
        $category
328
            ->setCategoryTitle($category_title)
329
            ->setDescription($description)
330
         //   ->setDisplayOrder($order)
331
            ->setParent($courseEntity)
332
            ->addCourseLink($courseEntity, $sessionEntity)
333
        ;
334
335
        $repo->create($category);
336
        $linkId = $category->getIid();
337
338
        if ($linkId) {
339
            // add link_category visibility
340
            // course ID is taken from context in api_set_default_visibility
341
            //api_set_default_visibility($linkId, TOOL_LINK_CATEGORY);
342
            /*api_item_property_update(
343
                $_course,
344
                TOOL_LINK_CATEGORY,
345
                $linkId,
346
                'LinkCategoryAdded',
347
                api_get_user_id()
348
            );
349
            api_set_default_visibility($linkId, TOOL_LINK_CATEGORY);*/
350
        }
351
352
        Display::addFlash(Display::return_message(get_lang('Category added')));
353
354
        return $linkId;
355
    }
356
357
    public static function deleteCategory($id)
358
    {
359
        $repo = Container::getLinkCategoryRepository();
360
        /** @var CLinkCategory $category */
361
        $category = $repo->find($id);
362
        if ($category) {
0 ignored issues
show
introduced by
$category is of type Chamilo\CourseBundle\Entity\CLinkCategory, thus it always evaluated to true.
Loading history...
363
            $repo->delete($category);
364
            Display::addFlash(Display::return_message(get_lang('The category has been deleted.')));
365
366
            return true;
367
        }
368
369
        return false;
370
    }
371
372
    /**
373
     * Used to delete a link.
374
     *
375
     * @param int $id
376
     *
377
     * @return bool
378
     */
379
    public static function deleteLink($id)
380
    {
381
        $repo = Container::getLinkRepository();
382
        $link = $repo->find($id);
383
        if ($link) {
384
            $repo->delete($link);
385
            self::delete_link_from_search_engine(api_get_course_id(), $id);
386
            Skill::deleteSkillsFromItem($id, ITEM_TYPE_LINK);
387
            Display::addFlash(Display::return_message(get_lang('The link has been deleted')));
388
389
            return true;
390
        }
391
392
        return false;
393
394
        $courseInfo = api_get_course_info();
0 ignored issues
show
Unused Code introduced by
$courseInfo = api_get_course_info() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
395
        $tbl_link = Database::get_course_table(TABLE_LINK);
396
397
        $course_id = $courseInfo['real_id'];
398
        $id = intval($id);
399
400
        if (empty($id)) {
401
            return false;
402
        }
403
404
        // -> Items are no longer physically deleted,
405
        // but the visibility is set to 2 (in item_property).
406
        // This will make a restore function possible for the platform administrator.
407
        $sql = "UPDATE $tbl_link SET on_homepage='0'
408
                WHERE c_id = $course_id AND iid='".$id."'";
409
        Database:: query($sql);
410
411
        /*api_item_property_update(
412
            $courseInfo,
413
            TOOL_LINK,
414
            $id,
415
            'delete',
416
            api_get_user_id()
417
        );*/
418
419
        return true;
420
    }
421
422
    /**
423
     * Removes a link from search engine database.
424
     *
425
     * @param string $course_id Course code
426
     * @param int    $link_id   Document id to delete
427
     */
428
    public static function delete_link_from_search_engine($course_id, $link_id)
429
    {
430
        // Remove from search engine if enabled.
431
        if ('true' === api_get_setting('search_enabled')) {
432
            $tbl_se_ref = Database::get_main_table(
433
                TABLE_MAIN_SEARCH_ENGINE_REF
434
            );
435
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
436
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
437
            $res = Database:: query($sql);
438
            if (Database:: num_rows($res) > 0) {
439
                $row = Database::fetch_array($res);
440
                $di = new ChamiloIndexer();
441
                $di->remove_document($row['search_did']);
442
            }
443
            $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
444
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
445
            Database:: query($sql);
446
447
            // Remove terms from db.
448
            delete_all_values_for_item($course_id, TOOL_DOCUMENT, $link_id);
449
        }
450
    }
451
452
    /**
453
     * Get link info.
454
     *
455
     * @param int $id
456
     *
457
     * @return array link info
458
     */
459
    public static function getLinkInfo($id)
460
    {
461
        $tbl_link = Database::get_course_table(TABLE_LINK);
462
        $course_id = api_get_course_int_id();
463
        $id = (int) $id;
464
465
        if (empty($id) || empty($course_id)) {
466
            return [];
467
        }
468
469
        $sql = "SELECT * FROM $tbl_link
470
                WHERE iid= $id ";
471
        $result = Database::query($sql);
472
        $data = [];
473
        if (Database::num_rows($result)) {
474
            $data = Database::fetch_array($result);
475
        }
476
477
        return $data;
478
    }
479
480
    /**
481
     * @param int   $id
482
     * @param array $values
483
     */
484
    public static function editLink($id, $values = [])
485
    {
486
        $tbl_link = Database::get_course_table(TABLE_LINK);
487
        $_course = api_get_course_info();
488
        $course_id = $_course['real_id'];
489
        $id = (int) $id;
490
491
        $values['url'] = trim($values['url']);
492
        $values['title'] = trim($values['title']);
493
        $values['description'] = trim($values['description']);
494
        $values['target'] = empty($values['target']) ? '_self' : $values['target'];
495
        $values['on_homepage'] = isset($values['on_homepage']) ? $values['on_homepage'] : '';
496
497
        $categoryId = (int) $values['category_id'];
498
499
        // We ensure URL to be absolute.
500
        if (false === strpos($values['url'], '://')) {
501
            $values['url'] = 'http://'.$_POST['url'];
502
        }
503
504
        // If the title is empty, we use the URL as title.
505
        if ('' == $values['title']) {
506
            $values['title'] = $values['url'];
507
        }
508
509
        // If the URL is invalid, an error occurs.
510
        if (!api_valid_url($values['url'], true)) {
511
            Display::addFlash(
512
                Display::return_message(get_lang('Please give the link URL, it should be valid.'), 'error')
513
            );
514
515
            return false;
516
        }
517
518
        if (empty($id) || empty($course_id)) {
519
            return false;
520
        }
521
522
        $repo = Container::getLinkRepository();
523
        /** @var CLink $link */
524
        $link = $repo->find($id);
525
526
        if (null === $link) {
527
            return false;
528
        }
529
530
        /*if ($link->getCategory() != $values['category_id']) {
531
            $sql = "SELECT MAX(display_order)
532
                    FROM $tbl_link
533
                    WHERE
534
                        category_id='".intval($values['category_id'])."'";
535
            $result = Database:: query($sql);
536
            [$max_display_order] = Database:: fetch_row($result);
537
            $max_display_order++;
538
        } else {
539
            $max_display_order = $row['display_order'];
540
        }*/
541
542
        $link
543
            ->setUrl($values['url'])
544
            ->setTitle($values['title'])
545
            ->setDescription($values['description'])
546
            ->setOnHomepage($values['on_homepage'])
547
            ->setTarget($values['target'])
548
        ;
549
550
        if (!empty($values['category_id'])) {
551
            $repoCategory = Container::getLinkCategoryRepository();
552
            /** @var CLinkCategory $category */
553
            $category = $repoCategory->find($categoryId);
554
            $link->setCategory($category);
555
        }
556
557
        $repo->update($link);
558
559
        // Update search enchine and its values table if enabled.
560
        if ('true' === api_get_setting('search_enabled')) {
561
            $course_int_id = api_get_course_int_id();
562
            $course_id = api_get_course_id();
563
            $link_title = Database:: escape_string($values['title']);
564
            $link_description = Database:: escape_string($values['description']);
565
566
            // Actually, it consists on delete terms from db,
567
            // insert new ones, create a new search engine document, and remove the old one.
568
            // Get search_did.
569
            $tbl_se_ref = Database::get_main_table(
570
                TABLE_MAIN_SEARCH_ENGINE_REF
571
            );
572
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
573
            $sql = sprintf(
574
                $sql,
575
                $tbl_se_ref,
576
                $course_id,
577
                TOOL_LINK,
578
                $id
579
            );
580
            $res = Database:: query($sql);
581
582
            if (Database:: num_rows($res) > 0) {
583
                $se_ref = Database:: fetch_array($res);
584
                $specific_fields = get_specific_field_list();
585
                $ic_slide = new IndexableChunk();
586
587
                $all_specific_terms = '';
588
                foreach ($specific_fields as $specific_field) {
589
                    delete_all_specific_field_value(
590
                        $course_id,
591
                        $specific_field['id'],
592
                        TOOL_LINK,
593
                        $id
594
                    );
595
                    if (isset($_REQUEST[$specific_field['code']])) {
596
                        $sterms = trim(
597
                            $_REQUEST[$specific_field['code']]
598
                        );
599
                        if (!empty($sterms)) {
600
                            $all_specific_terms .= ' '.$sterms;
601
                            $sterms = explode(',', $sterms);
602
                            foreach ($sterms as $sterm) {
603
                                $ic_slide->addTerm(
604
                                    trim($sterm),
605
                                    $specific_field['code']
606
                                );
607
                                add_specific_field_value(
608
                                    $specific_field['id'],
609
                                    $course_id,
610
                                    TOOL_LINK,
611
                                    $id,
612
                                    $sterm
613
                                );
614
                            }
615
                        }
616
                    }
617
                }
618
619
                // Build the chunk to index.
620
                $ic_slide->addValue("title", $link_title);
621
                $ic_slide->addCourseId($course_id);
622
                $ic_slide->addToolId(TOOL_LINK);
623
                $xapian_data = [
624
                    SE_COURSE_ID => $course_id,
625
                    SE_TOOL_ID => TOOL_LINK,
626
                    SE_DATA => [
627
                        'link_id' => $id,
628
                    ],
629
                    SE_USER => (int) api_get_user_id(),
630
                ];
631
                $ic_slide->xapian_data = serialize($xapian_data);
632
                $link_description = $all_specific_terms.' '.$link_description;
633
                $ic_slide->addValue('content', $link_description);
634
635
                // Add category name if set.
636
                if (isset($categoryId) && $categoryId > 0) {
637
                    $table_link_category = Database::get_course_table(
638
                        TABLE_LINK_CATEGORY
639
                    );
640
                    $sql_cat = 'SELECT * FROM %s WHERE id=%d and c_id = %d LIMIT 1';
641
                    $sql_cat = sprintf(
642
                        $sql_cat,
643
                        $table_link_category,
644
                        $categoryId,
645
                        $course_int_id
646
                    );
647
                    $result = Database:: query($sql_cat);
648
                    if (1 == Database:: num_rows($result)) {
649
                        $row = Database:: fetch_array($result);
650
                        $ic_slide->addValue(
651
                            'category',
652
                            $row['category_title']
653
                        );
654
                    }
655
                }
656
657
                $di = new ChamiloIndexer();
658
                isset($_POST['language']) ? $lang = Database:: escape_string($_POST['language']) : $lang = 'english';
659
                $di->connectDb(null, null, $lang);
660
                $di->remove_document($se_ref['search_did']);
661
                $di->addChunk($ic_slide);
662
663
                // Index and return search engine document id.
664
                $did = $di->index();
665
                if ($did) {
666
                    // Save it to db.
667
                    $sql = 'DELETE FROM %s
668
                            WHERE course_code=\'%s\'
669
                            AND tool_id=\'%s\'
670
                            AND ref_id_high_level=\'%s\'';
671
                    $sql = sprintf(
672
                        $sql,
673
                        $tbl_se_ref,
674
                        $course_id,
675
                        TOOL_LINK,
676
                        $id
677
                    );
678
                    Database:: query($sql);
679
                    $sql = 'INSERT INTO %s (c_id, id, course_code, tool_id, ref_id_high_level, search_did)
680
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
681
                    $sql = sprintf(
682
                        $sql,
683
                        $tbl_se_ref,
684
                        $course_int_id,
685
                        $course_id,
686
                        TOOL_LINK,
687
                        $id,
688
                        $did
689
                    );
690
                    Database:: query($sql);
691
                }
692
            }
693
        }
694
695
        Display::addFlash(Display::return_message(get_lang('The link has been modified.')));
696
    }
697
698
    /**
699
     * @param int   $id
700
     * @param array $values
701
     *
702
     * @return bool
703
     */
704
    public static function editCategory($id, $values)
705
    {
706
        $repo = Container::getLinkCategoryRepository();
707
        /** @var CLinkCategory $category */
708
        $category = $repo->find($id);
709
        $category
710
            ->setCategoryTitle($values['category_title'])
711
            ->setDescription($values['description'])
712
        ;
713
714
        $repo->update($category);
715
716
        Display::addFlash(Display::return_message(get_lang('The category has been modified.')));
717
718
        return true;
719
    }
720
721
    /**
722
     * Changes the visibility of a link.
723
     */
724
    public static function setVisible($id, $scope)
725
    {
726
        if (TOOL_LINK == $scope) {
727
            /*api_item_property_update(
728
                $_course,
729
                TOOL_LINK,
730
                $id,
731
                $_GET['action'],
732
                $_user['user_id']
733
            );*/
734
            $repo = Container::getLinkRepository();
735
            /** @var CLink $link */
736
            $link = $repo->find($id);
737
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
738
                $repo->setVisibilityPublished($link);
739
            }
740
        } elseif (TOOL_LINK_CATEGORY == $scope) {
741
            $repo = Container::getLinkCategoryRepository();
742
            /** @var CLink $link */
743
            $link = $repo->find($id);
744
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
745
                $repo->setVisibilityPublished($link);
746
            }
747
            /*api_item_property_update(
748
                $_course,
749
                TOOL_LINK_CATEGORY,
750
                $id,
751
                $_GET['action'],
752
                $_user['user_id']
753
            );*/
754
        }
755
        Display::addFlash(Display::return_message(get_lang('The visibility has been changed.')));
756
    }
757
758
    public static function setInvisible($id, $scope)
759
    {
760
        if (TOOL_LINK == $scope) {
761
            $repo = Container::getLinkRepository();
762
            /** @var CLink $link */
763
            $link = $repo->find($id);
764
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
765
                $repo->setVisibilityDraft($link);
766
            }
767
        } elseif (TOOL_LINK_CATEGORY == $scope) {
768
            $repo = Container::getLinkCategoryRepository();
769
            /** @var CLinkCategory $link */
770
            $link = $repo->find($id);
771
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLinkCategory, thus it always evaluated to true.
Loading history...
772
                $repo->setVisibilityDraft($link);
773
            }
774
        }
775
        Display::addFlash(Display::return_message(get_lang('The visibility has been changed.')));
776
    }
777
778
    /**
779
     * Generate SQL to select all the links categories in the current course and
780
     * session.
781
     *
782
     * @param int  $courseId
783
     * @param int  $sessionId
784
     * @param bool $withBaseContent
785
     *
786
     * @return CLinkCategory[]
787
     */
788
    public static function getLinkCategories($courseId, $sessionId, $withBaseContent = true)
789
    {
790
        $repo = Container::getLinkCategoryRepository();
791
792
        $courseEntity = api_get_course_entity($courseId);
793
        $sessionEntity = api_get_session_entity($sessionId);
794
795
        $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity);
796
797
        return $qb->getQuery()->getResult();
798
        /*
799
        $tblLinkCategory = Database::get_course_table(TABLE_LINK_CATEGORY);
800
        $tblItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
801
        $courseId = (int) $courseId;
802
        $courseInfo = api_get_course_info_by_id($courseId);
803
804
        // Condition for the session.
805
        $sessionCondition = api_get_session_condition(
806
            $sessionId,
807
            true,
808
            $withBaseContent,
809
            'linkcat.session_id'
810
        );
811
812
        // Getting links
813
        $sql = "SELECT *, linkcat.id
814
                FROM $tblLinkCategory linkcat
815
                WHERE
816
                    linkcat.c_id = $courseId
817
                    $sessionCondition
818
                ORDER BY linkcat.display_order DESC";
819
820
        $result = Database::query($sql);
821
        $categories = Database::store_result($result);
822
823
        $sql = "SELECT *, linkcat.id
824
                FROM $tblLinkCategory linkcat
825
                INNER JOIN $tblItemProperty ip
826
                ON (linkcat.id = ip.ref AND linkcat.c_id = ip.c_id)
827
                WHERE
828
                    ip.tool = '".TOOL_LINK_CATEGORY."' AND
829
                    (ip.visibility = '0' OR ip.visibility = '1')
830
                    $sessionCondition AND
831
                    linkcat.c_id = ".$courseId."
832
                ORDER BY linkcat.display_order DESC";
833
834
        $result = Database::query($sql);
835
836
        $categoryInItemProperty = [];
837
        if (Database::num_rows($result)) {
838
            while ($row = Database::fetch_array($result, 'ASSOC')) {
839
                $categoryInItemProperty[$row['id']] = $row;
840
            }
841
        }
842
843
        foreach ($categories as &$category) {
844
            if (!isset($categoryInItemProperty[$category['id']])) {
845
                api_item_property_update(
846
                    $courseInfo,
847
                    TOOL_LINK_CATEGORY,
848
                    $category['id'],
849
                    'LinkCategoryAdded',
850
                    api_get_user_id()
851
                );
852
            }
853
        }
854
855
        $sql = "SELECT DISTINCT linkcat.*, visibility
856
                FROM $tblLinkCategory linkcat
857
                INNER JOIN $tblItemProperty ip
858
                ON (linkcat.id = ip.ref AND linkcat.c_id = ip.c_id)
859
                WHERE
860
                    ip.tool = '".TOOL_LINK_CATEGORY."' AND
861
                    (ip.visibility = '0' OR ip.visibility = '1')
862
                    $sessionCondition AND
863
                    linkcat.c_id = ".$courseId."
864
                ORDER BY linkcat.display_order DESC
865
                ";
866
        $result = Database::query($sql);
867
868
        return Database::store_result($result, 'ASSOC');*/
869
    }
870
871
    /**
872
     * @param int $categoryId
873
     * @param $courseId
874
     * @param $sessionId
875
     * @param bool $withBaseContent
876
     *
877
     * @return CLink[]|null
878
     */
879
    public static function getLinksPerCategory(
880
        $categoryId,
881
        $courseId,
882
        $sessionId,
883
        $withBaseContent = true
884
    ) {
885
        $courseEntity = api_get_course_entity($courseId);
886
        $sessionEntity = api_get_session_entity($sessionId);
887
888
        if (empty($categoryId)) {
889
            $repo = Container::getLinkRepository();
890
            $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity, null, $courseEntity->getResourceNode());
891
892
            return $qb->getQuery()->getResult();
893
        }
894
895
        $repo = Container::getLinkCategoryRepository();
896
        /** @var CLinkCategory $category */
897
        $category = $repo->find($categoryId);
898
        if ($category) {
0 ignored issues
show
introduced by
$category is of type Chamilo\CourseBundle\Entity\CLinkCategory, thus it always evaluated to true.
Loading history...
899
            $repo = Container::getLinkRepository();
900
            $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity, null, $category->getResourceNode());
901
902
            return $qb->getQuery()->getResult();
903
        }
904
905
        return null;
906
907
        $tbl_link = Database::get_course_table(TABLE_LINK);
0 ignored issues
show
Unused Code introduced by
$tbl_link = Database::get_course_table(TABLE_LINK) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
908
        $TABLE_ITEM_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
909
        $courseId = (int) $courseId;
910
        $sessionId = (int) $sessionId;
911
        $categoryId = (int) $categoryId;
912
913
        // Condition for the session.
914
        $condition_session = api_get_session_condition(
915
            $sessionId,
916
            true,
917
            false,
918
            'ip.session_id'
919
        );
920
921
        if (!empty($sessionId)) {
922
            $conditionBaseSession = api_get_session_condition(
923
                0,
924
                true,
925
                $withBaseContent,
926
                'ip.session_id'
927
            );
928
            $condition = " AND
929
                (
930
                    (ip.visibility = '1' $conditionBaseSession) OR
931
932
                    (
933
                        (ip.visibility = '0' OR ip.visibility = '1')
934
                        $condition_session
935
                    )
936
                )
937
            ";
938
        } else {
939
            $condition = api_get_session_condition(
940
                0,
941
                true,
942
                false,
943
                'ip.session_id'
944
            );
945
            $condition .= " AND (ip.visibility = '0' OR ip.visibility = '1') $condition ";
946
        }
947
948
        $sql = "SELECT
949
                    link.id,
950
                    ip.session_id,
951
                    link.session_id link_session_id,
952
                    url,
953
                    category_id,
954
                    visibility,
955
                    description,
956
                    title,
957
                    target,
958
                    on_homepage
959
                FROM $tbl_link link
960
                INNER JOIN $TABLE_ITEM_PROPERTY ip
961
                ON (link.id = ip.ref AND link.c_id = ip.c_id)
962
                WHERE
963
                    ip.tool = '".TOOL_LINK."' AND
964
                    link.category_id = '".$categoryId."' AND
965
                    link.c_id = $courseId AND
966
                    ip.c_id = $courseId
967
                    $condition
968
                ORDER BY link.display_order ASC, ip.session_id DESC";
969
970
        $result = Database:: query($sql);
971
972
        return Database::store_result($result);
973
    }
974
975
    /**
976
     * Displays all the links of a given category.
977
     *
978
     * @param int  $categoryId
979
     * @param int  $courseId
980
     * @param int  $sessionId
981
     * @param bool $showActionLinks
982
     *
983
     * @return string
984
     */
985
    public static function showLinksPerCategory($categoryId, $courseId, $sessionId, $showActionLinks = true)
986
    {
987
        global $token;
988
        $links = self::getLinksPerCategory($categoryId, $courseId, $sessionId);
989
        $content = '';
990
        $numberOfLinks = count($links);
991
        if (!empty($links)) {
992
            $courseEntity = api_get_course_entity($courseId);
993
            $sessionEntity = api_get_session_entity($sessionId);
994
            $_user = api_get_user_info();
995
996
            $content .= '<div class="link list-group">';
997
            $i = 1;
998
            $linksAdded = [];
999
            foreach ($links as $link) {
1000
                $linkId = $link->getIid();
1001
                $resourceLink = $link->getFirstResourceLink();
1002
1003
                if (in_array($linkId, $linksAdded)) {
1004
                    continue;
1005
                }
1006
1007
                $visibility = (int) $link->isVisible($courseEntity, $sessionEntity);
1008
1009
                $linksAdded[] = $linkId;
1010
                $categoryId = 0;
1011
                if ($link->getCategory()) {
1012
                    $categoryId = $link->getCategory()->getIid();
1013
                }
1014
1015
                // Validation when belongs to a session.
1016
                $session_img = '';
1017
                $session = $resourceLink->getSession();
1018
                if ($session) {
1019
                    $session_img = api_get_session_image(
1020
                        $session->getId(),
1021
                        $_user['status']
1022
                    );
1023
                }
1024
1025
                $toolbar = '';
1026
                $link_validator = '';
1027
                if (api_is_allowed_to_edit(null, true)) {
1028
                    $toolbar .= Display::toolbarButton(
1029
                        '',
1030
                        'javascript:void(0);',
1031
                        'check-circle',
1032
                        'secondary btn-sm',
1033
                        [
1034
                            'onclick' => "check_url('".$linkId."', '".addslashes($link->getUrl())."');",
1035
                            'title' => get_lang('Check link'),
1036
                        ]
1037
                    );
1038
1039
                    $link_validator .= Display::span(
1040
                        '',
1041
                        [
1042
                        'id' => 'url_id_'.$linkId,
1043
                        'class' => 'check-link',
1044
                        ]
1045
                    );
1046
1047
                    if ($session === $sessionEntity) {
1048
                        $url = api_get_self().'?'.api_get_cidreq().'&action=editlink&id='.$linkId;
1049
                        $title = get_lang('Edit');
1050
                        $toolbar .= Display::toolbarButton(
1051
                            '',
1052
                            $url,
1053
                            'pencil-alt',
1054
                            'secondary btn-sm',
1055
                            [
1056
                                'title' => $title,
1057
                            ]
1058
                        );
1059
                    }
1060
1061
                    $urlVisibility = api_get_self().'?'.api_get_cidreq().
1062
                            '&sec_token='.$token.
1063
                            '&id='.$linkId.
1064
                            '&scope=link&category_id='.$categoryId;
1065
1066
                    switch ($visibility) {
1067
                        case 1:
1068
                            $urlVisibility .= '&action=invisible';
1069
                            $title = get_lang('Make invisible');
1070
                            $toolbar .= Display::toolbarButton(
1071
                                '',
1072
                                $urlVisibility,
1073
                                'eye',
1074
                                'secondary btn-sm',
1075
                                [
1076
                                    'title' => $title,
1077
                                ]
1078
                            );
1079
                            break;
1080
                        case 0:
1081
                            $urlVisibility .= '&action=visible';
1082
                            $title = get_lang('Make Visible');
1083
                            $toolbar .= Display::toolbarButton(
1084
                                '',
1085
                                $urlVisibility,
1086
                                'eye-slash',
1087
                                'secondary btn-sm',
1088
                                [
1089
                                    'title' => $title,
1090
                                ]
1091
                            );
1092
                            break;
1093
                    }
1094
1095
                    if ($session === $sessionEntity) {
1096
                        $moveLinkParams = [
1097
                            'id' => $linkId,
1098
                            'scope' => 'category',
1099
                            'category_id' => $categoryId,
1100
                            'action' => 'move_link_up',
1101
                        ];
1102
1103
                        $toolbar .= Display::toolbarButton(
1104
                            get_lang('Move up'),
1105
                            api_get_self().'?'.api_get_cidreq().'&'.http_build_query($moveLinkParams),
1106
                            'level-up-alt',
1107
                            'secondary',
1108
                            ['class' => 'btn-sm '.(1 === $i ? 'disabled' : '')],
1109
                            false
1110
                        );
1111
1112
                        $moveLinkParams['action'] = 'move_link_down';
1113
                        $toolbar .= Display::toolbarButton(
1114
                            get_lang('Move down'),
1115
                            api_get_self().'?'.api_get_cidreq().'&'.http_build_query($moveLinkParams),
1116
                            'level-down-alt',
1117
                            'secondary',
1118
                            ['class' => 'btn-sm '.($i === $numberOfLinks ? 'disabled' : '')],
1119
                            false
1120
                        );
1121
1122
                        $url = api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=deletelink&id='.$linkId.'&category_id='.$categoryId;
1123
                        $event = "javascript: if(!confirm('".get_lang('Do you want to delete this link?')."'))return false;";
1124
                        $title = get_lang('Delete');
1125
1126
                        $toolbar .= Display::toolbarButton(
1127
                            '',
1128
                            $url,
1129
                            'trash',
1130
                            'secondary btn-sm',
1131
                            [
1132
                                'onclick' => $event,
1133
                                'title' => $title,
1134
                            ]
1135
                        );
1136
                    }
1137
                }
1138
1139
                $showLink = false;
1140
                $titleClass = '';
1141
                if ($visibility) {
1142
                    $showLink = true;
1143
                } else {
1144
                    if (api_is_allowed_to_edit(null, true)) {
1145
                        $showLink = true;
1146
                        $titleClass = 'text-muted';
1147
                    }
1148
                }
1149
1150
                if ($showLink) {
1151
                    $iconLink = Display::return_icon(
1152
                        'url.png',
1153
                        get_lang('Link'),
1154
                        null,
1155
                        ICON_SIZE_SMALL
1156
                    );
1157
                    $url = api_get_path(WEB_CODE_PATH).'link/link_goto.php?'.api_get_cidreq().'&link_id='.$linkId.'&link_url='.urlencode($link->getUrl());
1158
                    $content .= '<div class="list-group-item">';
1159
                    if ($showActionLinks) {
1160
                        $content .= '<div class="pull-right"><div class="btn-group">'.$toolbar.'</div></div>';
1161
                    }
1162
                    $content .= '<h4 class="list-group-item-heading">';
1163
                    $content .= $iconLink;
1164
                    $content .= Display::tag(
1165
                        'a',
1166
                        Security::remove_XSS($link->getTitle()),
1167
                        [
1168
                            'href' => $url,
1169
                            'target' => $link->getTarget(),
1170
                            'class' => $titleClass,
1171
                        ]
1172
                    );
1173
                    $content .= $link_validator;
1174
                    $content .= $session_img;
1175
                    $content .= '</h4>';
1176
                    $content .= '<p class="list-group-item-text">'.$link->getDescription().'</p>';
1177
                    $content .= '</div>';
1178
                }
1179
                $i++;
1180
            }
1181
            $content .= '</div>';
1182
        }
1183
1184
        return $content;
1185
    }
1186
1187
    /**
1188
     * Displays the edit, delete and move icons.
1189
     *
1190
     * @param int   Category ID
1191
     * @param int $currentCategory
1192
     * @param int $countCategories
1193
     *
1194
     * @return string
1195
     *
1196
     * @author Patrick Cool <[email protected]>, Ghent University
1197
     */
1198
    public static function showCategoryAdminTools(CLinkCategory $category, $currentCategory, $countCategories)
1199
    {
1200
        $categoryId = $category->getIid();
1201
        $token = null;
1202
        $tools = '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=editcategory&id='.$categoryId.'&category_id='.$categoryId.'" title='.get_lang('Edit').'">'.
1203
            Display:: return_icon(
1204
                'edit.png',
1205
                get_lang('Edit'),
1206
                [],
1207
                ICON_SIZE_SMALL
1208
            ).'</a>';
1209
1210
        // DISPLAY MOVE UP COMMAND only if it is not the top link.
1211
        if (0 != $currentCategory) {
1212
            $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=up&up='.$categoryId.'&category_id='.$categoryId.'" title="'.get_lang('Up').'">'.
1213
                Display:: return_icon(
1214
                    'up.png',
1215
                    get_lang('Up'),
1216
                    [],
1217
                    ICON_SIZE_SMALL
1218
                ).'</a>';
1219
        } else {
1220
            $tools .= Display:: return_icon(
1221
                'up_na.png',
1222
                get_lang('Up'),
1223
                [],
1224
                ICON_SIZE_SMALL
1225
            ).'</a>';
1226
        }
1227
1228
        // DISPLAY MOVE DOWN COMMAND only if it is not the bottom link.
1229
        if ($currentCategory < $countCategories - 1) {
1230
            $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=down&down='.$categoryId.'&category_id='.$categoryId.'">'.
1231
                Display:: return_icon(
1232
                    'down.png',
1233
                    get_lang('down'),
1234
                    [],
1235
                    ICON_SIZE_SMALL
1236
                ).'</a>';
1237
        } else {
1238
            $tools .= Display:: return_icon(
1239
                'down_na.png',
1240
                get_lang('down'),
1241
                [],
1242
                ICON_SIZE_SMALL
1243
            ).'</a>';
1244
        }
1245
1246
        $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=deletecategory&id='.$categoryId."&category_id=$categoryId\"
1247
            onclick=\"javascript: if(!confirm('".get_lang('When deleting a category, all links of this category are also deleted.
1248
Do you really want to delete this category and its links ?')."')) return false;\">".
1249
            Display:: return_icon(
1250
                'delete.png',
1251
                get_lang('Delete'),
1252
                [],
1253
                ICON_SIZE_SMALL
1254
            ).'</a>';
1255
1256
        return $tools;
1257
    }
1258
1259
    /**
1260
     * move a link or a linkcategory up or down.
1261
     *
1262
     * @param   int Category ID
1263
     * @param   int Course ID
1264
     * @param   int Session ID
1265
     *
1266
     * @author Patrick Cool <[email protected]>, Ghent University
1267
     *
1268
     * @todo support sessions
1269
     */
1270
    public static function movecatlink($action, $catlinkid, $courseId = null, $sessionId = null)
1271
    {
1272
        $tbl_categories = Database::get_course_table(TABLE_LINK_CATEGORY);
1273
1274
        if (is_null($courseId)) {
1275
            $courseId = api_get_course_int_id();
1276
        }
1277
        $courseId = intval($courseId);
1278
        if (is_null($sessionId)) {
1279
            $sessionId = api_get_session_id();
1280
        }
1281
        $sessionId = intval($sessionId);
1282
        $thiscatlinkId = intval($catlinkid);
1283
1284
        if ('down' == $action) {
1285
            $sortDirection = 'DESC';
1286
        }
1287
1288
        if ('up' == $action) {
1289
            $sortDirection = 'ASC';
1290
        }
1291
1292
        $movetable = $tbl_categories;
1293
1294
        if (!empty($sortDirection)) {
1295
            if (!in_array(trim(strtoupper($sortDirection)), ['ASC', 'DESC'])) {
1296
                $sortDirection = 'ASC';
1297
            }
1298
1299
            $sql = "SELECT id, display_order FROM $tbl_categories
1300
                    WHERE c_id = $courseId
1301
                    ORDER BY display_order $sortDirection";
1302
            $linkresult = Database:: query($sql);
1303
            $thislinkOrder = 1;
1304
            while ($sortrow = Database:: fetch_array($linkresult)) {
1305
                // STEP 2 : FOUND THE NEXT LINK ID AND ORDER, COMMIT SWAP
1306
                // This part seems unlogic, but it isn't . We first look for the current link with the querystring ID
1307
                // and we know the next iteration of the while loop is the next one. These should be swapped.
1308
                if (isset($thislinkFound) && $thislinkFound) {
1309
                    $nextlinkId = $sortrow['id'];
1310
                    $nextlinkOrder = $sortrow['display_order'];
1311
1312
                    Database:: query(
1313
                        "UPDATE ".$movetable."
1314
                        SET display_order = '$nextlinkOrder'
1315
                        WHERE c_id = $courseId  AND id =  '$thiscatlinkId'"
1316
                    );
1317
                    Database:: query(
1318
                        "UPDATE ".$movetable."
1319
                        SET display_order = '$thislinkOrder'
1320
                        WHERE c_id = $courseId  AND id =  '$nextlinkId'"
1321
                    );
1322
1323
                    break;
1324
                }
1325
                if ($sortrow['id'] == $thiscatlinkId) {
1326
                    $thislinkOrder = $sortrow['display_order'];
1327
                    $thislinkFound = true;
1328
                }
1329
            }
1330
        }
1331
1332
        Display::addFlash(Display::return_message(get_lang('LinksMoved')));
1333
    }
1334
1335
    /**
1336
     * This function checks if the url is a vimeo link.
1337
     *
1338
     * @author Julio Montoya
1339
     *
1340
     * @version 1.0
1341
     */
1342
    public static function isVimeoLink($url)
1343
    {
1344
        $isLink = strrpos($url, 'vimeo.com');
1345
1346
        return $isLink;
1347
    }
1348
1349
    /**
1350
     * Get vimeo id from URL.
1351
     *
1352
     * @param string $url
1353
     *
1354
     * @return bool|mixed
1355
     */
1356
    public static function getVimeoLinkId($url)
1357
    {
1358
        $possibleUrls = [
1359
            'http://www.vimeo.com/',
1360
            'http://vimeo.com/',
1361
            'https://www.vimeo.com/',
1362
            'https://vimeo.com/',
1363
        ];
1364
        $url = str_replace($possibleUrls, '', $url);
1365
1366
        if (is_numeric($url)) {
1367
            return $url;
1368
        }
1369
1370
        return false;
1371
    }
1372
1373
    /**
1374
     * This function checks if the url is a youtube link.
1375
     *
1376
     * @author Jorge Frisancho
1377
     * @author Julio Montoya - Fixing code
1378
     *
1379
     * @version 1.0
1380
     */
1381
    public static function is_youtube_link($url)
1382
    {
1383
        $is_youtube_link = strrpos($url, 'youtube') || strrpos(
1384
            $url,
1385
            'youtu.be'
1386
        );
1387
1388
        return $is_youtube_link;
1389
    }
1390
1391
    /**
1392
     * This function checks if the url is a PDF File link.
1393
     *
1394
     * @author Jorge Frisancho
1395
     * @author Alex Aragón - Fixing code
1396
     *
1397
     * @version 1.0
1398
     */
1399
    public static function isPdfLink($url)
1400
    {
1401
        $isPdfLink = strrpos(strtolower($url), '.pdf');
1402
1403
        return $isPdfLink;
1404
    }
1405
1406
    /**
1407
     * Get youtube id from an URL.
1408
     *
1409
     * @param string $url
1410
     *
1411
     * @return string
1412
     */
1413
    public static function get_youtube_video_id($url)
1414
    {
1415
        // This is the length of YouTube's video IDs
1416
        $len = 11;
1417
1418
        // The ID string starts after "v=", which is usually right after
1419
        // "youtube.com/watch?" in the URL
1420
        $pos = strpos($url, "v=");
1421
        $id = '';
1422
1423
        //If false try other options
1424
        if (false === $pos) {
1425
            $url_parsed = parse_url($url);
1426
1427
            //Youtube shortener
1428
            //http://youtu.be/ID
1429
            $pos = strpos($url, "youtu.be");
1430
1431
            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...
1432
                $id = '';
1433
            } else {
1434
                return substr($url_parsed['path'], 1);
1435
            }
1436
1437
            //if empty try the youtube.com/embed/ID
1438
            if (empty($id)) {
1439
                $pos = strpos($url, "embed");
1440
                if (false === $pos) {
1441
                    return '';
1442
                } else {
1443
                    return substr($url_parsed['path'], 7);
1444
                }
1445
            }
1446
        } else {
1447
            // Offset the start location to match the beginning of the ID string
1448
            $pos += 2;
1449
            // Get the ID string and return it
1450
            $id = substr($url, $pos, $len);
1451
1452
            return $id;
1453
        }
1454
    }
1455
1456
    /**
1457
     * @param int    $courseId
1458
     * @param int    $sessionId
1459
     * @param int    $categoryId
1460
     * @param string $show
1461
     * @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...
1462
     * @param bool   $showActionLinks
1463
     * @param bool   $forceOpenCategories
1464
     *
1465
     * @return string
1466
     */
1467
    public static function listLinksAndCategories(
1468
        $courseId,
1469
        $sessionId,
1470
        $categoryId,
1471
        $show = 'none',
1472
        $token = null,
1473
        $showActionLinks = true,
1474
        $forceOpenCategories = false
1475
    ) {
1476
        $categoryId = (int) $categoryId;
1477
        $content = '';
1478
        $categories = self::getLinkCategories($courseId, $sessionId);
1479
        $countCategories = count($categories);
1480
        $linksPerCategory = self::showLinksPerCategory(0, $courseId, $sessionId, $showActionLinks);
1481
1482
        if ($showActionLinks) {
1483
            /*	Action Links */
1484
            $content = '<div class="actions">';
1485
            if (api_is_allowed_to_edit(null, true)) {
1486
                $content .= '<a href="'.api_get_self().'?'.api_get_cidreq(
1487
                    ).'&action=addlink&category_id='.$categoryId.'">'.
1488
                    Display::return_icon('new_link.png', get_lang('Add a link'), '', ICON_SIZE_MEDIUM).'</a>';
1489
                $content .= '<a href="'.api_get_self().'?'.api_get_cidreq(
1490
                    ).'&action=addcategory&category_id='.$categoryId.'">'.
1491
                    Display::return_icon('new_folder.png', get_lang('Add a category'), '', ICON_SIZE_MEDIUM).'</a>';
1492
            }
1493
1494
            if (!empty($countCategories)) {
1495
                $content .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=list&show=none">';
1496
                $content .= Display::return_icon(
1497
                        'forum_listview.png',
1498
                        get_lang('List View'),
1499
                        '',
1500
                        ICON_SIZE_MEDIUM
1501
                    ).' </a>';
1502
1503
                $content .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=list&show=all">';
1504
                $content .= Display::return_icon(
1505
                        'forum_nestedview.png',
1506
                        get_lang('Nested View'),
1507
                        '',
1508
                        ICON_SIZE_MEDIUM
1509
                    ).'</a>';
1510
            }
1511
1512
            $content .= Display::url(
1513
                Display::return_icon('pdf.png', get_lang('Export to PDF'), '', ICON_SIZE_MEDIUM),
1514
                api_get_self().'?'.api_get_cidreq().'&action=export'
1515
            );
1516
            $content .= '</div>';
1517
        }
1518
1519
        if (empty($countCategories)) {
1520
            $content .= $linksPerCategory;
1521
        } else {
1522
            if (!empty($linksPerCategory)) {
1523
                $content .= Display::panel($linksPerCategory, get_lang('General'));
1524
            }
1525
        }
1526
1527
        $counter = 0;
1528
        $courseEntity = api_get_course_entity($courseId);
1529
        $sessionEntity = api_get_session_entity($sessionId);
1530
        $allowToEdit = api_is_allowed_to_edit(null, true);
1531
1532
        foreach ($categories as $category) {
1533
            $categoryItemId = $category->getIid();
1534
            $isVisible = $category->isVisible($courseEntity, $sessionEntity);
1535
            // Student don't see invisible categories.
1536
            if (!$allowToEdit) {
1537
                if (!$isVisible) {
1538
                    continue;
1539
                }
1540
            }
1541
1542
            // Validation when belongs to a session
1543
            $showChildren = $categoryId === $categoryItemId || 'all' === $show;
1544
            if ($forceOpenCategories) {
1545
                $showChildren = true;
1546
            }
1547
1548
            $strVisibility = '';
1549
            $visibilityClass = null;
1550
            if ($isVisible) {
1551
                $strVisibility = '<a
1552
                    href="link.php?'.api_get_cidreq().'&sec_token='.$token.'&action=invisible&id='.$categoryItemId.'&scope='.TOOL_LINK_CATEGORY.'"
1553
                    title="'.get_lang('Hide').'">'.
1554
                    Display::return_icon('visible.png', get_lang('Hide'), [], ICON_SIZE_SMALL).'</a>';
1555
            } elseif (!$isVisible) {
1556
                $visibilityClass = 'text-muted';
1557
                $strVisibility = ' <a
1558
                    href="link.php?'.api_get_cidreq().'&sec_token='.$token.'&action=visible&id='.$categoryItemId.'&scope='.TOOL_LINK_CATEGORY.'"
1559
                    title="'.get_lang('Show').'">'.
1560
                    Display::return_icon('invisible.png', get_lang('Show'), [], ICON_SIZE_SMALL).'</a>';
1561
            }
1562
1563
            $header = '';
1564
            if ($showChildren) {
1565
                $header .= '<a
1566
                    class="'.$visibilityClass.'" href="'.api_get_self().'?'.api_get_cidreq().'&category_id=">';
1567
                $header .= Display::return_icon('forum_nestedview.png');
1568
            } else {
1569
                $header .= '<a
1570
                    class="'.$visibilityClass.'" href="'.api_get_self().'?'.api_get_cidreq().'&category_id='.$categoryItemId.'">';
1571
                $header .= Display::return_icon('forum_listview.png');
1572
            }
1573
            $header .= Security::remove_XSS($category->getCategoryTitle()).'</a>';
1574
1575
            if ($showActionLinks) {
1576
                if ($allowToEdit) {
1577
                    if ($category->getFirstResourceLink() &&
1578
                        $sessionEntity === $category->getFirstResourceLink()->getSession()
1579
                    ) {
1580
                        $header .= $strVisibility;
1581
                        $header .= self::showCategoryAdminTools($category, $counter, count($categories));
1582
                    } else {
1583
                        $header .= get_lang('Edition not available from the session, please edit from the basic course.');
1584
                    }
1585
                }
1586
            }
1587
1588
            $childrenContent = '';
1589
            if ($showChildren) {
1590
                $childrenContent = self::showLinksPerCategory(
1591
                    $categoryItemId,
1592
                    api_get_course_int_id(),
1593
                    api_get_session_id()
1594
                );
1595
            }
1596
1597
            $content .= Display::panel($category->getDescription().$childrenContent, $header);
1598
            $counter++;
1599
        }
1600
1601
        return $content;
1602
    }
1603
1604
    /**
1605
     * @param int    $linkId
1606
     * @param string $action
1607
     * @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...
1608
     *
1609
     * @return FormValidator
1610
     */
1611
    public static function getLinkForm($linkId, $action, $token = null)
1612
    {
1613
        $courseId = api_get_course_int_id();
1614
        $sessionId = api_get_session_id();
1615
        $linkInfo = self::getLinkInfo($linkId);
1616
        $categoryId = isset($linkInfo['category_id']) ? $linkInfo['category_id'] : '';
1617
        $lpId = isset($_GET['lp_id']) ? Security::remove_XSS($_GET['lp_id']) : null;
1618
1619
        $form = new FormValidator(
1620
            'link',
1621
            'post',
1622
            api_get_self().'?action='.$action.
1623
            '&category_id='.$categoryId.
1624
            '&'.api_get_cidreq().
1625
            '&id='.$linkId.
1626
            '&sec_token='.$token
1627
        );
1628
1629
        if ('addlink' === $action) {
1630
            $form->addHeader(get_lang('Add a link'));
1631
        } else {
1632
            $form->addHeader(get_lang('Edit link'));
1633
        }
1634
1635
        $target_link = '_blank';
1636
        $title = '';
1637
        $category = '';
1638
        $onhomepage = '';
1639
        $description = '';
1640
1641
        if (!empty($linkInfo)) {
1642
            $urllink = $linkInfo['url'];
1643
            $title = $linkInfo['title'];
1644
            $description = $linkInfo['description'];
1645
            $category = $linkInfo['category_id'];
1646
            if (0 != $linkInfo['on_homepage']) {
1647
                $onhomepage = 1;
1648
            }
1649
            $target_link = $linkInfo['target'];
1650
        }
1651
1652
        $form->addHidden('id', $linkId);
1653
        $form->addText('url', 'URL');
1654
        $form->addRule('url', get_lang('Please give the link URL, it should be valid.'), 'url');
1655
        $form->addText('title', get_lang('Link name'));
1656
        $form->addHtmlEditor(
1657
            'description',
1658
            get_lang('Description'),
1659
            false,
1660
            false,
1661
            ['ToolbarSet' => 'Profile', 'Width' => '100%', 'Height' => '130']
1662
        );
1663
1664
        $resultcategories = self::getLinkCategories($courseId, $sessionId);
1665
        $options = ['0' => '--'];
1666
        if (!empty($resultcategories)) {
1667
            foreach ($resultcategories as $myrow) {
1668
                $options[$myrow->getIid()] = $myrow->getCategoryTitle();
1669
            }
1670
        }
1671
1672
        $form->addSelect('category_id', get_lang('Category'), $options);
1673
        $form->addCheckBox('on_homepage', null, get_lang('Show link on course homepage'));
1674
1675
        $targets = [
1676
            '_self' => get_lang('Open self'),
1677
            '_blank' => get_lang('Open blank'),
1678
            '_parent' => get_lang('Open parent'),
1679
            '_top' => get_lang('Open top'),
1680
        ];
1681
1682
        $form->addSelect(
1683
            'target',
1684
            [
1685
                get_lang('Link\'s target'),
1686
                get_lang('Select the target which shows the link on the homepage of the course'),
1687
            ],
1688
            $targets
1689
        );
1690
1691
        $defaults = [
1692
            'url' => empty($urllink) ? 'http://' : Security::remove_XSS($urllink),
1693
            'title' => Security::remove_XSS($title),
1694
            'category_id' => $category,
1695
            'on_homepage' => $onhomepage,
1696
            'description' => $description,
1697
            'target' => $target_link,
1698
        ];
1699
1700
        if ('true' === api_get_setting('search_enabled')) {
1701
            $specific_fields = get_specific_field_list();
1702
            $form->addCheckBox('index_document', get_lang('Index link title and description?s'), get_lang('Yes'));
1703
1704
            foreach ($specific_fields as $specific_field) {
1705
                $default_values = '';
1706
                if ('editlink' === $action) {
1707
                    $filter = [
1708
                        'field_id' => $specific_field['id'],
1709
                        'ref_id' => intval($_GET['id']),
1710
                        'tool_id' => '\''.TOOL_LINK.'\'',
1711
                    ];
1712
                    $values = get_specific_field_values_list($filter, ['value']);
1713
                    if (!empty($values)) {
1714
                        $arr_str_values = [];
1715
                        foreach ($values as $value) {
1716
                            $arr_str_values[] = $value['value'];
1717
                        }
1718
                        $default_values = implode(', ', $arr_str_values);
1719
                    }
1720
                }
1721
                $form->addText($specific_field['name'], $specific_field['code']);
1722
                $defaults[$specific_field['name']] = $default_values;
1723
            }
1724
        }
1725
1726
        $skillList = Skill::addSkillsToForm($form, ITEM_TYPE_LINK, $linkId);
1727
        $form->addHidden('lp_id', $lpId);
1728
        $form->addButtonSave(get_lang('Save links'), 'submitLink');
1729
        $defaults['skills'] = array_keys($skillList);
1730
        $form->setDefaults($defaults);
1731
1732
        return $form;
1733
    }
1734
1735
    /**
1736
     * @param int    $id
1737
     * @param string $action
1738
     *
1739
     * @return FormValidator
1740
     */
1741
    public static function getCategoryForm($id, $action)
1742
    {
1743
        $id = (int) $id;
1744
        $action = Security::remove_XSS($action);
1745
1746
        $form = new FormValidator(
1747
            'category',
1748
            'post',
1749
            api_get_self().'?action='.$action.'&'.api_get_cidreq()
1750
        );
1751
1752
        $defaults = [];
1753
        if ('addcategory' === $action) {
1754
            $form->addHeader(get_lang('Add a category'));
1755
            $my_cat_title = get_lang('Add a category');
1756
        } else {
1757
            $form->addHeader(get_lang('Edit Category'));
1758
            $my_cat_title = get_lang('Edit Category');
1759
            $defaults = self::getCategory($id);
1760
        }
1761
        $form->addHidden('id', $id);
1762
        $form->addText('category_title', get_lang('Category name'));
1763
        $form->addHtmlEditor(
1764
            'description',
1765
            get_lang('Description'),
1766
            false,
1767
            false,
1768
            ['ToolbarSet' => 'Profile', 'Width' => '100%', 'Height' => '130']
1769
        );
1770
        $form->addButtonSave($my_cat_title, 'submitCategory');
1771
        $form->setDefaults($defaults);
1772
1773
        return $form;
1774
    }
1775
1776
    /**
1777
     * @param int $id
1778
     *
1779
     * @return array
1780
     */
1781
    public static function getCategory($id)
1782
    {
1783
        $table = Database::get_course_table(TABLE_LINK_CATEGORY);
1784
        $id = (int) $id;
1785
        $courseId = api_get_course_int_id();
1786
1787
        if (empty($id) || empty($courseId)) {
1788
            return [];
1789
        }
1790
        $sql = "SELECT * FROM $table
1791
                WHERE iid = $id";
1792
        $result = Database::query($sql);
1793
1794
        return Database::fetch_array($result, 'ASSOC');
1795
    }
1796
1797
    /**
1798
     * Move a link up in its category.
1799
     *
1800
     * @param int $id
1801
     *
1802
     * @return bool
1803
     */
1804
    public static function moveLinkUp($id)
1805
    {
1806
        return self::moveLinkDisplayOrder($id, 'ASC');
1807
    }
1808
1809
    /**
1810
     * Move a link down in its category.
1811
     *
1812
     * @param int $id
1813
     *
1814
     * @return bool
1815
     */
1816
    public static function moveLinkDown($id)
1817
    {
1818
        return self::moveLinkDisplayOrder($id, 'DESC');
1819
    }
1820
1821
    /**
1822
     * @param string $url
1823
     *
1824
     * @return bool
1825
     */
1826
    public static function checkUrl($url)
1827
    {
1828
        // Check if curl is available.
1829
        if (!in_array('curl', get_loaded_extensions())) {
1830
            return false;
1831
        }
1832
1833
        // set URL and other appropriate options
1834
        $defaults = [
1835
            CURLOPT_URL => $url,
1836
            CURLOPT_FOLLOWLOCATION => true, // follow redirects accept youtube.com
1837
            CURLOPT_HEADER => 0,
1838
            CURLOPT_RETURNTRANSFER => true,
1839
            CURLOPT_TIMEOUT => 4,
1840
        ];
1841
1842
        $proxySettings = api_get_configuration_value('proxy_settings');
1843
1844
        if (!empty($proxySettings) &&
1845
            isset($proxySettings['curl_setopt_array'])
1846
        ) {
1847
            $defaults[CURLOPT_PROXY] = $proxySettings['curl_setopt_array']['CURLOPT_PROXY'];
1848
            $defaults[CURLOPT_PROXYPORT] = $proxySettings['curl_setopt_array']['CURLOPT_PROXYPORT'];
1849
        }
1850
1851
        // Create a new cURL resource
1852
        $ch = curl_init();
1853
        curl_setopt_array($ch, $defaults);
1854
1855
        // grab URL and pass it to the browser
1856
        ob_start();
1857
        $result = curl_exec($ch);
1858
        ob_get_clean();
1859
1860
        // close cURL resource, and free up system resources
1861
        curl_close($ch);
1862
1863
        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...
1864
    }
1865
1866
    /**
1867
     * Move a link inside its category (display_order field).
1868
     *
1869
     * @param int    $id        The link ID
1870
     * @param string $direction The direction to sort the links
1871
     *
1872
     * @return bool
1873
     */
1874
    private static function moveLinkDisplayOrder($id, $direction)
1875
    {
1876
        $em = Database::getManager();
1877
        $repo = Container::getLinkRepository();
1878
1879
        /** @var CLink $link */
1880
        $link = $repo->find($id);
1881
1882
        if (!$link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
1883
            return false;
1884
        }
1885
1886
        $compareLinks = $repo
1887
            ->findBy(
1888
                [
1889
                    'categoryId' => $link->getCategory() ? $link->getCategory()->getIid() : 0,
1890
                ],
1891
                ['displayOrder' => $direction]
1892
            );
1893
1894
        /** @var CLink $prevLink */
1895
        $prevLink = null;
1896
1897
        /** @var CLink $compareLink */
1898
        foreach ($compareLinks as $compareLink) {
1899
            if ($compareLink->getIid() !== $link->getIid()) {
1900
                $prevLink = $compareLink;
1901
1902
                continue;
1903
            }
1904
1905
            if (!$prevLink) {
1906
                return false;
1907
            }
1908
1909
            $newPrevLinkDisplayOrder = $link->getDisplayOrder();
1910
            $newLinkDisplayOrder = $prevLink->getDisplayOrder();
1911
1912
            $link->setDisplayOrder($newLinkDisplayOrder);
1913
            $prevLink->setDisplayOrder($newPrevLinkDisplayOrder);
1914
1915
            $em->persist($prevLink);
1916
            $em->persist($link);
1917
            break;
1918
        }
1919
1920
        $em->flush();
1921
1922
        return true;
1923
    }
1924
}
1925