Completed
Push — master ( 9dadb1...edd250 )
by Julito
12:09 queued 19s
created

Link::addCategory()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 59
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 24
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 59
rs 9.536

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\Entity\ResourceLink;
6
use Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\CourseBundle\Entity\CLink;
8
use Chamilo\CourseBundle\Entity\CLinkCategory;
9
10
/**
11
 * Function library for the links tool.
12
 *
13
 * This is a complete remake of the original link tool.
14
 * New features:
15
 * - Organize links into categories;
16
 * - favorites/bookmarks interface;
17
 * - move links up/down within a category;
18
 * - move categories up/down;
19
 * - expand/collapse all categories;
20
 * - add link to 'root' category => category-less link is always visible.
21
 *
22
 * @author Patrick Cool (December 2003 - January 2004)
23
 * @author René Haentjens, CSV file import (October 2004)
24
 */
25
class Link extends Model
26
{
27
    public $table;
28
    public $is_course_model = true;
29
    public $columns = [
30
        'id',
31
        'c_id',
32
        'url',
33
        'title',
34
        'description',
35
        'category_id',
36
        'display_order',
37
        'on_homepage',
38
        'target',
39
        'session_id',
40
    ];
41
    public $required = ['url', 'title'];
42
    private $course;
43
44
    /**
45
     * Link constructor.
46
     */
47
    public function __construct()
48
    {
49
        $this->table = Database::get_course_table(TABLE_LINK);
50
    }
51
52
    /**
53
     * @param array $course
54
     */
55
    public function setCourse($course)
56
    {
57
        $this->course = $course;
58
    }
59
60
    /**
61
     * @return array
62
     */
63
    public function getCourse()
64
    {
65
        return !empty($this->course) ? $this->course : api_get_course_info();
66
    }
67
68
    /**
69
     * Organize the saving of a link, using the parent's save method and
70
     * updating the item_property table.
71
     *
72
     * @param array $params
73
     * @param bool  $showQuery Whether to show the query in logs when
74
     *                          calling parent's save method
75
     *
76
     * @return bool True if link could be saved, false otherwise
77
     */
78
    public function save($params, $showQuery = null)
79
    {
80
        $course_info = $this->getCourse();
81
        $course_id = $course_info['real_id'];
82
        $session_id = api_get_session_id();
83
84
        $title = stripslashes($params['title']);
85
        $urllink = $params['url'];
86
        $description = $params['description'];
87
        $categoryId = (int) $params['category_id'];
88
89
        $onhomepage = 0;
90
        if (isset($params['on_homepage'])) {
91
            $onhomepage = Security::remove_XSS($params['on_homepage']);
92
        }
93
94
        $target = '_self'; // Default target.
95
        if (!empty($params['target'])) {
96
            $target = Security::remove_XSS($params['target']);
97
        }
98
99
        $urllink = trim($urllink);
100
        $title = trim($title);
101
        $description = trim($description);
102
103
        // We ensure URL to be absolute.
104
        if (false === strpos($urllink, '://')) {
105
            $urllink = 'http://'.$urllink;
106
        }
107
108
        // If the title is empty, we use the URL as title.
109
        if ('' == $title) {
110
            $title = $urllink;
111
        }
112
113
        // If the URL is invalid, an error occurs.
114
        if (!api_valid_url($urllink, true)) {
115
            // A check against an absolute URL
116
            Display::addFlash(Display::return_message(get_lang('Please give the link URL, it should be valid.'), 'error'));
117
118
            return false;
119
        } else {
120
            $category = null;
121
            $repoCategory = Container::getLinkCategoryRepository();
122
            if (!empty($categoryId)) {
123
                /** @var CLinkCategory $category */
124
                $category = $repoCategory->find($categoryId);
125
            }
126
127
            // Looking for the largest order number for this category.
128
            $link = new CLink();
129
            $link
130
                ->setUrl($urllink)
131
                ->setTitle($title)
132
                ->setDescription($description)
133
                ->setOnHomepage($onhomepage)
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->getEntityManager()->persist($link);
153
            $repo->getEntityManager()->flush();
154
            $link_id = $link->getIid();
155
156
            if (('true' === api_get_setting('search_enabled')) &&
157
                $link_id && extension_loaded('xapian')
158
            ) {
159
                require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
160
161
                $course_int_id = $_course['real_id'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $_course seems to be never defined.
Loading history...
162
                $courseCode = $_course['code'];
163
                $specific_fields = get_specific_field_list();
164
                $ic_slide = new IndexableChunk();
165
166
                // Add all terms to db.
167
                $all_specific_terms = '';
168
                foreach ($specific_fields as $specific_field) {
169
                    if (isset($_REQUEST[$specific_field['code']])) {
170
                        $sterms = trim($_REQUEST[$specific_field['code']]);
171
                        if (!empty($sterms)) {
172
                            $all_specific_terms .= ' '.$sterms;
173
                            $sterms = explode(',', $sterms);
174
                            foreach ($sterms as $sterm) {
175
                                $ic_slide->addTerm(
176
                                    trim($sterm),
177
                                    $specific_field['code']
178
                                );
179
                                add_specific_field_value(
180
                                    $specific_field['id'],
181
                                    $courseCode,
182
                                    TOOL_LINK,
183
                                    $link_id,
184
                                    $sterm
185
                                );
186
                            }
187
                        }
188
                    }
189
                }
190
191
                // Build the chunk to index.
192
                $ic_slide->addValue('title', $title);
193
                $ic_slide->addCourseId($courseCode);
194
                $ic_slide->addToolId(TOOL_LINK);
195
                $xapian_data = [
196
                    SE_COURSE_ID => $courseCode,
197
                    SE_TOOL_ID => TOOL_LINK,
198
                    SE_DATA => [
199
                        'link_id' => (int) $link_id,
200
                    ],
201
                    SE_USER => (int) api_get_user_id(),
202
                ];
203
                $ic_slide->xapian_data = serialize($xapian_data);
204
                $description = $all_specific_terms.' '.$description;
205
                $ic_slide->addValue('content', $description);
206
207
                // Add category name if set.
208
                if (isset($categoryId) && $categoryId > 0) {
209
                    $table_link_category = Database::get_course_table(
210
                        TABLE_LINK_CATEGORY
211
                    );
212
                    $sql_cat = 'SELECT * FROM %s WHERE id=%d AND c_id = %d LIMIT 1';
213
                    $sql_cat = sprintf(
214
                        $sql_cat,
215
                        $table_link_category,
216
                        (int) $categoryId,
217
                        $course_int_id
218
                    );
219
                    $result = Database:: query($sql_cat);
220
                    if (1 == Database:: num_rows($result)) {
221
                        $row = Database:: fetch_array($result);
222
                        $ic_slide->addValue(
223
                            'category',
224
                            $row['category_title']
225
                        );
226
                    }
227
                }
228
229
                $di = new ChamiloIndexer();
230
                isset($params['language']) ? $lang = Database:: escape_string(
231
                    $params['language']
232
                ) : $lang = 'english';
233
                $di->connectDb(null, null, $lang);
234
                $di->addChunk($ic_slide);
235
236
                // Index and return search engine document id.
237
                $did = $di->index();
238
                if ($did) {
239
                    // Save it to db.
240
                    $tbl_se_ref = Database::get_main_table(
241
                        TABLE_MAIN_SEARCH_ENGINE_REF
242
                    );
243
                    $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
244
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
245
                    $sql = sprintf(
246
                        $sql,
247
                        $tbl_se_ref,
248
                        $course_int_id,
249
                        $courseCode,
250
                        TOOL_LINK,
251
                        $link_id,
252
                        $did
253
                    );
254
                    Database:: query($sql);
255
                }
256
            }
257
            Display::addFlash(Display::return_message(get_lang('The link has been added.')));
258
259
            return $link_id;
260
        }
261
    }
262
263
    /**
264
     * Update a link in the database.
265
     *
266
     * @param int    $linkId    The ID of the link to update
267
     * @param string $linkUrl   The new URL to be saved
268
     * @param int    $courseId
269
     * @param int    $sessionId
270
     *
271
     * @return bool
272
     */
273
    public function updateLink(
274
        $linkId,
275
        $linkUrl,
276
        $courseId = null,
277
        $sessionId = null
278
    ) {
279
        $tblLink = Database::get_course_table(TABLE_LINK);
280
        $linkUrl = Database::escape_string($linkUrl);
281
        $linkId = intval($linkId);
282
        if (is_null($courseId)) {
283
            $courseId = api_get_course_int_id();
284
        }
285
        $courseId = intval($courseId);
286
        if (is_null($sessionId)) {
287
            $sessionId = api_get_session_id();
288
        }
289
        $sessionId = intval($sessionId);
290
        if ('' != $linkUrl) {
291
            $sql = "UPDATE $tblLink SET
292
                    url = '$linkUrl'
293
                    WHERE id = $linkId AND c_id = $courseId AND session_id = $sessionId";
294
            $resLink = Database::query($sql);
295
296
            return $resLink;
297
        }
298
299
        return false;
300
    }
301
302
    public static function addCategory()
303
    {
304
        $_course = api_get_course_info();
305
        $course_id = $_course['real_id'];
306
        $tbl_categories = Database::get_course_table(TABLE_LINK_CATEGORY);
307
308
        $category_title = trim($_POST['category_title']);
309
        $description = trim($_POST['description']);
310
311
        if (empty($category_title)) {
312
            echo Display::return_message(get_lang('Please give the category name'), 'error');
313
314
            return false;
315
        }
316
317
        // Looking for the largest order number for this category.
318
        /*$result = Database:: query(
319
            "SELECT MAX(display_order) FROM  $tbl_categories
320
            WHERE c_id = $course_id "
321
        );
322
        [$orderMax] = Database:: fetch_row($result);
323
        $order = $orderMax + 1;
324
        $order = (int) $order;*/
325
        $session_id = api_get_session_id();
326
327
        $repo = Container::getLinkCategoryRepository();
328
        $courseEntity = api_get_course_entity($course_id);
329
        $sessionEntity = api_get_session_entity($session_id);
330
331
        $category = new CLinkCategory();
332
        $category
333
            ->setCategoryTitle($category_title)
334
            ->setDescription($description)
335
         //   ->setDisplayOrder($order)
336
            ->setParent($courseEntity)
337
            ->addCourseLink($courseEntity, $sessionEntity)
338
        ;
339
340
        $repo->getEntityManager()->persist($category);
341
        $repo->getEntityManager()->flush();
342
        $linkId = $category->getIid();
343
344
        if ($linkId) {
345
            // add link_category visibility
346
            // course ID is taken from context in api_set_default_visibility
347
            //api_set_default_visibility($linkId, TOOL_LINK_CATEGORY);
348
            /*api_item_property_update(
349
                $_course,
350
                TOOL_LINK_CATEGORY,
351
                $linkId,
352
                'LinkCategoryAdded',
353
                api_get_user_id()
354
            );
355
            api_set_default_visibility($linkId, TOOL_LINK_CATEGORY);*/
356
        }
357
358
        Display::addFlash(Display::return_message(get_lang('Category added')));
359
360
        return $linkId;
361
    }
362
363
    public static function deleteCategory($id)
364
    {
365
        $repo = Container::getLinkCategoryRepository();
366
        /** @var CLinkCategory $category */
367
        $category = $repo->find($id);
368
        if ($category) {
0 ignored issues
show
introduced by
$category is of type Chamilo\CourseBundle\Entity\CLinkCategory, thus it always evaluated to true.
Loading history...
369
            $repo->delete($category);
370
            Display::addFlash(Display::return_message(get_lang('The category has been deleted.')));
371
372
            return true;
373
        }
374
375
        return false;
376
    }
377
378
    /**
379
     * Used to delete a link.
380
     *
381
     * @param int $id
382
     *
383
     * @return bool
384
     */
385
    public static function deleteLink($id)
386
    {
387
        $repo = Container::getLinkRepository();
388
        $link = $repo->find($id);
389
        if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CoreBundle\Entity\ResourceInterface, thus it always evaluated to true.
Loading history...
390
            $repo->getEntityManager()->remove($link);
391
            $repo->getEntityManager()->flush();
392
            self::delete_link_from_search_engine(api_get_course_id(), $id);
393
            Skill::deleteSkillsFromItem($id, ITEM_TYPE_LINK);
394
            Display::addFlash(Display::return_message(get_lang('The link has been deleted')));
395
396
            return true;
397
        }
398
399
        return false;
400
401
        $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...
402
        $tbl_link = Database::get_course_table(TABLE_LINK);
403
404
        $course_id = $courseInfo['real_id'];
405
        $id = intval($id);
406
407
        if (empty($id)) {
408
            return false;
409
        }
410
411
        // -> Items are no longer physically deleted,
412
        // but the visibility is set to 2 (in item_property).
413
        // This will make a restore function possible for the platform administrator.
414
        $sql = "UPDATE $tbl_link SET on_homepage='0'
415
                WHERE c_id = $course_id AND iid='".$id."'";
416
        Database:: query($sql);
417
418
        /*api_item_property_update(
419
            $courseInfo,
420
            TOOL_LINK,
421
            $id,
422
            'delete',
423
            api_get_user_id()
424
        );*/
425
426
        return true;
427
    }
428
429
    /**
430
     * Removes a link from search engine database.
431
     *
432
     * @param string $course_id Course code
433
     * @param int    $link_id   Document id to delete
434
     */
435
    public static function delete_link_from_search_engine($course_id, $link_id)
436
    {
437
        // Remove from search engine if enabled.
438
        if ('true' === api_get_setting('search_enabled')) {
439
            $tbl_se_ref = Database::get_main_table(
440
                TABLE_MAIN_SEARCH_ENGINE_REF
441
            );
442
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
443
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
444
            $res = Database:: query($sql);
445
            if (Database:: num_rows($res) > 0) {
446
                $row = Database::fetch_array($res);
447
                $di = new ChamiloIndexer();
448
                $di->remove_document($row['search_did']);
449
            }
450
            $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
451
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
452
            Database:: query($sql);
453
454
            // Remove terms from db.
455
            require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
456
            delete_all_values_for_item($course_id, TOOL_DOCUMENT, $link_id);
457
        }
458
    }
459
460
    /**
461
     * Get link info.
462
     *
463
     * @param int $id
464
     *
465
     * @return array link info
466
     */
467
    public static function getLinkInfo($id)
468
    {
469
        $tbl_link = Database::get_course_table(TABLE_LINK);
470
        $course_id = api_get_course_int_id();
471
        $id = (int) $id;
472
473
        if (empty($id) || empty($course_id)) {
474
            return [];
475
        }
476
477
        $sql = "SELECT * FROM $tbl_link
478
                WHERE iid= $id ";
479
        $result = Database::query($sql);
480
        $data = [];
481
        if (Database::num_rows($result)) {
482
            $data = Database::fetch_array($result);
483
        }
484
485
        return $data;
486
    }
487
488
    /**
489
     * @param int   $id
490
     * @param array $values
491
     */
492
    public static function editLink($id, $values = [])
493
    {
494
        $tbl_link = Database::get_course_table(TABLE_LINK);
495
        $_course = api_get_course_info();
496
        $course_id = $_course['real_id'];
497
        $id = intval($id);
498
499
        $values['url'] = trim($values['url']);
500
        $values['title'] = trim($values['title']);
501
        $values['description'] = trim($values['description']);
502
        $values['target'] = empty($values['target']) ? '_self' : $values['target'];
503
        $values['on_homepage'] = isset($values['on_homepage']) ? $values['on_homepage'] : '';
504
505
        $categoryId = intval($values['category_id']);
506
507
        // We ensure URL to be absolute.
508
        if (false === strpos($values['url'], '://')) {
509
            $values['url'] = 'http://'.$_POST['url'];
510
        }
511
512
        // If the title is empty, we use the URL as title.
513
        if ('' == $values['title']) {
514
            $values['title'] = $values['url'];
515
        }
516
517
        // If the URL is invalid, an error occurs.
518
        if (!api_valid_url($values['url'], true)) {
519
            Display::addFlash(
520
                Display::return_message(get_lang('Please give the link URL, it should be valid.'), 'error')
521
            );
522
523
            return false;
524
        }
525
526
        if (empty($id) || empty($course_id)) {
527
            return false;
528
        }
529
530
        // Finding the old category_id.
531
        $sql = "SELECT * FROM $tbl_link
532
                WHERE c_id = $course_id AND iid='".$id."'";
533
        $result = Database:: query($sql);
534
        $row = Database:: fetch_array($result);
535
        $category_id = $row['category_id'];
536
537
        if ($category_id != $values['category_id']) {
538
            $sql = "SELECT MAX(display_order)
539
                    FROM $tbl_link
540
                    WHERE
541
                        c_id = $course_id AND
542
                        category_id='".intval($values['category_id'])."'";
543
            $result = Database:: query($sql);
544
            [$max_display_order] = Database:: fetch_row($result);
545
            $max_display_order++;
546
        } else {
547
            $max_display_order = $row['display_order'];
548
        }
549
        $params = [
550
            'url' => $values['url'],
551
            'title' => $values['title'],
552
            'description' => $values['description'],
553
            'category_id' => $values['category_id'],
554
            'display_order' => $max_display_order,
555
            'on_homepage' => $values['on_homepage'],
556
            'target' => $values['target'],
557
        ];
558
559
        Database::update(
560
            $tbl_link,
561
            $params,
562
            ['iid = ?' => [$course_id, $id]]
563
        );
564
565
        // Update search enchine and its values table if enabled.
566
        if ('true' === api_get_setting('search_enabled')) {
567
            $course_int_id = api_get_course_int_id();
568
            $course_id = api_get_course_id();
569
            $link_title = Database:: escape_string($values['title']);
570
            $link_description = Database:: escape_string($values['description']);
571
572
            // Actually, it consists on delete terms from db,
573
            // insert new ones, create a new search engine document, and remove the old one.
574
            // Get search_did.
575
            $tbl_se_ref = Database::get_main_table(
576
                TABLE_MAIN_SEARCH_ENGINE_REF
577
            );
578
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
579
            $sql = sprintf(
580
                $sql,
581
                $tbl_se_ref,
582
                $course_id,
583
                TOOL_LINK,
584
                $id
585
            );
586
            $res = Database:: query($sql);
587
588
            if (Database:: num_rows($res) > 0) {
589
                require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
590
591
                $se_ref = Database:: fetch_array($res);
592
                $specific_fields = get_specific_field_list();
593
                $ic_slide = new IndexableChunk();
594
595
                $all_specific_terms = '';
596
                foreach ($specific_fields as $specific_field) {
597
                    delete_all_specific_field_value(
598
                        $course_id,
599
                        $specific_field['id'],
600
                        TOOL_LINK,
601
                        $id
602
                    );
603
                    if (isset($_REQUEST[$specific_field['code']])) {
604
                        $sterms = trim(
605
                            $_REQUEST[$specific_field['code']]
606
                        );
607
                        if (!empty($sterms)) {
608
                            $all_specific_terms .= ' '.$sterms;
609
                            $sterms = explode(',', $sterms);
610
                            foreach ($sterms as $sterm) {
611
                                $ic_slide->addTerm(
612
                                    trim($sterm),
613
                                    $specific_field['code']
614
                                );
615
                                add_specific_field_value(
616
                                    $specific_field['id'],
617
                                    $course_id,
618
                                    TOOL_LINK,
619
                                    $id,
620
                                    $sterm
621
                                );
622
                            }
623
                        }
624
                    }
625
                }
626
627
                // Build the chunk to index.
628
                $ic_slide->addValue("title", $link_title);
629
                $ic_slide->addCourseId($course_id);
630
                $ic_slide->addToolId(TOOL_LINK);
631
                $xapian_data = [
632
                    SE_COURSE_ID => $course_id,
633
                    SE_TOOL_ID => TOOL_LINK,
634
                    SE_DATA => [
635
                        'link_id' => (int) $id,
636
                    ],
637
                    SE_USER => (int) api_get_user_id(),
638
                ];
639
                $ic_slide->xapian_data = serialize($xapian_data);
640
                $link_description = $all_specific_terms.' '.$link_description;
641
                $ic_slide->addValue('content', $link_description);
642
643
                // Add category name if set.
644
                if (isset($categoryId) && $categoryId > 0) {
645
                    $table_link_category = Database::get_course_table(
646
                        TABLE_LINK_CATEGORY
647
                    );
648
                    $sql_cat = 'SELECT * FROM %s WHERE id=%d and c_id = %d LIMIT 1';
649
                    $sql_cat = sprintf(
650
                        $sql_cat,
651
                        $table_link_category,
652
                        $categoryId,
653
                        $course_int_id
654
                    );
655
                    $result = Database:: query($sql_cat);
656
                    if (1 == Database:: num_rows($result)) {
657
                        $row = Database:: fetch_array($result);
658
                        $ic_slide->addValue(
659
                            'category',
660
                            $row['category_title']
661
                        );
662
                    }
663
                }
664
665
                $di = new ChamiloIndexer();
666
                isset($_POST['language']) ? $lang = Database:: escape_string($_POST['language']) : $lang = 'english';
667
                $di->connectDb(null, null, $lang);
668
                $di->remove_document($se_ref['search_did']);
669
                $di->addChunk($ic_slide);
670
671
                // Index and return search engine document id.
672
                $did = $di->index();
673
                if ($did) {
674
                    // Save it to db.
675
                    $sql = 'DELETE FROM %s
676
                            WHERE course_code=\'%s\'
677
                            AND tool_id=\'%s\'
678
                            AND ref_id_high_level=\'%s\'';
679
                    $sql = sprintf(
680
                        $sql,
681
                        $tbl_se_ref,
682
                        $course_id,
683
                        TOOL_LINK,
684
                        $id
685
                    );
686
                    Database:: query($sql);
687
                    $sql = 'INSERT INTO %s (c_id, id, course_code, tool_id, ref_id_high_level, search_did)
688
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
689
                    $sql = sprintf(
690
                        $sql,
691
                        $tbl_se_ref,
692
                        $course_int_id,
693
                        $course_id,
694
                        TOOL_LINK,
695
                        $id,
696
                        $did
697
                    );
698
                    Database:: query($sql);
699
                }
700
            }
701
        }
702
703
        Display::addFlash(Display::return_message(get_lang('The link has been modified.')));
704
    }
705
706
    /**
707
     * @param int   $id
708
     * @param array $values
709
     *
710
     * @return bool
711
     */
712
    public static function editCategory($id, $values)
713
    {
714
        $table = Database::get_course_table(TABLE_LINK_CATEGORY);
715
        $course_id = api_get_course_int_id();
716
        $id = (int) $id;
717
718
        // This is used to put the modified info of the category-form into the database.
719
        $params = [
720
            'category_title' => $values['category_title'],
721
            'description' => $values['description'],
722
        ];
723
        Database::update(
724
            $table,
725
            $params,
726
            ['c_id = ? AND id = ?' => [$course_id, $id]]
727
        );
728
        Display::addFlash(Display::return_message(get_lang('The category has been modified.')));
729
730
        return true;
731
    }
732
733
    /**
734
     * Changes the visibility of a link.
735
     */
736
    public static function setVisible($id, $scope)
737
    {
738
        if (TOOL_LINK == $scope) {
739
            /*api_item_property_update(
740
                $_course,
741
                TOOL_LINK,
742
                $id,
743
                $_GET['action'],
744
                $_user['user_id']
745
            );*/
746
            $repo = Container::getLinkRepository();
747
            /** @var CLink $link */
748
            $link = $repo->find($id);
749
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
750
                $repo->setVisibilityPublished($link);
751
            }
752
        } elseif (TOOL_LINK_CATEGORY == $scope) {
753
            $repo = Container::getLinkCategoryRepository();
754
            /** @var CLink $link */
755
            $link = $repo->find($id);
756
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
757
                $repo->setVisibilityPublished($link);
758
            }
759
            /*api_item_property_update(
760
                $_course,
761
                TOOL_LINK_CATEGORY,
762
                $id,
763
                $_GET['action'],
764
                $_user['user_id']
765
            );*/
766
        }
767
        Display::addFlash(Display::return_message(get_lang('The visibility has been changed.')));
768
    }
769
770
    public static function setInvisible($id, $scope)
771
    {
772
        if (TOOL_LINK == $scope) {
773
            $repo = Container::getLinkRepository();
774
            /** @var CLink $link */
775
            $link = $repo->find($id);
776
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
777
                $repo->setVisibilityDraft($link);
778
            }
779
        } elseif (TOOL_LINK_CATEGORY == $scope) {
780
            $repo = Container::getLinkCategoryRepository();
781
            /** @var CLinkCategory $link */
782
            $link = $repo->find($id);
783
            if ($link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLinkCategory, thus it always evaluated to true.
Loading history...
784
                $repo->setVisibilityDraft($link);
785
            }
786
        }
787
        Display::addFlash(Display::return_message(get_lang('The visibility has been changed.')));
788
    }
789
790
    /**
791
     * Generate SQL to select all the links categories in the current course and
792
     * session.
793
     *
794
     * @param int  $courseId
795
     * @param int  $sessionId
796
     * @param bool $withBaseContent
797
     *
798
     * @return CLinkCategory[]
799
     */
800
    public static function getLinkCategories($courseId, $sessionId, $withBaseContent = true)
801
    {
802
        $repo = Container::getLinkCategoryRepository();
803
804
        $courseEntity = api_get_course_entity($courseId);
805
        $sessionEntity = api_get_session_entity($sessionId);
806
807
        $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity);
808
809
        return $qb->getQuery()->getResult();
810
811
        $tblLinkCategory = Database::get_course_table(TABLE_LINK_CATEGORY);
0 ignored issues
show
Unused Code introduced by
$tblLinkCategory = Datab...le(TABLE_LINK_CATEGORY) 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...
812
        $tblItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
813
        $courseId = (int) $courseId;
814
        $courseInfo = api_get_course_info_by_id($courseId);
815
816
        // Condition for the session.
817
        $sessionCondition = api_get_session_condition(
818
            $sessionId,
819
            true,
820
            $withBaseContent,
821
            'linkcat.session_id'
822
        );
823
824
        // Getting links
825
        $sql = "SELECT *, linkcat.id
826
                FROM $tblLinkCategory linkcat
827
                WHERE
828
                    linkcat.c_id = $courseId
829
                    $sessionCondition
830
                ORDER BY linkcat.display_order DESC";
831
832
        $result = Database::query($sql);
833
        $categories = Database::store_result($result);
834
835
        $sql = "SELECT *, linkcat.id
836
                FROM $tblLinkCategory linkcat
837
                INNER JOIN $tblItemProperty ip
838
                ON (linkcat.id = ip.ref AND linkcat.c_id = ip.c_id)
839
                WHERE
840
                    ip.tool = '".TOOL_LINK_CATEGORY."' AND
841
                    (ip.visibility = '0' OR ip.visibility = '1')
842
                    $sessionCondition AND
843
                    linkcat.c_id = ".$courseId."
844
                ORDER BY linkcat.display_order DESC";
845
846
        $result = Database::query($sql);
847
848
        $categoryInItemProperty = [];
849
        if (Database::num_rows($result)) {
850
            while ($row = Database::fetch_array($result, 'ASSOC')) {
851
                $categoryInItemProperty[$row['id']] = $row;
852
            }
853
        }
854
855
        foreach ($categories as &$category) {
856
            if (!isset($categoryInItemProperty[$category['id']])) {
857
                api_item_property_update(
0 ignored issues
show
Bug introduced by
The function api_item_property_update was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

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