Passed
Push — master ( 748ce8...32285e )
by Julito
07:34
created

Link   F

Complexity

Total Complexity 176

Size/Duplication

Total Lines 1974
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 1073
dl 0
loc 1974
rs 1.308
c 0
b 0
f 0
wmc 176

33 Methods

Rating   Name   Duplication   Size   Complexity  
A updateLink() 0 27 4
A addCategory() 0 70 3
A __construct() 0 3 1
A setCourse() 0 3 1
A getCourse() 0 3 2
A save() 0 37 3
A getLinksPerCategory() 0 94 4
A deleteCategory() 0 34 2
A setInvisible() 0 18 5
F editLink() 0 220 20
D getLinkForm() 0 117 14
A showCategoryAdminTools() 0 59 3
A editCategory() 0 19 1
F addLink() 0 194 20
A moveLinkDown() 0 3 1
F listLinksAndCategories() 0 126 18
B getLinkCategories() 0 81 5
A getCategoryForm() 0 27 2
A moveLinkUp() 0 3 1
A deleteLink() 0 42 3
A getLinkInfo() 0 18 4
A is_youtube_link() 0 8 2
A get_youtube_video_id() 0 40 5
A getVimeoLinkId() 0 15 2
A isPdfLink() 0 5 1
D showLinksPerCategory() 0 195 16
B moveLinkDisplayOrder() 0 49 6
B movecatlink() 0 63 11
A setVisible() 0 32 5
A isVimeoLink() 0 5 1
A getCategory() 0 15 3
A delete_link_from_search_engine() 0 22 3
A checkUrl() 0 38 4

How to fix   Complexity   

Complex Class

Complex classes like Link often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Link, and based on these observations, apply Extract Interface, too.

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

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

888
    public static function getLinkCategories($courseId, $sessionId, /** @scrutinizer ignore-unused */ $withBaseContent = true)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
889
    {
890
        $repo = Container::getLinkCategoryRepository();
891
892
        $courseEntity = api_get_course_entity($courseId);
893
        $sessionEntity = api_get_session_entity($sessionId);
894
895
        $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity);
896
897
        return $qb->getQuery()->getResult();
898
899
        $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...
900
        $tblItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
901
        $courseId = (int) $courseId;
902
        $courseInfo = api_get_course_info_by_id($courseId);
903
904
        // Condition for the session.
905
        $sessionCondition = api_get_session_condition(
906
            $sessionId,
907
            true,
908
            $withBaseContent,
909
            'linkcat.session_id'
910
        );
911
912
        // Getting links
913
        $sql = "SELECT *, linkcat.id
914
                FROM $tblLinkCategory linkcat
915
                WHERE
916
                    linkcat.c_id = $courseId
917
                    $sessionCondition
918
                ORDER BY linkcat.display_order DESC";
919
920
        $result = Database::query($sql);
921
        $categories = Database::store_result($result);
922
923
        $sql = "SELECT *, linkcat.id
924
                FROM $tblLinkCategory linkcat
925
                INNER JOIN $tblItemProperty ip
926
                ON (linkcat.id = ip.ref AND linkcat.c_id = ip.c_id)
927
                WHERE
928
                    ip.tool = '".TOOL_LINK_CATEGORY."' AND
929
                    (ip.visibility = '0' OR ip.visibility = '1')
930
                    $sessionCondition AND
931
                    linkcat.c_id = ".$courseId."
932
                ORDER BY linkcat.display_order DESC";
933
934
        $result = Database::query($sql);
935
936
        $categoryInItemProperty = [];
937
        if (Database::num_rows($result)) {
938
            while ($row = Database::fetch_array($result, 'ASSOC')) {
939
                $categoryInItemProperty[$row['id']] = $row;
940
            }
941
        }
942
943
        foreach ($categories as &$category) {
944
            if (!isset($categoryInItemProperty[$category['id']])) {
945
                api_item_property_update(
946
                    $courseInfo,
947
                    TOOL_LINK_CATEGORY,
948
                    $category['id'],
949
                    'LinkCategoryAdded',
950
                    api_get_user_id()
951
                );
952
            }
953
        }
954
955
        $sql = "SELECT DISTINCT linkcat.*, visibility
956
                FROM $tblLinkCategory linkcat
957
                INNER JOIN $tblItemProperty ip
958
                ON (linkcat.id = ip.ref AND linkcat.c_id = ip.c_id)
959
                WHERE
960
                    ip.tool = '".TOOL_LINK_CATEGORY."' AND
961
                    (ip.visibility = '0' OR ip.visibility = '1')
962
                    $sessionCondition AND
963
                    linkcat.c_id = ".$courseId."
964
                ORDER BY linkcat.display_order DESC
965
                ";
966
        $result = Database::query($sql);
967
968
        return Database::store_result($result, 'ASSOC');
969
    }
970
971
    /**
972
     * @param int $categoryId
973
     * @param $courseId
974
     * @param $sessionId
975
     * @param bool $withBaseContent
976
     *
977
     * @return CLink[]|null
978
     */
979
    public static function getLinksPerCategory(
980
        $categoryId,
981
        $courseId,
982
        $sessionId,
983
        $withBaseContent = true
0 ignored issues
show
Unused Code introduced by
The parameter $withBaseContent is not used and could be removed. ( Ignorable by Annotation )

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

983
        /** @scrutinizer ignore-unused */ $withBaseContent = true

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

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

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

1929
        curl_setopt_array(/** @scrutinizer ignore-type */ $ch, $defaults);
Loading history...
1930
1931
        // grab URL and pass it to the browser
1932
        ob_start();
1933
        $result = curl_exec($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_exec() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

1933
        $result = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
1934
        ob_get_clean();
1935
1936
        // close cURL resource, and free up system resources
1937
        curl_close($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_close() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

1937
        curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
1938
1939
        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...
1940
    }
1941
1942
    /**
1943
     * Move a link inside its category (display_order field).
1944
     *
1945
     * @param int    $id        The link ID
1946
     * @param string $direction The direction to sort the links
1947
     *
1948
     * @return bool
1949
     */
1950
    private static function moveLinkDisplayOrder($id, $direction)
1951
    {
1952
        $em = Database::getManager();
1953
        /** @var CLink $link */
1954
        $link = $em->find('ChamiloCourseBundle:CLink', $id);
1955
1956
        if (!$link) {
0 ignored issues
show
introduced by
$link is of type Chamilo\CourseBundle\Entity\CLink, thus it always evaluated to true.
Loading history...
1957
            return false;
1958
        }
1959
1960
        $compareLinks = $em
1961
            ->getRepository('ChamiloCourseBundle:CLink')
1962
            ->findBy(
1963
                [
1964
                    'cId' => $link->getCId(),
1965
                    'categoryId' => $link->getCategory() ? $link->getCategory()->getIid() : 0,
1966
                ],
1967
                ['displayOrder' => $direction]
1968
            );
1969
1970
        /** @var CLink $prevLink */
1971
        $prevLink = null;
1972
1973
        /** @var CLink $compareLink */
1974
        foreach ($compareLinks as $compareLink) {
1975
            if ($compareLink->getId() !== $link->getId()) {
1976
                $prevLink = $compareLink;
1977
1978
                continue;
1979
            }
1980
1981
            if (!$prevLink) {
1982
                return false;
1983
            }
1984
1985
            $newPrevLinkDisplayOrder = $link->getDisplayOrder();
1986
            $newLinkDisplayOrder = $prevLink->getDisplayOrder();
1987
1988
            $link->setDisplayOrder($newLinkDisplayOrder);
1989
            $prevLink->setDisplayOrder($newPrevLinkDisplayOrder);
1990
1991
            $em->merge($prevLink);
1992
            $em->merge($link);
1993
            break;
1994
        }
1995
1996
        $em->flush();
1997
1998
        return true;
1999
    }
2000
}
2001