Completed
Push — master ( 9b8b24...6e1754 )
by Julito
58:58
created

Link::checkUrl()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 38
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 20
nc 3
nop 1
dl 0
loc 38
rs 8.5806
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CLink;
5
6
/**
7
 * Function library for the links tool.
8
 *
9
 * This is a complete remake of the original link tool.
10
 * New features:
11
 * - Organize links into categories;
12
 * - favorites/bookmarks interface;
13
 * - move links up/down within a category;
14
 * - move categories up/down;
15
 * - expand/collapse all categories;
16
 * - add link to 'root' category => category-less link is always visible.
17
 *
18
 * @author Patrick Cool, complete remake (December 2003 - January 2004)
19
 * @author René Haentjens, CSV file import (October 2004)
20
 * @package chamilo.link
21
 */
22
class Link extends Model
23
{
24
    public $table;
25
    public $is_course_model = true;
26
    public $columns = array(
27
        'id',
28
        'c_id',
29
        'url',
30
        'title',
31
        'description',
32
        'category_id',
33
        'display_order',
34
        'on_homepage',
35
        'target',
36
        'session_id'
37
    );
38
    public $required = array('url', 'title');
39
    private $course;
40
41
    /**
42
     * Link constructor.
43
     */
44
    public function __construct()
45
    {
46
        $this->table = Database::get_course_table(TABLE_LINK);
47
    }
48
49
    /**
50
     * @param array $course
51
     */
52
    public function setCourse($course)
53
    {
54
        $this->course = $course;
55
    }
56
57
    /**
58
     * @return array
59
     */
60
    public function getCourse()
61
    {
62
        return !empty($this->course) ? $this->course : api_get_course_info();
63
    }
64
65
    /**
66
     * Organize the saving of a link, using the parent's save method and
67
     * updating the item_property table
68
     * @param array $params
69
     * @param boolean $show_query Whether to show the query in logs when
70
     * calling parent's save method
71
     *
72
     * @return bool True if link could be saved, false otherwise
73
     */
74
    public function save($params, $show_query = null)
75
    {
76
        $course_info = $this->getCourse();
77
        $courseId = $course_info['real_id'];
78
79
        $params['session_id'] = api_get_session_id();
80
        $params['category_id'] = isset($params['category_id']) ? $params['category_id'] : 0;
81
82
        $sql = "SELECT MAX(display_order)
83
                FROM  ".$this->table."
84
                WHERE
85
                    c_id = $courseId AND
86
                    category_id = '".intval($params['category_id'])."'";
87
        $result = Database:: query($sql);
88
        list ($orderMax) = Database:: fetch_row($result);
89
        $order = $orderMax + 1;
90
        $params['display_order'] = $order;
91
92
        $id = parent::save($params, $show_query);
93
94
        if (!empty($id)) {
95
            // iid
96
            $sql = "UPDATE ".$this->table." SET id = iid WHERE iid = $id";
97
            Database::query($sql);
98
99
            api_item_property_update(
100
                $course_info,
101
                TOOL_LINK,
102
                $id,
103
                'LinkAdded',
104
                api_get_user_id()
105
            );
106
107
            api_set_default_visibility($id, TOOL_LINK);
108
        }
109
110
        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...
111
    }
112
113
    /**
114
     * Update a link in the database
115
     * @param int $linkId The ID of the link to update
116
     * @param string $linkUrl The new URL to be saved
117
     * @param int   $courseId
118
     * @param int   $sessionId
119
     * @return bool
120
     */
121
    public function updateLink(
122
        $linkId,
123
        $linkUrl,
124
        $courseId = null,
125
        $sessionId = null
126
    ) {
127
        $tblLink = Database::get_course_table(TABLE_LINK);
128
        $linkUrl = Database::escape_string($linkUrl);
129
        $linkId = intval($linkId);
130
        if (is_null($courseId)) {
131
            $courseId = api_get_course_int_id();
132
        }
133
        $courseId = intval($courseId);
134
        if (is_null($sessionId)) {
135
            $sessionId = api_get_session_id();
136
        }
137
        $sessionId = intval($sessionId);
138
        if ($linkUrl != '') {
139
            $sql = "UPDATE $tblLink SET 
140
                    url = '$linkUrl'
141
                    WHERE id = $linkId AND c_id = $courseId AND session_id = $sessionId";
142
            $resLink = Database::query($sql);
143
144
            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...
145
        }
146
147
        return false;
148
    }
149
150
    /**
151
     * Used to add a link or a category
152
     * @param string $type , "link" or "category"
153
     * @todo replace strings by constants
154
     * @author Patrick Cool <[email protected]>, Ghent University
155
     * @return bool True on success, false on failure
156
     */
157
    public static function addlinkcategory($type)
158
    {
159
        $ok = true;
160
        $_course = api_get_course_info();
161
        $course_id = $_course['real_id'];
162
        $session_id = api_get_session_id();
163
164
        if ($type == 'link') {
165
            $title = Security::remove_XSS(stripslashes($_POST['title']));
166
            $urllink = Security::remove_XSS($_POST['url']);
167
            $description = Security::remove_XSS($_POST['description']);
168
            $selectcategory = Security::remove_XSS($_POST['category_id']);
169
170
            if (!isset($_POST['on_homepage'])) {
171
                $onhomepage = 0;
172
            } else {
173
                $onhomepage = Security::remove_XSS($_POST['on_homepage']);
174
            }
175
176
            if (empty($_POST['target'])) {
177
                $target = '_self'; // Default target.
178
            } else {
179
                $target = Security::remove_XSS($_POST['target']);
180
            }
181
182
            $urllink = trim($urllink);
183
            $title = trim($title);
184
            $description = trim($description);
185
186
            // We ensure URL to be absolute.
187
            if (strpos($urllink, '://') === false) {
188
                $urllink = 'http://'.$urllink;
189
            }
190
191
            // If the title is empty, we use the URL as title.
192
            if ($title == '') {
193
                $title = $urllink;
194
            }
195
196
            // If the URL is invalid, an error occurs.
197
            if (!api_valid_url($urllink, true)) {
198
                // A check against an absolute URL
199
                Display::addFlash(Display::return_message(get_lang('GiveURL'), 'error'));
200
201
                return false;
202
            } else {
203
                // Looking for the largest order number for this category.
204
205
                $link = new Link();
206
                $params = [
207
                    'c_id' => $course_id,
208
                    'url' => $urllink,
209
                    'title' => $title,
210
                    'description' => $description,
211
                    'category_id' => $selectcategory,
212
                    'on_homepage' => $onhomepage,
213
                    'target' => $target,
214
                    'session_id' => $session_id,
215
                ];
216
                $link_id = $link->save($params);
217
218
                if ((api_get_setting('search_enabled') == 'true') &&
219
                    $link_id && extension_loaded('xapian')
220
                ) {
221
                    require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
222
223
                    $course_int_id = $_course['real_id'];
224
                    $courseCode = $_course['code'];
225
                    $specific_fields = get_specific_field_list();
226
                    $ic_slide = new IndexableChunk();
227
228
                    // Add all terms to db.
229
                    $all_specific_terms = '';
230
                    foreach ($specific_fields as $specific_field) {
231
                        if (isset($_REQUEST[$specific_field['code']])) {
232
                            $sterms = trim($_REQUEST[$specific_field['code']]);
233
                            if (!empty($sterms)) {
234
                                $all_specific_terms .= ' '.$sterms;
235
                                $sterms = explode(',', $sterms);
236
                                foreach ($sterms as $sterm) {
237
                                    $ic_slide->addTerm(
238
                                        trim($sterm),
239
                                        $specific_field['code']
240
                                    );
241
                                    add_specific_field_value(
242
                                        $specific_field['id'],
243
                                        $courseCode,
244
                                        TOOL_LINK,
245
                                        $link_id,
246
                                        $sterm
247
                                    );
248
                                }
249
                            }
250
                        }
251
                    }
252
253
                    // Build the chunk to index.
254
                    $ic_slide->addValue('title', $title);
255
                    $ic_slide->addCourseId($courseCode);
256
                    $ic_slide->addToolId(TOOL_LINK);
257
                    $xapian_data = array(
258
                        SE_COURSE_ID => $courseCode,
259
                        SE_TOOL_ID => TOOL_LINK,
260
                        SE_DATA => array(
261
                            'link_id' => (int) $link_id
262
                        ),
263
                        SE_USER => (int) api_get_user_id(),
264
                    );
265
                    $ic_slide->xapian_data = serialize($xapian_data);
266
                    $description = $all_specific_terms.' '.$description;
267
                    $ic_slide->addValue('content', $description);
268
269
                    // Add category name if set.
270
                    if (isset($selectcategory) && $selectcategory > 0) {
271
                        $table_link_category = Database::get_course_table(
272
                            TABLE_LINK_CATEGORY
273
                        );
274
                        $sql_cat = 'SELECT * FROM %s WHERE id=%d AND c_id = %d LIMIT 1';
275
                        $sql_cat = sprintf(
276
                            $sql_cat,
277
                            $table_link_category,
278
                            (int) $selectcategory,
279
                            $course_int_id
280
                        );
281
                        $result = Database:: query($sql_cat);
282
                        if (Database:: num_rows($result) == 1) {
283
                            $row = Database:: fetch_array($result);
284
                            $ic_slide->addValue(
285
                                'category',
286
                                $row['category_title']
287
                            );
288
                        }
289
                    }
290
291
                    $di = new ChamiloIndexer();
292
                    isset($_POST['language']) ? $lang = Database:: escape_string(
293
                        $_POST['language']
294
                    ) : $lang = 'english';
295
                    $di->connectDb(null, null, $lang);
296
                    $di->addChunk($ic_slide);
297
298
                    // Index and return search engine document id.
299
                    $did = $di->index();
300
                    if ($did) {
301
                        // Save it to db.
302
                        $tbl_se_ref = Database::get_main_table(
303
                            TABLE_MAIN_SEARCH_ENGINE_REF
304
                        );
305
                        $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
306
                                VALUES (NULL , \'%s\', \'%s\', %s, %s)';
307
                        $sql = sprintf(
308
                            $sql,
309
                            $tbl_se_ref,
310
                            $course_int_id,
311
                            $courseCode,
312
                            TOOL_LINK,
313
                            $link_id,
314
                            $did
315
                        );
316
                        Database:: query($sql);
317
                    }
318
                }
319
                Display::addFlash(Display::return_message(get_lang('LinkAdded')));
320
            }
321
        } elseif ($type == 'category') {
322
            $tbl_categories = Database::get_course_table(TABLE_LINK_CATEGORY);
323
324
            $category_title = trim($_POST['category_title']);
325
            $description = trim($_POST['description']);
326
327
            if (empty($category_title)) {
328
                echo Display::return_message(get_lang('GiveCategoryName'), 'error');
329
                $ok = false;
330
            } else {
331
                // Looking for the largest order number for this category.
332
                $result = Database:: query(
333
                    "SELECT MAX(display_order) FROM  $tbl_categories
334
                    WHERE c_id = $course_id "
335
                );
336
                list ($orderMax) = Database:: fetch_row($result);
337
                $order = $orderMax + 1;
338
                $order = intval($order);
339
                $session_id = api_get_session_id();
340
341
                $params = [
342
                    'c_id' => $course_id,
343
                    'category_title' => $category_title,
344
                    'description' => $description,
345
                    'display_order' => $order,
346
                    'session_id' => $session_id
347
                ];
348
                $linkId = Database::insert($tbl_categories, $params);
349
350
                if ($linkId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $linkId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
351
                    // iid
352
                    $sql = "UPDATE $tbl_categories SET id = iid WHERE iid = $linkId";
353
                    Database:: query($sql);
354
355
                    // add link_category visibility
356
                    // course ID is taken from context in api_set_default_visibility
357
                    //api_set_default_visibility($linkId, TOOL_LINK_CATEGORY);
358
                    api_item_property_update(
359
                        $_course,
360
                        TOOL_LINK_CATEGORY,
361
                        $linkId,
362
                        'LinkCategoryAdded',
363
                        api_get_user_id()
364
                    );
365
                    api_set_default_visibility($linkId, TOOL_LINK_CATEGORY);
366
                }
367
368
                Display::addFlash(Display::return_message(get_lang('CategoryAdded')));
369
            }
370
        }
371
372
        return $ok;
373
    }
374
375
    /**
376
     * Used to delete a link or a category
377
     * @author Patrick Cool <[email protected]>, Ghent University
378
     * @param int $id
379
     * @param string $type The type of item to delete
380
     * @return bool
381
     */
382
    public static function deletelinkcategory($id, $type)
383
    {
384
        $courseInfo = api_get_course_info();
385
        $tbl_link = Database::get_course_table(TABLE_LINK);
386
        $tbl_categories = Database::get_course_table(TABLE_LINK_CATEGORY);
387
388
        $course_id = $courseInfo['real_id'];
389
        $id = intval($id);
390
391
        if (empty($id)) {
392
            return false;
393
        }
394
395
        $result = false;
396
397
        switch ($type) {
398
            case 'link':
399
                // -> Items are no longer physically deleted,
400
                // but the visibility is set to 2 (in item_property).
401
                // This will make a restore function possible for the platform administrator.
402
                $sql = "UPDATE $tbl_link SET on_homepage='0'
403
                        WHERE c_id = $course_id AND id='".$id."'";
404
                Database:: query($sql);
405
406
                api_item_property_update(
407
                    $courseInfo,
408
                    TOOL_LINK,
409
                    $id,
410
                    'delete',
411
                    api_get_user_id()
412
                );
413
                self::delete_link_from_search_engine(api_get_course_id(), $id);
414
                Display::addFlash(Display::return_message(get_lang('LinkDeleted')));
415
                $result = true;
416
                break;
417
            case 'category':
418
                // First we delete the category itself and afterwards all the links of this category.
419
                $sql = "DELETE FROM ".$tbl_categories."
420
                        WHERE c_id = $course_id AND id='".$id."'";
421
                Database:: query($sql);
422
423
                $sql = "DELETE FROM ".$tbl_link."
424
                        WHERE c_id = $course_id AND category_id='".$id."'";
425
                Database:: query($sql);
426
427
                api_item_property_update(
428
                    $courseInfo,
429
                    TOOL_LINK_CATEGORY,
430
                    $id,
431
                    'delete',
432
                    api_get_user_id()
433
                );
434
435
                Display::addFlash(Display::return_message(get_lang('CategoryDeleted')));
436
                $result = true;
437
                break;
438
        }
439
440
        return $result;
441
    }
442
443
    /**
444
     * Removes a link from search engine database
445
     * @param string $course_id Course code
446
     * @param int $link_id Document id to delete
447
     * @return void
448
     */
449
    public static function delete_link_from_search_engine($course_id, $link_id)
450
    {
451
        // Remove from search engine if enabled.
452
        if (api_get_setting('search_enabled') === 'true') {
453
            $tbl_se_ref = Database::get_main_table(
454
                TABLE_MAIN_SEARCH_ENGINE_REF
455
            );
456
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
457
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
458
            $res = Database:: query($sql);
459
            if (Database:: num_rows($res) > 0) {
460
                $row = Database::fetch_array($res);
461
                $di = new ChamiloIndexer();
462
                $di->remove_document($row['search_did']);
463
            }
464
            $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
465
            $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
466
            Database:: query($sql);
467
468
            // Remove terms from db.
469
            require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
470
            delete_all_values_for_item($course_id, TOOL_DOCUMENT, $link_id);
471
        }
472
    }
473
474
    /**
475
     *
476
     * Get link info
477
     * @param int $id
478
     * @return array link info
479
     *
480
     **/
481
    public static function getLinkInfo($id)
482
    {
483
        $tbl_link = Database::get_course_table(TABLE_LINK);
484
        $course_id = api_get_course_int_id();
485
486
        if (empty($id) || empty($course_id)) {
487
            return [];
488
        }
489
490
        $sql = "SELECT * FROM $tbl_link
491
                WHERE c_id = $course_id AND id='".intval($id)."' ";
492
        $result = Database::query($sql);
493
        $data = array();
494
        if (Database::num_rows($result)) {
495
            $data = Database::fetch_array($result);
496
        }
497
        return $data;
498
    }
499
500
    /**
501
     * @param int $id
502
     * @param array $values
503
     */
504
    public static function editLink($id, $values = array())
505
    {
506
        $tbl_link = Database::get_course_table(TABLE_LINK);
507
        $_course = api_get_course_info();
508
        $course_id = $_course['real_id'];
509
        $id = intval($id);
510
511
        $values['url'] = trim($values['url']);
512
        $values['title'] = trim($values['title']);
513
        $values['description'] = trim($values['description']);
514
        $values['target'] = empty($values['target']) ? '_self' : $values['target'];
515
        $values['on_homepage'] = isset($values['on_homepage']) ? $values['on_homepage'] : '';
516
517
        $categoryId = intval($values['category_id']);
518
519
        // We ensure URL to be absolute.
520
        if (strpos($values['url'], '://') === false) {
521
            $values['url'] = 'http://'.$_POST['url'];
522
        }
523
524
        // If the title is empty, we use the URL as title.
525
        if ($values['title'] == '') {
526
            $values['title'] = $values['url'];
527
        }
528
529
        // If the URL is invalid, an error occurs.
530
        if (!api_valid_url($values['url'], true)) {
531
            Display::addFlash(
532
                Display::return_message(get_lang('GiveURL'), 'error')
533
            );
534
535
            return false;
536
        }
537
538
        if (empty($id) || empty($course_id)) {
539
            return false;
540
        }
541
542
        // Finding the old category_id.
543
        $sql = "SELECT * FROM $tbl_link
544
                WHERE c_id = $course_id AND id='".$id."'";
545
        $result = Database:: query($sql);
546
        $row = Database:: fetch_array($result);
547
        $category_id = $row['category_id'];
548
549
        if ($category_id != $values['category_id']) {
550
            $sql = "SELECT MAX(display_order)
551
                    FROM $tbl_link 
552
                    WHERE
553
                        c_id = $course_id AND
554
                        category_id='".intval($values['category_id'])."'";
555
            $result = Database:: query($sql);
556
            list ($max_display_order) = Database:: fetch_row($result);
557
            $max_display_order++;
558
        } else {
559
            $max_display_order = $row['display_order'];
560
        }
561
        $params = [
562
            'url' => $values['url'],
563
            'title' => $values['title'],
564
            'description' => $values['description'],
565
            'category_id' => $values['category_id'],
566
            'display_order' => $max_display_order,
567
            'on_homepage' => $values['on_homepage'],
568
            'target' => $values['target'],
569
            'category_id' => $values['category_id']
570
        ];
571
572
        Database::update(
573
            $tbl_link,
574
            $params,
575
            ['c_id = ? AND id = ?' => [$course_id, $id]]
576
        );
577
578
        // Update search enchine and its values table if enabled.
579
        if (api_get_setting('search_enabled') == 'true') {
580
            $course_int_id = api_get_course_int_id();
581
            $course_id = api_get_course_id();
582
            $link_title = Database:: escape_string($values['title']);
583
            $link_description = Database:: escape_string($values['description']);
584
585
            // Actually, it consists on delete terms from db,
586
            // insert new ones, create a new search engine document, and remove the old one.
587
            // Get search_did.
588
            $tbl_se_ref = Database::get_main_table(
589
                TABLE_MAIN_SEARCH_ENGINE_REF
590
            );
591
            $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
592
            $sql = sprintf(
593
                $sql,
594
                $tbl_se_ref,
595
                $course_id,
596
                TOOL_LINK,
597
                $id
598
            );
599
            $res = Database:: query($sql);
600
601
            if (Database:: num_rows($res) > 0) {
602
                require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
603
604
                $se_ref = Database:: fetch_array($res);
605
                $specific_fields = get_specific_field_list();
606
                $ic_slide = new IndexableChunk();
607
608
                $all_specific_terms = '';
609
                foreach ($specific_fields as $specific_field) {
610
                    delete_all_specific_field_value(
611
                        $course_id,
612
                        $specific_field['id'],
613
                        TOOL_LINK,
614
                        $id
615
                    );
616
                    if (isset($_REQUEST[$specific_field['code']])) {
617
                        $sterms = trim(
618
                            $_REQUEST[$specific_field['code']]
619
                        );
620
                        if (!empty($sterms)) {
621
                            $all_specific_terms .= ' '.$sterms;
622
                            $sterms = explode(',', $sterms);
623
                            foreach ($sterms as $sterm) {
624
                                $ic_slide->addTerm(
625
                                    trim($sterm),
626
                                    $specific_field['code']
627
                                );
628
                                add_specific_field_value(
629
                                    $specific_field['id'],
630
                                    $course_id,
631
                                    TOOL_LINK,
632
                                    $id,
633
                                    $sterm
634
                                );
635
                            }
636
                        }
637
                    }
638
                }
639
640
                // Build the chunk to index.
641
                $ic_slide->addValue("title", $link_title);
642
                $ic_slide->addCourseId($course_id);
643
                $ic_slide->addToolId(TOOL_LINK);
644
                $xapian_data = array(
645
                    SE_COURSE_ID => $course_id,
646
                    SE_TOOL_ID => TOOL_LINK,
647
                    SE_DATA => array(
648
                        'link_id' => (int) $id
649
                    ),
650
                    SE_USER => (int) api_get_user_id(),
651
652
                );
653
                $ic_slide->xapian_data = serialize($xapian_data);
654
                $link_description = $all_specific_terms.' '.$link_description;
655
                $ic_slide->addValue('content', $link_description);
656
657
                // Add category name if set.
658
                if (isset($categoryId) && $categoryId > 0) {
659
                    $table_link_category = Database::get_course_table(
660
                        TABLE_LINK_CATEGORY
661
                    );
662
                    $sql_cat = 'SELECT * FROM %s WHERE id=%d and c_id = %d LIMIT 1';
663
                    $sql_cat = sprintf(
664
                        $sql_cat,
665
                        $table_link_category,
666
                        $categoryId,
667
                        $course_int_id
668
                    );
669
                    $result = Database:: query($sql_cat);
670
                    if (Database:: num_rows($result) == 1) {
671
                        $row = Database:: fetch_array($result);
672
                        $ic_slide->addValue(
673
                            'category',
674
                            $row['category_title']
675
                        );
676
                    }
677
                }
678
679
                $di = new ChamiloIndexer();
680
                isset ($_POST['language']) ? $lang = Database:: escape_string($_POST['language']) : $lang = 'english';
681
                $di->connectDb(null, null, $lang);
682
                $di->remove_document($se_ref['search_did']);
683
                $di->addChunk($ic_slide);
684
685
                // Index and return search engine document id.
686
                $did = $di->index();
687
                if ($did) {
688
                    // Save it to db.
689
                    $sql = 'DELETE FROM %s
690
                            WHERE course_code=\'%s\'
691
                            AND tool_id=\'%s\'
692
                            AND ref_id_high_level=\'%s\'';
693
                    $sql = sprintf(
694
                        $sql,
695
                        $tbl_se_ref,
696
                        $course_id,
697
                        TOOL_LINK,
698
                        $id
699
                    );
700
                    Database:: query($sql);
701
                    $sql = 'INSERT INTO %s (c_id, id, course_code, tool_id, ref_id_high_level, search_did)
702
                            VALUES (NULL , \'%s\', \'%s\', %s, %s)';
703
                    $sql = sprintf(
704
                        $sql,
705
                        $tbl_se_ref,
706
                        $course_int_id,
707
                        $course_id,
708
                        TOOL_LINK,
709
                        $id,
710
                        $did
711
                    );
712
                    Database:: query($sql);
713
                }
714
            }
715
        }
716
717
        // "WHAT'S NEW" notification: update table last_toolEdit.
718
        api_item_property_update(
719
            $_course,
720
            TOOL_LINK,
721
            $id,
722
            'LinkUpdated',
723
            api_get_user_id()
724
        );
725
        Display::addFlash(Display::return_message(get_lang('LinkModded')));
726
    }
727
728
    /**
729
     * @param int $id
730
     * @param array $values
731
     * @return bool
732
     */
733
    public static function editCategory($id, $values)
734
    {
735
        $table = Database::get_course_table(TABLE_LINK_CATEGORY);
736
        $course_id = api_get_course_int_id();
737
        $id = intval($id);
738
739
        // This is used to put the modified info of the category-form into the database.
740
        $params = [
741
            'category_title' => $values['category_title'],
742
            'description' => $values['description']
743
        ];
744
        Database::update(
745
            $table,
746
            $params,
747
            ['c_id = ? AND id = ?' => [$course_id, $id]]
748
        );
749
        Display::addFlash(Display::return_message(get_lang('CategoryModded')));
750
751
        return true;
752
    }
753
754
    /**
755
     * Changes the visibility of a link
756
     * @todo add the changing of the visibility of a course
757
     * @author Patrick Cool <[email protected]>, Ghent University
758
     */
759
    public static function change_visibility_link($id, $scope)
760
    {
761
        $_course = api_get_course_info();
762
        $_user = api_get_user_info();
763
        if ($scope == TOOL_LINK) {
764
            api_item_property_update(
765
                $_course,
766
                TOOL_LINK,
767
                $id,
768
                $_GET['action'],
769
                $_user['user_id']
770
            );
771
            Display::addFlash(Display::return_message(get_lang('VisibilityChanged')));
772
        } elseif ($scope == TOOL_LINK_CATEGORY) {
773
            api_item_property_update(
774
                $_course,
775
                TOOL_LINK_CATEGORY,
776
                $id,
777
                $_GET['action'],
778
                $_user['user_id']
779
            );
780
            Display::addFlash(Display::return_message(get_lang('VisibilityChanged')));
781
        }
782
    }
783
784
    /**
785
     * Generate SQL to select all the links categories in the current course and
786
     * session
787
     * @param   int $courseId
788
     * @param   int $sessionId
789
     * @param   bool $withBaseContent
790
     *
791
     * @return array
792
     */
793
    public static function getLinkCategories($courseId, $sessionId, $withBaseContent = true)
794
    {
795
        $tblLinkCategory = Database::get_course_table(TABLE_LINK_CATEGORY);
796
        $tblItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
797
        $courseId = intval($courseId);
798
        $courseInfo = api_get_course_info_by_id($courseId);
799
800
        // Condition for the session.
801
        $sessionCondition = api_get_session_condition(
802
            $sessionId,
803
            true,
804
            $withBaseContent,
805
            'linkcat.session_id'
806
        );
807
808
        // Getting links
809
        $sql = "SELECT *, linkcat.id
810
                FROM $tblLinkCategory linkcat
811
                WHERE
812
                    linkcat.c_id = $courseId
813
                    $sessionCondition
814
                ORDER BY linkcat.display_order DESC";
815
816
        $result = Database::query($sql);
817
        $categories = Database::store_result($result);
818
819
        $sql = "SELECT *, linkcat.id
820
                FROM $tblLinkCategory linkcat
821
                INNER JOIN $tblItemProperty ip
822
                ON (linkcat.id = ip.ref AND linkcat.c_id = ip.c_id)
823
                WHERE
824
                    ip.tool = '".TOOL_LINK_CATEGORY."' AND
825
                    (ip.visibility = '0' OR ip.visibility = '1')
826
                    $sessionCondition AND
827
                    linkcat.c_id = ".$courseId."
828
                ORDER BY linkcat.display_order DESC";
829
830
        $result = Database::query($sql);
831
832
        $categoryInItemProperty = array();
833
        if (Database::num_rows($result)) {
834
            while ($row = Database::fetch_array($result, 'ASSOC')) {
835
                $categoryInItemProperty[$row['id']] = $row;
836
            }
837
        }
838
839
        foreach ($categories as & $category) {
840
            if (!isset($categoryInItemProperty[$category['id']])) {
841
                api_item_property_update(
842
                    $courseInfo,
843
                    TOOL_LINK_CATEGORY,
844
                    $category['id'],
845
                    'LinkCategoryAdded',
846
                    api_get_user_id()
847
                );
848
                //api_set_default_visibility($category['id'], TOOL_LINK_CATEGORY);
849
            }
850
        }
851
852
        $sql = "SELECT DISTINCT linkcat.*, visibility
853
                FROM $tblLinkCategory linkcat
854
                INNER JOIN $tblItemProperty ip
855
                ON (linkcat.id = ip.ref AND linkcat.c_id = ip.c_id)
856
                WHERE
857
                    ip.tool = '".TOOL_LINK_CATEGORY."' AND
858
                    (ip.visibility = '0' OR ip.visibility = '1')
859
                    $sessionCondition AND
860
                    linkcat.c_id = ".$courseId."
861
                ORDER BY linkcat.display_order DESC
862
                ";
863
        $result = Database::query($sql);
864
865
        return Database::store_result($result, 'ASSOC');
866
    }
867
868
    /**
869
     * @param integer $categoryId
870
     * @param $courseId
871
     * @param $sessionId
872
     * @param bool $withBaseContent
873
     *
874
     * @return array
875
     */
876
    public static function getLinksPerCategory(
877
        $categoryId,
878
        $courseId,
879
        $sessionId,
880
        $withBaseContent = true
881
    ) {
882
        $tbl_link = Database::get_course_table(TABLE_LINK);
883
        $TABLE_ITEM_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
884
        $courseId = (int) $courseId;
885
        $sessionId = (int) $sessionId;
886
        $categoryId = (int) $categoryId;
887
888
        // Condition for the session.
889
        $condition_session = api_get_session_condition(
890
            $sessionId,
891
            true,
892
            false,
893
            'ip.session_id'
894
        );
895
896
        if (!empty($sessionId)) {
897
            $conditionBaseSession = api_get_session_condition(
898
                0,
899
                true,
900
                $withBaseContent,
901
                'ip.session_id'
902
            );
903
            $condition = " AND 
904
                (
905
                    (ip.visibility = '1' $conditionBaseSession) OR
906
                     
907
                    (
908
                        (ip.visibility = '0' OR ip.visibility = '1')
909
                        $condition_session
910
                    )
911
                )
912
            ";
913
        } else {
914
            $condition = api_get_session_condition(
915
                0,
916
                true,
917
                false,
918
                'ip.session_id'
919
            );
920
            $condition .= " AND (ip.visibility = '0' OR ip.visibility = '1') $condition ";
921
        }
922
923
        $sql = "SELECT 
924
                    link.id,
925
                    ip.session_id,
926
                    link.session_id link_session_id,
927
                    url,
928
                    category_id,
929
                    visibility,
930
                    description,
931
                    title,
932
                    target,
933
                    on_homepage
934
                FROM $tbl_link link
935
                INNER JOIN $TABLE_ITEM_PROPERTY ip
936
                ON (link.id = ip.ref AND link.c_id = ip.c_id)
937
                WHERE
938
                    ip.tool = '".TOOL_LINK."' AND
939
                    link.category_id = '" . $categoryId."' AND
940
                    link.c_id = $courseId AND
941
                    ip.c_id = $courseId
942
                    $condition
943
                ORDER BY link.display_order ASC, ip.session_id DESC";
944
945
        $result = Database:: query($sql);
946
947
        return Database::store_result($result);
948
    }
949
950
    /**
951
     * Displays all the links of a given category.
952
     * @author Patrick Cool <[email protected]>, Ghent University
953
     * @author Julio Montoya
954
     *
955
     * @param $catid
956
     * @param integer $courseId
957
     * @param integer $session_id
958
     * @return string
959
     */
960
    public static function showLinksPerCategory($catid, $courseId, $session_id)
961
    {
962
        global $token;
963
        $_user = api_get_user_info();
964
        $catid = intval($catid);
965
966
        $links = self::getLinksPerCategory($catid, $courseId, $session_id);
967
        $content = '';
968
        $numberOfLinks = count($links);
969
970
        if (!empty($links)) {
971
            $content .= '<div class="link list-group">';
972
            $i = 1;
973
            $linksAdded = [];
974
            foreach ($links as $myrow) {
975
                $linkId = $myrow['id'];
976
977
                if (in_array($linkId, $linksAdded)) {
978
                    continue;
979
                }
980
981
                $linksAdded[] = $linkId;
982
                $categoryId = $myrow['category_id'];
983
984
                // Validation when belongs to a session.
985
                $session_img = api_get_session_image(
986
                    $myrow['link_session_id'],
987
                    $_user['status']
988
                );
989
990
                $toolbar = '';
991
                $link_validator = '';
992
                if (api_is_allowed_to_edit(null, true)) {
993
                    $toolbar .= Display::toolbarButton(
994
                        '',
995
                        'javascript:void(0);',
996
                        'check-circle-o',
997
                        'default btn-sm',
998
                        array(
999
                            'onclick' => "check_url('".$linkId."', '".addslashes($myrow['url'])."');",
1000
                            'title' => get_lang('CheckURL')
1001
                        )
1002
                    );
1003
1004
                    $link_validator .= Display::span(
1005
                        '',
1006
                        array(
1007
                        'id' => 'url_id_'.$linkId,
1008
                        'class' => 'check-link'
1009
                        )
1010
                    );
1011
1012
                    if ($session_id == $myrow['link_session_id']) {
1013
                        $url = api_get_self().'?'.api_get_cidreq().'&action=editlink&id='.$linkId;
1014
                        $title = get_lang('Edit');
1015
                        $toolbar .= Display::toolbarButton(
1016
                            '',
1017
                            $url,
1018
                            'pencil',
1019
                            'default btn-sm',
1020
                            array(
1021
                                'title' => $title
1022
                            )
1023
                        );
1024
                    }
1025
1026
                    $urlVisibility = api_get_self().'?'.api_get_cidreq().
1027
                            '&sec_token='.$token.
1028
                            '&id='.$linkId.
1029
                            '&scope=link&category_id='.$categoryId;
1030
1031
                    switch ($myrow['visibility']) {
1032
                        case '1':
1033
                            $urlVisibility .= '&action=invisible';
1034
                            $title = get_lang('MakeInvisible');
1035
                            $toolbar .= Display::toolbarButton(
1036
                                '',
1037
                                $urlVisibility,
1038
                                'eye',
1039
                                'default btn-sm',
1040
                                array(
1041
                                    'title' => $title
1042
                                )
1043
                            );
1044
                            break;
1045
                        case '0':
1046
                            $urlVisibility .= '&action=visible';
1047
                            $title = get_lang('MakeVisible');
1048
                            $toolbar .= Display::toolbarButton(
1049
                                '',
1050
                                $urlVisibility,
1051
                                'eye-slash',
1052
                                'primary btn-sm',
1053
                                array(
1054
                                    'title' => $title
1055
                                )
1056
                            );
1057
                            break;
1058
                    }
1059
1060
                    if ($session_id == $myrow['link_session_id']) {
1061
                        $moveLinkParams = [
1062
                            'id' => $linkId,
1063
                            'scope' => 'category',
1064
                            'category_id' => $categoryId,
1065
                            'action' => 'move_link_up'
1066
                        ];
1067
1068
                        $toolbar .= Display::toolbarButton(
1069
                            get_lang('MoveUp'),
1070
                            api_get_self().'?'.api_get_cidreq().'&'.http_build_query($moveLinkParams),
1071
                            'level-up',
1072
                            'default',
1073
                            ['class' => 'btn-sm '.($i === 1 ? 'disabled' : '')],
1074
                            false
1075
                        );
1076
1077
                        $moveLinkParams['action'] = 'move_link_down';
1078
                        $toolbar .= Display::toolbarButton(
1079
                            get_lang('MoveDown'),
1080
                            api_get_self().'?'.api_get_cidreq().'&'.http_build_query($moveLinkParams),
1081
                            'level-down',
1082
                            'default',
1083
                            ['class' => 'btn-sm '.($i === $numberOfLinks ? 'disabled' : '')],
1084
                            false
1085
                        );
1086
1087
                        $url .= api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=deletelink&id='.$linkId.'&category_id='.$categoryId;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $url does not seem to be defined for all execution paths leading up to this point.
Loading history...
1088
                        $event = "javascript: if(!confirm('".get_lang('LinkDelconfirm')."'))return false;";
1089
                        $title = get_lang('Delete');
1090
1091
                        $toolbar .= Display::toolbarButton(
1092
                            '',
1093
                            $url,
1094
                            'trash',
1095
                            'default btn-sm',
1096
                            array(
1097
                                'onclick' => $event,
1098
                                'title' => $title
1099
                            )
1100
                        );
1101
                    }
1102
                }
1103
1104
                $showLink = false;
1105
                $titleClass = '';
1106
                if ($myrow['visibility'] == '1') {
1107
                    $showLink = true;
1108
                } else {
1109
                    if (api_is_allowed_to_edit(null, true)) {
1110
                        $showLink = true;
1111
                        $titleClass = 'text-muted';
1112
                    }
1113
                }
1114
1115
                if ($showLink) {
1116
                    $iconLink = Display::return_icon(
1117
                        'url.png',
1118
                        get_lang('Link'),
1119
                        null,
1120
                        ICON_SIZE_SMALL
1121
                    );
1122
                    $url = api_get_path(WEB_CODE_PATH).'link/link_goto.php?'.api_get_cidreq().'&link_id='.$linkId.'&link_url='.urlencode($myrow['url']);
1123
                    $content .= '<div class="list-group-item">';
1124
                    $content .= '<div class="pull-right"><div class="btn-group">'.$toolbar.'</div></div>';
1125
                    $content .= '<h4 class="list-group-item-heading">';
1126
                    $content .= $iconLink;
1127
                    $content .= Display::tag(
1128
                        'a',
1129
                        Security::remove_XSS($myrow['title']),
1130
                        array(
1131
                            'href' => $url,
1132
                            'target' => $myrow['target'],
1133
                            'class' => $titleClass
1134
                        )
1135
                    );
1136
                    $content .= $link_validator;
1137
                    $content .= $session_img;
1138
                    $content .= '</h4>';
1139
                    $content .= '<p class="list-group-item-text">'.$myrow['description'].'</p>';
1140
                    $content .= '</div>';
1141
                }
1142
                $i++;
1143
            }
1144
            $content .= '</div>';
1145
        }
1146
1147
        return $content;
1148
    }
1149
1150
    /**
1151
     * Displays the edit, delete and move icons
1152
     * @param int   Category ID
1153
     * @param integer $currentCategory
1154
     * @param integer $countCategories
1155
     * @return string
1156
     *
1157
     * @author Patrick Cool <[email protected]>, Ghent University
1158
     */
1159
    public static function showCategoryAdminTools($category, $currentCategory, $countCategories)
1160
    {
1161
        $categoryId = $category['id'];
1162
        $token = null;
1163
        $tools = '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=editcategory&id='.$categoryId.'&category_id='.$categoryId.'" title='.get_lang('Modify').'">'.
1164
            Display:: return_icon(
1165
                'edit.png',
1166
                get_lang('Modify'),
1167
                array(),
1168
                ICON_SIZE_SMALL
1169
            ).'</a>';
1170
1171
        // DISPLAY MOVE UP COMMAND only if it is not the top link.
1172
        if ($currentCategory != 0) {
1173
            $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=up&up='.$categoryId.'&category_id='.$categoryId.'" title="'.get_lang('Up').'">'.
1174
                Display:: return_icon(
1175
                    'up.png',
1176
                    get_lang('Up'),
1177
                    array(),
1178
                    ICON_SIZE_SMALL
1179
                ).'</a>';
1180
        } else {
1181
            $tools .= Display:: return_icon(
1182
                'up_na.png',
1183
                get_lang('Up'),
1184
                array(),
1185
                ICON_SIZE_SMALL
1186
            ).'</a>';
1187
        }
1188
1189
        // DISPLAY MOVE DOWN COMMAND only if it is not the bottom link.
1190
        if ($currentCategory < $countCategories - 1) {
1191
            $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=down&down='.$categoryId.'&category_id='.$categoryId.'">'.
1192
                Display:: return_icon(
1193
                    'down.png',
1194
                    get_lang('Down'),
1195
                    array(),
1196
                    ICON_SIZE_SMALL
1197
                ).'</a>';
1198
        } else {
1199
            $tools .= Display:: return_icon(
1200
                'down_na.png',
1201
                get_lang('Down'),
1202
                array(),
1203
                ICON_SIZE_SMALL
1204
            ).'</a>';
1205
        }
1206
1207
        $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&sec_token='.$token.'&action=deletecategory&id='.$categoryId."&category_id=$categoryId\"
1208
            onclick=\"javascript: if(!confirm('".get_lang('CategoryDelconfirm')."')) return false;\">".
1209
            Display:: return_icon(
1210
                'delete.png',
1211
                get_lang('Delete'),
1212
                array(),
1213
                ICON_SIZE_SMALL
1214
            ).'</a>';
1215
1216
        return $tools;
1217
    }
1218
1219
    /**
1220
     * move a link or a linkcategory up or down
1221
     * @param   int Category ID
1222
     * @param   int Course ID
1223
     * @param   int Session ID
1224
     * @author Patrick Cool <[email protected]>, Ghent University
1225
     * @todo support sessions
1226
     */
1227
    public static function movecatlink($action, $catlinkid, $courseId = null, $sessionId = null)
1228
    {
1229
        $tbl_categories = Database::get_course_table(TABLE_LINK_CATEGORY);
1230
1231
        if (is_null($courseId)) {
1232
            $courseId = api_get_course_int_id();
1233
        }
1234
        $courseId = intval($courseId);
1235
        if (is_null($sessionId)) {
1236
            $sessionId = api_get_session_id();
1237
        }
1238
        $sessionId = intval($sessionId);
1239
        $thiscatlinkId = intval($catlinkid);
1240
1241
        if ($action == 'down') {
1242
            $sortDirection = 'DESC';
1243
        }
1244
1245
        if ($action == 'up') {
1246
            $sortDirection = 'ASC';
1247
        }
1248
1249
        $movetable = $tbl_categories;
1250
1251
        if (!empty($sortDirection)) {
1252
            if (!in_array(trim(strtoupper($sortDirection)), array('ASC', 'DESC'))) {
1253
                $sortDirection = 'ASC';
1254
            }
1255
1256
            $sql = "SELECT id, display_order FROM $movetable
1257
                    WHERE c_id = $courseId
1258
                    ORDER BY display_order $sortDirection";
1259
            $linkresult = Database:: query($sql);
1260
            $thislinkOrder = 1;
1261
            while ($sortrow = Database:: fetch_array($linkresult)) {
1262
                // STEP 2 : FOUND THE NEXT LINK ID AND ORDER, COMMIT SWAP
1263
                // This part seems unlogic, but it isn't . We first look for the current link with the querystring ID
1264
                // and we know the next iteration of the while loop is the next one. These should be swapped.
1265
                if (isset($thislinkFound) && $thislinkFound) {
1266
                    $nextlinkId = $sortrow['id'];
1267
                    $nextlinkOrder = $sortrow['display_order'];
1268
1269
                    Database:: query(
1270
                        "UPDATE ".$movetable."
1271
                        SET display_order = '$nextlinkOrder'
1272
                        WHERE c_id = $courseId  AND id =  '$thiscatlinkId'"
1273
                    );
1274
                    Database:: query(
1275
                        "UPDATE ".$movetable."
1276
                        SET display_order = '$thislinkOrder'
1277
                        WHERE c_id = $courseId  AND id =  '$nextlinkId'"
1278
                    );
1279
1280
                    break;
1281
                }
1282
                if ($sortrow['id'] == $thiscatlinkId) {
1283
                    $thislinkOrder = $sortrow['display_order'];
1284
                    $thislinkFound = true;
1285
                }
1286
            }
1287
        }
1288
1289
        Display::addFlash(Display::return_message(get_lang('LinkMoved')));
1290
    }
1291
1292
    /**
1293
     * CSV file import functions
1294
     * @author René Haentjens , Ghent University
1295
     * @param string $catname
1296
     * @return int
1297
     */
1298
    public static function get_cat($catname)
1299
    {
1300
        // Get category id (existing or make new).
1301
        $tbl_categories = Database::get_course_table(TABLE_LINK_CATEGORY);
1302
        $course_id = api_get_course_int_id();
1303
1304
        $result = Database:: query(
1305
            "SELECT id FROM ".$tbl_categories."
1306
            WHERE c_id = $course_id AND category_title='".Database::escape_string($catname)."'"
1307
        );
1308
        if (Database:: num_rows($result) >= 1 && ($row = Database:: fetch_array($result))) {
1309
            return $row['id']; // Several categories with same name: take the first.
1310
        }
1311
1312
        $result = Database:: query(
1313
            "SELECT MAX(display_order) FROM ".$tbl_categories." WHERE c_id = $course_id "
1314
        );
1315
        list ($max_order) = Database:: fetch_row($result);
1316
1317
        $params = [
1318
            'c_id' => $course_id,
1319
            'category_title' => $catname,
1320
            'description' => '',
1321
            'display_order' => $max_order + 1
1322
        ];
1323
        $id = Database::insert($tbl_categories, $params);
1324
1325
        return $id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $id could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
1326
    }
1327
1328
    /**
1329
     * CSV file import functions
1330
     * @author René Haentjens , Ghent University
1331
     * @param string $url
1332
     * @param string $title
1333
     * @param string $description
1334
     * @param string $on_homepage
1335
     * @param string $hidden
1336
     */
1337
    public static function put_link($url, $cat, $title, $description, $on_homepage, $hidden)
1338
    {
1339
        $_course = api_get_course_info();
1340
        $_user = api_get_user_info();
1341
1342
        $tbl_link = Database::get_course_table(TABLE_LINK);
1343
        $course_id = api_get_course_int_id();
1344
1345
        $urleq = "url='".Database:: escape_string($url)."'";
1346
        $cateq = "category_id=".intval($cat);
1347
1348
        $result = Database:: query("
1349
            SELECT id FROM $tbl_link
1350
            WHERE c_id = $course_id AND ".$urleq.' AND '.$cateq
1351
        );
1352
1353
        if (Database:: num_rows($result) >= 1 && ($row = Database:: fetch_array($result))) {
1354
            $sql = "UPDATE $tbl_link SET 
1355
                        title = '".Database:: escape_string($title)."', 
1356
                        description = '" . Database:: escape_string($description)."'
1357
                    WHERE c_id = $course_id AND  id='".Database:: escape_string($row['id'])."'";
1358
            Database:: query($sql);
1359
1360
            $ipu = 'LinkUpdated';
1361
            $rv = 1; // 1 = upd
1362
        } else {
1363
            // Add new link
1364
            $result = Database:: query(
1365
                "SELECT MAX(display_order) FROM  $tbl_link
1366
                WHERE c_id = $course_id AND category_id='".intval($cat)."'"
1367
            );
1368
            list ($max_order) = Database:: fetch_row($result);
1369
1370
            Database:: query(
1371
                "INSERT INTO $tbl_link (c_id, url, title, description, category_id, display_order, on_homepage)
1372
                VALUES (".api_get_course_int_id().",
1373
                '" . Database:: escape_string($url)."',
1374
                '" . Database:: escape_string($title)."',
1375
                '" . Database:: escape_string($description)."',
1376
                '" . intval($cat)."','".(intval($max_order) + 1)."',
1377
                '" . intval($on_homepage).
1378
                "')"
1379
            );
1380
1381
            $id = Database:: insert_id();
1382
            $ipu = 'LinkAdded';
1383
            $rv = 2; // 2 = new
1384
        }
1385
1386
        api_item_property_update(
1387
            $_course,
1388
            TOOL_LINK,
1389
            $id,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $id does not seem to be defined for all execution paths leading up to this point.
Loading history...
1390
            $ipu,
1391
            $_user['user_id']
1392
        );
1393
1394
        if ($hidden && $ipu == 'LinkAdded') {
1395
            api_item_property_update(
1396
                $_course,
1397
                TOOL_LINK,
1398
                $id,
1399
                'invisible',
1400
                $_user['user_id']
1401
            );
1402
        }
1403
1404
        return $rv;
1405
    }
1406
1407
    /**
1408
     * CSV file import functions
1409
     * @author René Haentjens , Ghent University
1410
     */
1411
    public static function import_link($linkdata)
1412
    {
1413
        // url, category_id, title, description, ...
1414
        // Field names used in the uploaded file
1415
        $known_fields = array(
1416
            'url',
1417
            'category',
1418
            'title',
1419
            'description',
1420
            'on_homepage',
1421
            'hidden'
1422
        );
1423
1424
        $hide_fields = array(
1425
            'kw',
1426
            'kwd',
1427
            'kwds',
1428
            'keyword',
1429
            'keywords'
1430
        );
1431
1432
        // All other fields are added to description, as "name:value".
1433
        // Only one hide_field is assumed to be present, <> is removed from value.
1434
        if (!($url = trim($linkdata['url'])) || !($title = trim($linkdata['title']))) {
1435
            return 0; // 0 = fail
1436
        }
1437
1438
        $cat = ($catname = trim($linkdata['category'])) ? self::get_cat($catname) : 0;
1439
1440
        $regs = array(); // Will be passed to ereg()
1441
        $d = '';
1442
        foreach ($linkdata as $key => $value) {
1443
            if (!in_array($key, $known_fields)) {
1444
                if (in_array($key, $hide_fields) && ereg(
0 ignored issues
show
Deprecated Code introduced by
The function ereg() has been deprecated: 5.3.0 Use preg_match() instead ( Ignorable by Annotation )

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

1444
                if (in_array($key, $hide_fields) && /** @scrutinizer ignore-deprecated */ ereg(

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
1445
                        '^<?([^>]*)>?$',
1446
                        $value,
1447
                        $regs
1448
                    )
1449
                ) { // possibly in <...>
1450
                    if (($kwlist = trim($regs[1])) != '') {
1451
                        $kw = '<i kw="'.htmlspecialchars($kwlist).'">';
1452
                    } else {
1453
                        $kw = '';
1454
                    }
1455
                    // i.e. assume only one of the $hide_fields will be present
1456
                    // and if found, hide the value as expando property of an <i> tag
1457
                } elseif (trim($value)) {
1458
                    $d .= ', '.$key.':'.$value;
1459
                }
1460
            }
1461
        }
1462
        if (!empty($d)) {
1463
            $d = substr($d, 2).' - ';
1464
        }
1465
1466
        return self::put_link(
1467
            $url,
1468
            $cat,
1469
            $title,
1470
            $kw.ereg_replace(
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $kw does not seem to be defined for all execution paths leading up to this point.
Loading history...
Deprecated Code introduced by
The function ereg_replace() has been deprecated: 5.3.0 Use preg_replace() instead ( Ignorable by Annotation )

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

1470
            $kw./** @scrutinizer ignore-deprecated */ ereg_replace(

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
1471
                '\[((/?(b|big|i|small|sub|sup|u))|br/)\]',
1472
                '<\\1>',
1473
                htmlspecialchars($d.$linkdata['description'])
1474
            ).($kw ? '</i>' : ''),
1475
            $linkdata['on_homepage'] ? '1' : '0',
1476
            $linkdata['hidden'] ? '1' : '0'
1477
        );
1478
        // i.e. allow some BBcode tags, e.g. [b]...[/b]
1479
    }
1480
1481
    /**
1482
     * This function checks if the url is a vimeo link
1483
     * @author Julio Montoya
1484
     * @version 1.0
1485
     */
1486
    public static function isVimeoLink($url)
1487
    {
1488
        $isLink = strrpos($url, "vimeo.com");
1489
1490
        return $isLink;
1491
    }
1492
1493
    /**
1494
     * Get vimeo id from URL
1495
     * @param string $url
1496
     * @return bool|mixed
1497
     */
1498
    public static function getVimeoLinkId($url)
1499
    {
1500
        $possibleUrls = array(
1501
            'http://www.vimeo.com/',
1502
            'http://vimeo.com/',
1503
            'https://www.vimeo.com/',
1504
            'https://vimeo.com/'
1505
        );
1506
        $url = str_replace($possibleUrls, '', $url);
1507
1508
        if (is_numeric($url)) {
1509
            return $url;
1510
        }
1511
        return false;
1512
    }
1513
1514
    /**
1515
     * This function checks if the url is a youtube link
1516
     * @author Jorge Frisancho
1517
     * @author Julio Montoya - Fixing code
1518
     * @version 1.0
1519
     */
1520
    public static function is_youtube_link($url)
1521
    {
1522
        $is_youtube_link = strrpos($url, "youtube") || strrpos(
1523
            $url,
1524
            "youtu.be"
1525
        );
1526
        return $is_youtube_link;
1527
    }
1528
1529
    /**
1530
     * Get youtube id from an URL
1531
     * @param string $url
1532
     * @return string
1533
     */
1534
    public static function get_youtube_video_id($url)
1535
    {
1536
        // This is the length of YouTube's video IDs
1537
        $len = 11;
1538
1539
        // The ID string starts after "v=", which is usually right after
1540
        // "youtube.com/watch?" in the URL
1541
        $pos = strpos($url, "v=");
1542
        $id = '';
1543
1544
        //If false try other options
1545
        if ($pos === false) {
1546
            $url_parsed = parse_url($url);
1547
1548
            //Youtube shortener
1549
            //http://youtu.be/ID
1550
            $pos = strpos($url, "youtu.be");
1551
1552
            if ($pos == false) {
1553
                $id = '';
1554
            } else {
1555
                return substr($url_parsed['path'], 1);
1556
            }
1557
1558
            //if empty try the youtube.com/embed/ID
1559
            if (empty($id)) {
1560
                $pos = strpos($url, "embed");
1561
                if ($pos === false) {
1562
                    return '';
1563
                } else {
1564
                    return substr($url_parsed['path'], 7);
1565
                }
1566
            }
1567
        } else {
1568
            // Offset the start location to match the beginning of the ID string
1569
            $pos += 2;
1570
            // Get the ID string and return it
1571
            $id = substr($url, $pos, $len);
1572
            return $id;
1573
        }
1574
    }
1575
1576
    /**
1577
     * @param int $course_id
1578
     * @param int $session_id
1579
     * @param int $categoryId
1580
     * @param string $show
1581
     * @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...
1582
     */
1583
    public static function listLinksAndCategories(
1584
        $course_id,
1585
        $session_id,
1586
        $categoryId,
1587
        $show = 'none',
1588
        $token = null
1589
    ) {
1590
        $tbl_link = Database::get_course_table(TABLE_LINK);
1591
        $tblCIP = Database::get_course_table(TABLE_ITEM_PROPERTY);
1592
        $categoryId = intval($categoryId);
1593
1594
        /*	Action Links */
1595
        echo '<div class="actions">';
1596
        if (api_is_allowed_to_edit(null, true)) {
1597
            echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=addlink&category_id='.$categoryId.'">'.
1598
                Display::return_icon('new_link.png', get_lang('LinkAdd'), '', ICON_SIZE_MEDIUM).'</a>';
1599
            echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=addcategory&category_id='.$categoryId.'">'.
1600
                Display::return_icon('new_folder.png', get_lang('CategoryAdd'), '', ICON_SIZE_MEDIUM).'</a>';
1601
        }
1602
1603
        $categories = self::getLinkCategories($course_id, $session_id);
1604
        $countCategories = count($categories);
1605
        if (!empty($countCategories)) {
1606
            echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=list&show=none">';
1607
            echo Display::return_icon('forum_listview.png', get_lang('FlatView'), '', ICON_SIZE_MEDIUM).' </a>';
1608
1609
            echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=list&show=all">';
1610
            echo Display::return_icon('forum_nestedview.png', get_lang('NestedView'), '', ICON_SIZE_MEDIUM).'</a>';
1611
        }
1612
        echo '</div>';
1613
        $linksPerCategory = self::showLinksPerCategory(0, $course_id, $session_id);
1614
1615
        if (empty($countCategories)) {
1616
            echo $linksPerCategory;
1617
        } else {
1618
            if (!empty($linksPerCategory)) {
1619
                echo Display::panel($linksPerCategory, get_lang('NoCategory'));
1620
            }
1621
        }
1622
1623
        $counter = 0;
1624
        foreach ($categories as $myrow) {
1625
            // Student don't see invisible categories.
1626
            if (!api_is_allowed_to_edit(null, true)) {
1627
                if ($myrow['visibility'] == 0) {
1628
                    continue;
1629
                }
1630
            }
1631
1632
            // Validation when belongs to a session
1633
            $showChildren = $categoryId == $myrow['id'] || $show == 'all';
1634
            $myrow['description'] = $myrow['description'];
1635
1636
            $strVisibility = '';
1637
            $visibilityClass = null;
1638
            if ($myrow['visibility'] == '1') {
1639
                $strVisibility = '<a href="link.php?'.api_get_cidreq().'&sec_token='.$token.'&action=invisible&id='.$myrow['id'].'&scope='.TOOL_LINK_CATEGORY.'" title="'.get_lang('Hide').'">'.
1640
                    Display::return_icon('visible.png', get_lang('Hide'), array(), ICON_SIZE_SMALL).'</a>';
1641
            } elseif ($myrow['visibility'] == '0') {
1642
                $visibilityClass = 'text-muted';
1643
                $strVisibility = ' <a href="link.php?'.api_get_cidreq().'&sec_token='.$token.'&action=visible&id='.$myrow['id'].'&scope='.TOOL_LINK_CATEGORY.'" title="'.get_lang('Show').'">'.
1644
                    Display::return_icon('invisible.png', get_lang('Show'), array(), ICON_SIZE_SMALL).'</a>';
1645
            }
1646
1647
            $header = '';
1648
            if ($showChildren) {
1649
                $header .= '<a class="'.$visibilityClass.'" href="'.api_get_self().'?'.api_get_cidreq().'&category_id=">';
1650
                $header .= Display::return_icon('forum_nestedview.png');
1651
            } else {
1652
                $header .= '<a class="'.$visibilityClass.'" href="'.api_get_self().'?'.api_get_cidreq().'&category_id='.$myrow['id'].'">';
1653
                $header .= Display::return_icon('forum_listview.png');
1654
            }
1655
1656
            $header .= Security::remove_XSS($myrow['category_title']).'</a>';
1657
            $header .= '<div class="pull-right">';
1658
1659
            if (api_is_allowed_to_edit(null, true)) {
1660
                if ($session_id == $myrow['session_id']) {
1661
                    $header .= $strVisibility;
1662
                    $header .= self::showCategoryAdminTools($myrow, $counter, count($categories));
1663
                } else {
1664
                    $header .= get_lang('EditionNotAvailableFromSession');
1665
                }
1666
            }
1667
1668
            $childrenContent = '';
1669
            if ($showChildren) {
1670
                $childrenContent = self::showLinksPerCategory(
1671
                    $myrow['id'],
1672
                    api_get_course_int_id(),
1673
                    api_get_session_id()
1674
                );
1675
            }
1676
1677
            echo Display::panel($myrow['description'].$childrenContent, $header);
1678
1679
            $counter++;
1680
        }
1681
    }
1682
1683
    /**
1684
     * @param int $linkId
1685
     * @param $action
1686
     * @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...
1687
     *
1688
     * @return FormValidator
1689
     */
1690
    public static function getLinkForm($linkId, $action, $token = null)
1691
    {
1692
        $course_id = api_get_course_int_id();
1693
        $session_id = api_get_session_id();
1694
        $linkInfo = self::getLinkInfo($linkId);
1695
        $categoryId = isset($linkInfo['category_id']) ? $linkInfo['category_id'] : '';
1696
        $lpId = isset($_GET['lp_id']) ? Security::remove_XSS($_GET['lp_id']) : null;
1697
1698
        $form = new FormValidator(
1699
            'link',
1700
            'post',
1701
            api_get_self().'?action='.$action.
1702
            '&category_id='.$categoryId.
1703
            '&'.api_get_cidreq().
1704
            '&id='.$linkId.
1705
            '&sec_token='.$token
1706
        );
1707
1708
        if ($action == 'addlink') {
1709
            $form->addHeader(get_lang('LinkAdd'));
1710
        } else {
1711
            $form->addHeader(get_lang('LinkMod'));
1712
        }
1713
1714
        $target_link = '_blank';
1715
        $title = '';
1716
        $category = '';
1717
        $onhomepage = '';
1718
        $description = '';
1719
1720
        if (!empty($linkInfo)) {
1721
            $urllink = $linkInfo['url'];
1722
            $title = $linkInfo['title'];
1723
            $description = $linkInfo['description'];
1724
            $category = $linkInfo['category_id'];
1725
            if ($linkInfo['on_homepage'] != 0) {
1726
                $onhomepage = 1;
1727
            }
1728
            $target_link = $linkInfo['target'];
1729
        }
1730
1731
        $form->addHidden('id', $linkId);
1732
        $form->addText('url', 'URL');
1733
        $form->addRule('url', get_lang('GiveURL'), 'url');
1734
        $form->addText('title', get_lang('LinkName'));
1735
        $form->addTextarea('description', get_lang('Description'));
1736
1737
        $resultcategories = self::getLinkCategories($course_id, $session_id);
1738
        $options = ['0' => '--'];
1739
        if (!empty($resultcategories)) {
1740
            foreach ($resultcategories as $myrow) {
1741
                $options[$myrow['id']] = $myrow['category_title'];
1742
            }
1743
        }
1744
1745
        $form->addSelect('category_id', get_lang('Category'), $options);
1746
        $form->addCheckBox('on_homepage', null, get_lang('OnHomepage'));
1747
1748
        $targets = array(
1749
            '_self' => get_lang('LinkOpenSelf'),
1750
            '_blank' => get_lang('LinkOpenBlank'),
1751
            '_parent' => get_lang('LinkOpenParent'),
1752
            '_top' => get_lang('LinkOpenTop')
1753
        );
1754
1755
        $form->addSelect(
1756
            'target',
1757
            array(
1758
                get_lang('LinkTarget'),
1759
                get_lang('AddTargetOfLinkOnHomepage')
1760
            ),
1761
            $targets
1762
        );
1763
1764
        $defaults = array(
1765
            'url' => empty($urllink) ? 'http://' : Security::remove_XSS($urllink),
1766
            'title' => Security::remove_XSS($title),
1767
            'category_id' => $category,
1768
            'on_homepage' => $onhomepage,
1769
            'description' => $description,
1770
            'target' => $target_link
1771
        );
1772
1773
        if (api_get_setting('search_enabled') == 'true') {
1774
            require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
1775
            $specific_fields = get_specific_field_list();
1776
            $form->addCheckBox('index_document', get_lang('SearchFeatureDoIndexLink'), get_lang('Yes'));
1777
1778
            foreach ($specific_fields as $specific_field) {
1779
                $default_values = '';
1780
                if ($action == 'editlink') {
1781
                    $filter = array(
1782
                        'field_id' => $specific_field['id'],
1783
                        'ref_id' => intval($_GET['id']),
1784
                        'tool_id' => '\''.TOOL_LINK.'\''
1785
                    );
1786
                    $values = get_specific_field_values_list($filter, array('value'));
1787
                    if (!empty($values)) {
1788
                        $arr_str_values = array();
1789
                        foreach ($values as $value) {
1790
                            $arr_str_values[] = $value['value'];
1791
                        }
1792
                        $default_values = implode(', ', $arr_str_values);
1793
                    }
1794
                }
1795
                $form->addText($specific_field['name'], $specific_field['code']);
1796
                $defaults[$specific_field['name']] = $default_values;
1797
            }
1798
        }
1799
1800
        $form->addHidden('lp_id', $lpId);
1801
        $form->addButtonSave(get_lang('SaveLink'), 'submitLink');
1802
        $form->setDefaults($defaults);
1803
1804
        return $form;
1805
    }
1806
1807
    /**
1808
     * @param int $id
1809
     * @param string $action
1810
     *
1811
     * @return FormValidator
1812
     */
1813
    public static function getCategoryForm($id, $action)
1814
    {
1815
        $form = new FormValidator(
1816
            'category',
1817
            'post',
1818
            api_get_self().'?action='.$action.'&'.api_get_cidreq()
1819
        );
1820
1821
        $defaults = [];
1822
        if ($action == 'addcategory') {
1823
            $form->addHeader(get_lang('CategoryAdd'));
1824
            $my_cat_title = get_lang('CategoryAdd');
1825
        } else {
1826
            $form->addHeader(get_lang('CategoryMod'));
1827
            $my_cat_title = get_lang('CategoryMod');
1828
            $defaults = self::getCategory($id);
1829
        }
1830
        $form->addHidden('id', $id);
1831
        $form->addText('category_title', get_lang('CategoryName'));
1832
        $form->addTextarea('description', get_lang('Description'));
1833
        $form->addButtonSave($my_cat_title, 'submitCategory');
1834
        $form->setDefaults($defaults);
1835
1836
        return $form;
1837
    }
1838
1839
    /**
1840
     * @param int $id
1841
     * @return array
1842
     */
1843
    public static function getCategory($id)
1844
    {
1845
        $table = Database::get_course_table(TABLE_LINK_CATEGORY);
1846
        $id = intval($id);
1847
        $courseId = api_get_course_int_id();
1848
1849
        if (empty($id) || empty($courseId)) {
1850
            return [];
1851
        }
1852
        $sql = "SELECT * FROM $table 
1853
                WHERE id = $id AND c_id = $courseId";
1854
        $result = Database::query($sql);
1855
        $category = Database::fetch_array($result, 'ASSOC');
1856
1857
        return $category;
1858
    }
1859
1860
    /**
1861
     * Move a link inside its category (display_order field)
1862
     * @param int $id The link ID
1863
     * @param string $direction The direction to sort the links
1864
     * @return bool
1865
     */
1866
    private static function moveLinkDisplayOrder($id, $direction)
1867
    {
1868
        $em = Database::getManager();
1869
        /** @var CLink $link */
1870
        $link = $em->find('ChamiloCourseBundle:CLink', $id);
1871
1872
        if (!$link) {
1873
            return false;
1874
        }
1875
1876
        $compareLinks = $em
1877
            ->getRepository('ChamiloCourseBundle:CLink')
1878
            ->findBy(
1879
                [
1880
                    'cId' => $link->getCId(),
1881
                    'categoryId' => $link->getCategoryId()
1882
                ],
1883
                ['displayOrder' => $direction]
1884
            );
1885
1886
        /** @var CLink $prevLink */
1887
        $prevLink = null;
1888
1889
        /** @var CLink $compareLink */
1890
        foreach ($compareLinks as $compareLink) {
1891
            if ($compareLink->getId() !== $link->getId()) {
1892
                $prevLink = $compareLink;
1893
1894
                continue;
1895
            }
1896
1897
            if (!$prevLink) {
1898
                return false;
1899
            }
1900
1901
            $newPrevLinkDisplayOrder = $link->getDisplayOrder();
1902
            $newLinkDisplayOrder = $prevLink->getDisplayOrder();
1903
1904
            $link->setDisplayOrder($newLinkDisplayOrder);
1905
            $prevLink->setDisplayOrder($newPrevLinkDisplayOrder);
1906
1907
            $em->merge($prevLink);
1908
            $em->merge($link);
1909
            break;
1910
        }
1911
1912
        $em->flush();
1913
1914
        return true;
1915
    }
1916
1917
    /**
1918
     * Move a link up in its category
1919
     * @param int $id
1920
     * @return bool
1921
     */
1922
    public static function moveLinkUp($id)
1923
    {
1924
        return self::moveLinkDisplayOrder($id, 'ASC');
1925
    }
1926
1927
    /**
1928
     * Move a link down in its category
1929
     * @param int $id
1930
     * @return bool
1931
     */
1932
    public static function moveLinkDown($id)
1933
    {
1934
        return self::moveLinkDisplayOrder($id, 'DESC');
1935
    }
1936
1937
    /**
1938
     * @param string $url
1939
     * @return bool
1940
     */
1941
    public static function checkUrl($url)
1942
    {
1943
        // Check if curl is available.
1944
        if (!in_array('curl', get_loaded_extensions())) {
1945
            return false;
1946
        }
1947
1948
        // set URL and other appropriate options
1949
        $defaults = array(
1950
            CURLOPT_URL => $url,
1951
            CURLOPT_FOLLOWLOCATION => true, // follow redirects accept youtube.com
1952
            CURLOPT_HEADER => 0,
1953
            CURLOPT_RETURNTRANSFER => true,
1954
            CURLOPT_TIMEOUT => 4
1955
        );
1956
1957
        $proxySettings = api_get_configuration_value('proxy_settings');
1958
1959
        if (!empty($proxySettings) &&
1960
            isset($proxySettings['curl_setopt_array'])
1961
        ) {
1962
             $defaults[CURLOPT_PROXY] = $proxySettings['curl_setopt_array']['CURLOPT_PROXY'];
1963
             $defaults[CURLOPT_PROXYPORT] = $proxySettings['curl_setopt_array']['CURLOPT_PROXYPORT'];
1964
        }
1965
1966
        // Create a new cURL resource
1967
        $ch = curl_init();
1968
        curl_setopt_array($ch, $defaults);
1969
1970
        // grab URL and pass it to the browser
1971
        ob_start();
1972
        $result = curl_exec($ch);
1973
        ob_get_clean();
1974
1975
        // close cURL resource, and free up system resources
1976
        curl_close($ch);
1977
1978
        return $result;
1979
    }
1980
}
1981