Passed
Push — master ( 8d44d5...90cb87 )
by Yannick
09:10 queued 13s
created

AbstractLink::delete_linked_data()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\GradebookCategory;
5
use Chamilo\CoreBundle\Entity\GradebookLink;
6
7
/**
8
 * Class AbstractLink
9
 * Defines a gradebook AbstractLink object.
10
 * To implement specific links,
11
 * extend this class and define a type in LinkFactory.
12
 * Use the methods in LinkFactory to create link objects.
13
 *
14
 * @author Bert Steppé
15
 * @author Julio Montoya <[email protected]> security improvements
16
 */
17
abstract class AbstractLink implements GradebookItem
18
{
19
    public $course_id;
20
    public $studentList;
21
    /** @var GradebookLink */
22
    public $entity;
23
    protected $id;
24
    protected $type;
25
    protected $ref_id;
26
    protected $user_id;
27
    protected $course_code;
28
    /** @var Category */
29
    protected $category;
30
    protected $created_at;
31
    protected $weight;
32
    protected $visible;
33
    protected $session_id;
34
35
    /**
36
     * Constructor.
37
     */
38
    public function __construct()
39
    {
40
        $this->course_id = api_get_course_int_id();
41
    }
42
43
    /**
44
     * @return bool
45
     */
46
    abstract public function has_results();
47
48
    /**
49
     * @return string
50
     */
51
    abstract public function get_link();
52
53
    /**
54
     * @return bool
55
     */
56
    abstract public function is_valid_link();
57
58
    /**
59
     * @return string
60
     */
61
    abstract public function get_type_name();
62
63
    /**
64
     * @return bool
65
     */
66
    abstract public function needs_name_and_description();
67
68
    /**
69
     * @return bool
70
     */
71
    abstract public function needs_max();
72
73
    /**
74
     * @return bool
75
     */
76
    abstract public function needs_results();
77
78
    /**
79
     * @return bool
80
     */
81
    abstract public function is_allowed_to_change_name();
82
83
    /**
84
     * @return int
85
     */
86
    public function get_id()
87
    {
88
        return $this->id;
89
    }
90
91
    /**
92
     * @return string
93
     */
94
    public function get_type()
95
    {
96
        return $this->type;
97
    }
98
99
    /**
100
     * @return int
101
     */
102
    public function get_ref_id()
103
    {
104
        return (int) $this->ref_id;
105
    }
106
107
    /**
108
     * @return int
109
     */
110
    public function get_session_id()
111
    {
112
        return (int) $this->session_id;
113
    }
114
115
    /**
116
     * @return int
117
     */
118
    public function get_user_id()
119
    {
120
        return $this->user_id;
121
    }
122
123
    /**
124
     * @return string
125
     */
126
    public function get_course_code()
127
    {
128
        return $this->course_code;
129
    }
130
131
    /**
132
     * @return Category
133
     */
134
    public function getCategory()
135
    {
136
        return $this->category;
137
    }
138
139
    /**
140
     * @param Category $category
141
     */
142
    public function setCategory($category)
143
    {
144
        $this->category = $category;
145
    }
146
147
    /**
148
     * @return int
149
     */
150
    public function get_category_id()
151
    {
152
        return $this->category->get_id();
153
    }
154
155
    /**
156
     * @param int $category_id
157
     */
158
    public function set_category_id($category_id)
159
    {
160
        $categories = Category::load($category_id);
161
        if (isset($categories[0])) {
162
            $this->setCategory($categories[0]);
163
        }
164
    }
165
166
    public function get_date()
167
    {
168
        return $this->created_at;
169
    }
170
171
    public function get_weight()
172
    {
173
        return $this->weight;
174
    }
175
176
    public function is_locked()
177
    {
178
        return isset($this->locked) && 1 == $this->locked ? true : false;
179
    }
180
181
    public function is_visible()
182
    {
183
        return $this->visible;
184
    }
185
186
    public function set_id($id)
187
    {
188
        $this->id = $id;
189
    }
190
191
    public function set_type($type)
192
    {
193
        $this->type = $type;
194
    }
195
196
    public function set_ref_id($ref_id)
197
    {
198
        $this->ref_id = $ref_id;
199
    }
200
201
    public function set_user_id($user_id)
202
    {
203
        $this->user_id = $user_id;
204
    }
205
206
    /**
207
     * Set course ID and course code. If ID is empty, set both to null
208
     * @param ?int $courseId
209
     */
210
    public function setCourseId(?int $courseId = null): AbstractLink {
211
        $courseInfo = api_get_course_info_by_id($courseId);
212
        if (!empty($courseInfo)) {
213
            $this->course_code = $courseInfo['code'];
214
            $this->course_id = $courseId;
215
        } else {
216
            $this->course_code = null;
217
            $this->course_id = null;
218
        }
219
220
        return $this;
221
    }
222
223
    /**
224
     * @return array
225
     */
226
    public function getStudentList()
227
    {
228
        if (empty($this->studentList)) {
229
            return [];
230
        }
231
232
        return $this->studentList;
233
    }
234
235
    /**
236
     * @param array $list
237
     */
238
    public function setStudentList($list)
239
    {
240
        $this->studentList = $list;
241
    }
242
243
    public function set_date($date)
244
    {
245
        $this->created_at = $date;
246
    }
247
248
    public function set_weight($weight)
249
    {
250
        $this->weight = $weight;
251
    }
252
253
    public function set_visible($visible)
254
    {
255
        $this->visible = $visible;
256
    }
257
258
    /**
259
     * @param int $id
260
     */
261
    public function set_session_id($id)
262
    {
263
        $this->session_id = $id;
264
    }
265
266
    /**
267
     * @param $locked
268
     */
269
    public function set_locked($locked)
270
    {
271
        $this->locked = $locked;
272
    }
273
274
    /**
275
     * @return int
276
     */
277
    public function getCourseId()
278
    {
279
        return (int) $this->course_id;
280
    }
281
282
    /**
283
     * Retrieve links and return them as an array of extensions of AbstractLink.
284
     * To keep consistency, do not call this method but LinkFactory::load instead.
285
     *
286
     * @param int    $id
287
     * @param int    $type
288
     * @param int    $ref_id
289
     * @param int    $user_id
290
     * @param ?int    $courseId
291
     * @param int    $category_id
292
     * @param int    $visible
293
     *
294
     * @return array
295
     */
296
    public static function load(
297
        $id = null,
298
        $type = null,
299
        $ref_id = null,
300
        $user_id = null,
301
        ?int $courseId = null,
302
        $category_id = null,
303
        $visible = null
304
    ) {
305
        $tbl_grade_links = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
306
        $sql = 'SELECT * FROM '.$tbl_grade_links;
307
        $paramcount = 0;
308
        if (isset($id)) {
309
            $sql .= ' WHERE id = '.intval($id);
310
            $paramcount++;
311
        }
312
        if (isset($type)) {
313
            if (0 != $paramcount) {
314
                $sql .= ' AND';
315
            } else {
316
                $sql .= ' WHERE';
317
            }
318
            $sql .= ' type = '.intval($type);
319
            $paramcount++;
320
        }
321
        if (isset($ref_id)) {
322
            if (0 != $paramcount) {
323
                $sql .= ' AND';
324
            } else {
325
                $sql .= ' WHERE';
326
            }
327
            $sql .= ' ref_id = '.intval($ref_id);
328
            $paramcount++;
329
        }
330
        if (isset($user_id)) {
331
            if (0 != $paramcount) {
332
                $sql .= ' AND';
333
            } else {
334
                $sql .= ' WHERE';
335
            }
336
            $sql .= ' user_id = '.intval($user_id);
337
            $paramcount++;
338
        }
339
        if (!empty($courseId)) {
340
            if (0 != $paramcount) {
341
                $sql .= ' AND';
342
            } else {
343
                $sql .= ' WHERE';
344
            }
345
            $sql .= " c_id = $courseId";
346
            $paramcount++;
347
        }
348
        if (isset($category_id)) {
349
            if (0 != $paramcount) {
350
                $sql .= ' AND';
351
            } else {
352
                $sql .= ' WHERE';
353
            }
354
            $sql .= ' category_id = '.intval($category_id);
355
            $paramcount++;
356
        }
357
        if (isset($visible)) {
358
            if (0 != $paramcount) {
359
                $sql .= ' AND';
360
            } else {
361
                $sql .= ' WHERE';
362
            }
363
            $sql .= ' visible = '.intval($visible);
364
        }
365
366
        $result = Database::query($sql);
367
        $links = self::create_objects_from_sql_result($result);
368
369
        return $links;
370
    }
371
372
    /**
373
     * Insert this link into the database.
374
     * @return int 0 on error, or the link's database id
375
     * @throws Exception
376
     */
377
    public function add(): int
378
    {
379
        $this->add_linked_data();
380
        if (!empty($this->type) &&
381
            !empty($this->ref_id) &&
382
            !empty($this->user_id) &&
383
            !empty($this->course_id) &&
384
            !empty($this->category)
385
        ) {
386
            $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
387
            $sql = "SELECT count(*) count FROM $table
388
                    WHERE
389
                        ref_id = ".$this->get_ref_id()." AND
390
                        category_id =  ".$this->category->get_id()." AND
391
                        c_id = '".$this->course_id."' AND
392
                        type =  ".$this->type." ";
393
394
            $result = Database::query($sql);
395
            $row = Database::fetch_assoc($result);
396
397
            if (0 == $row['count']) {
398
                $em = Database::getManager();
399
                $category = null;
400
                if (!empty($this->get_category_id())) {
401
                    $category = $em->getRepository(GradebookCategory::class)->find($this->get_category_id());
402
                }
403
404
                $link = new GradebookLink();
405
                $link
406
                    ->setType($this->get_type())
407
                    ->setVisible($this->is_visible())
408
                    ->setWeight(api_float_val($this->get_weight()))
409
                    ->setUser(api_get_user_entity($this->get_user_id()))
410
                    ->setRefId($this->get_ref_id())
411
                    ->setCategory($category)
412
                    ->setCourse(api_get_course_entity($this->course_id))
413
                ;
414
                $em->persist($link);
415
                $em->flush();
416
417
                $this->set_id($link->getId());
418
419
                return $link->getId();
420
            }
421
        }
422
423
        return 0;
424
    }
425
426
    /**
427
     * Update the properties of this link in the database.
428
     */
429
    public function save()
430
    {
431
        $em = Database::getManager();
432
        $link = $em->find(GradebookLink::class, $this->id);
433
434
        if (!$link) {
435
            return;
436
        }
437
438
        self::add_link_log($this->id);
439
        $this->save_linked_data();
440
        $course = api_get_course_entity($this->getCourseId());
441
442
        $category = null;
443
        if (!empty($this->get_category_id())) {
444
            $category = $em->getRepository(GradebookCategory::class)->find($this->get_category_id());
445
        }
446
447
        $link
448
            ->setType($this->get_type())
449
            ->setRefId($this->get_ref_id())
450
            ->setUser(api_get_user_entity($this->get_user_id()))
451
            ->setCourse($course)
452
            ->setCategory($category)
453
            ->setWeight($this->get_weight())
454
            ->setVisible($this->is_visible())
455
        ;
456
457
        $em->persist($link);
458
        $em->flush();
459
    }
460
461
    /**
462
     * @param int $evaluationId
463
     */
464
    public static function add_link_log($evaluationId, $nameLog = null)
465
    {
466
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINKEVAL_LOG);
467
        $dateobject = self::load($evaluationId, null, null, null, null);
468
        $now = api_get_utc_datetime();
469
        $arreval = get_object_vars($dateobject[0]);
470
        $description_log = isset($arreval['description']) ? $arreval['description'] : '';
471
        if (empty($nameLog)) {
472
            if (isset($_POST['name_link'])) {
473
                $name_log = isset($_POST['name_link']) ? $_POST['name_link'] : $arreval['course_id'];
474
            } elseif (isset($_POST['link_'.$evaluationId]) && $_POST['link_'.$evaluationId]) {
475
                $name_log = $_POST['link_'.$evaluationId];
476
            } else {
477
                $name_log = $arreval['course_id'];
478
            }
479
        } else {
480
            $name_log = $nameLog;
481
        }
482
483
        $params = [
484
            'id_linkeval_log' => $arreval['id'],
485
            'title' => $name_log,
486
            'description' => $description_log,
487
            'created_at' => $now,
488
            'weight' => $arreval['weight'],
489
            'visible' => $arreval['visible'],
490
            'type' => 'Link',
491
            'user_id_log' => api_get_user_id(),
492
        ];
493
        Database::insert($table, $params);
494
    }
495
496
    /**
497
     * Delete this link from the database.
498
     */
499
    public function delete()
500
    {
501
        $this->delete_linked_data();
502
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
503
        $sql = 'DELETE FROM '.$table.'
504
                WHERE id = '.intval($this->id);
505
        Database::query($sql);
506
    }
507
508
    /**
509
     * Generate an array of possible categories where this link can be moved to.
510
     * Notice: its own parent will be included in the list: it's up to the frontend
511
     * to disable this element.
512
     *
513
     * @return array 2-dimensional array - every element contains 3 subelements (id, name, level)
514
     */
515
    public function get_target_categories()
516
    {
517
        // links can only be moved to categories inside this course
518
        $targets = [];
519
        $level = 0;
520
        $categories = Category::load(null, null, $this->course_id, 0);
521
        foreach ($categories as $cat) {
522
            $targets[] = [$cat->get_id(), $cat->get_name(), $level + 1];
523
            $targets = $this->addTargetSubcategories(
524
                $targets,
525
                $level + 1,
526
                $cat->get_id()
527
            );
528
        }
529
530
        return $targets;
531
    }
532
533
    /**
534
     * Move this link to the given category.
535
     * If this link moves to outside a course, delete it.
536
     */
537
    public function move_to_cat(GradebookCategory $cat)
538
    {
539
        if ($this->getCourseId() != $cat->getCourse()->getId()) {
540
            $this->delete();
541
        } else {
542
            $this->set_category_id($cat->getId());
543
            $this->save();
544
        }
545
    }
546
547
    /**
548
     * Find links by name
549
     * To keep consistency, do not call this method but LinkFactory::find_links instead.
550
     *
551
     * @todo can be written more efficiently using a new (but very complex) sql query
552
     *
553
     * @param string $name_mask
554
     *
555
     * @return array
556
     */
557
    public static function find_links($name_mask, $selectcat)
558
    {
559
        $rootcat = Category::load($selectcat);
560
        $links = $rootcat[0]->get_links((api_is_allowed_to_edit() ? null : api_get_user_id()), true);
561
        $foundlinks = [];
562
        foreach ($links as $link) {
563
            if (!(false === api_strpos(api_strtolower($link->get_name()), api_strtolower($name_mask)))) {
564
                $foundlinks[] = $link;
565
            }
566
        }
567
568
        return $foundlinks;
569
    }
570
571
    /**
572
     * @return string
573
     */
574
    public function get_item_type()
575
    {
576
        return 'L';
577
    }
578
579
    /**
580
     * @return string
581
     */
582
    public function get_icon_name()
583
    {
584
        return 'link';
585
    }
586
587
    public function get_all_links()
588
    {
589
        return [];
590
    }
591
592
    public function add_linked_data()
593
    {
594
    }
595
596
    public function save_linked_data()
597
    {
598
    }
599
600
    public function delete_linked_data()
601
    {
602
    }
603
604
    /**
605
     * @param string $name
606
     */
607
    public function set_name($name)
608
    {
609
    }
610
611
    /**
612
     * @param string $description
613
     */
614
    public function set_description($description)
615
    {
616
    }
617
618
    /**
619
     * @param int $max
620
     */
621
    public function set_max($max)
622
    {
623
    }
624
625
    public function get_view_url($stud_id)
626
    {
627
        return null;
628
    }
629
630
    /**
631
     * Locks a link.
632
     *
633
     * @param int $locked 1 or unlocked 0
634
     *
635
     * */
636
    public function lock($locked)
637
    {
638
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
639
        $sql = "UPDATE $table SET locked = '".intval($locked)."'
640
                WHERE id='".$this->id."'";
641
        Database::query($sql);
642
    }
643
644
    /**
645
     * Get current user ranking.
646
     *
647
     * @param int   $userId
648
     * @param array $studentList Array with user id and scores
649
     *                           Example: [1 => 5.00, 2 => 8.00]
650
     *
651
     * @return array
652
     */
653
    public static function getCurrentUserRanking($userId, $studentList)
654
    {
655
        $ranking = null;
656
        $currentUserId = $userId;
657
        if (!empty($studentList) && !empty($currentUserId)) {
658
            $studentList = array_map('floatval', $studentList);
659
            asort($studentList);
660
            $ranking = $count = count($studentList);
661
662
            foreach ($studentList as $userId => $position) {
0 ignored issues
show
introduced by
$userId is overwriting one of the parameters of this function.
Loading history...
663
                if ($currentUserId == $userId) {
664
                    break;
665
                }
666
                $ranking--;
667
            }
668
669
            // If no ranking was detected.
670
            if (0 == $ranking) {
671
                return [];
672
            }
673
674
            return [$ranking, $count];
675
        }
676
677
        return [];
678
    }
679
680
    /**
681
     * @return string
682
     */
683
    public function getSkillsFromItem()
684
    {
685
        $toolType = '';
686
        switch ($this->type) {
687
            case LINK_ATTENDANCE:
688
                $toolType = ITEM_TYPE_ATTENDANCE;
689
                break;
690
            case LINK_EXERCISE:
691
                $toolType = ITEM_TYPE_EXERCISE;
692
                break;
693
            case LINK_FORUM_THREAD:
694
                $toolType = ITEM_TYPE_FORUM_THREAD;
695
                break;
696
            case LINK_LEARNPATH:
697
                $toolType = ITEM_TYPE_LEARNPATH;
698
                break;
699
            case LINK_HOTPOTATOES:
700
                $toolType = ITEM_TYPE_HOTPOTATOES;
701
                break;
702
            case LINK_STUDENTPUBLICATION:
703
                $toolType = ITEM_TYPE_STUDENT_PUBLICATION;
704
                break;
705
            case LINK_SURVEY:
706
                $toolType = ITEM_TYPE_SURVEY;
707
                break;
708
        }
709
710
        $skillToString = SkillModel::getSkillRelItemsToString($toolType, $this->get_ref_id());
711
712
        return $skillToString;
713
    }
714
715
    /**
716
     * @param int $itemId
717
     * @param int $linkType
718
     * @param int $courseId
719
     * @param int $sessionId
720
     *
721
     * @return array
722
     * @throws Exception
723
     */
724
    public static function getGradebookLinksFromItem(
725
        int $itemId,
726
        int $linkType,
727
        int $courseId,
728
        ?int $sessionId = 0
729
    ): array
730
    {
731
        if (empty($courseId) || empty($itemId) || empty($linkType)) {
732
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the type-hinted return array.
Loading history...
733
        }
734
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
735
        $tableCategory = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
736
        $sessionId = (int) $sessionId;
737
738
        $sessionCondition = api_get_session_condition($sessionId, true, false, 'c.session_id');
739
740
        $sql = "SELECT DISTINCT l.*
741
                FROM $table l INNER JOIN $tableCategory c
742
                ON (c.c_id = l.c_id AND c.id = l.category_id)
743
                WHERE
744
                    ref_id = $itemId AND
745
                    type = $linkType AND
746
                    l.c_id = $courseId
747
                    $sessionCondition ";
748
749
        $result = Database::query($sql);
750
        if (Database::num_rows($result)) {
751
            return Database::store_result($result);
752
        }
753
754
        return [];
755
    }
756
757
    /**
758
     * @param Doctrine\DBAL\Driver\Statement|null $result
759
     *
760
     * @return array
761
     */
762
    private static function create_objects_from_sql_result($result)
763
    {
764
        $links = [];
765
        $allow = ('true' === api_get_setting('gradebook.allow_gradebook_stats'));
766
        if ($allow) {
767
            $em = Database::getManager();
768
            $repo = $em->getRepository(GradebookLink::class);
769
        }
770
771
        while ($data = Database::fetch_array($result)) {
772
            $link = LinkFactory::create($data['type']);
773
            $link->set_id($data['id']);
774
            $link->set_type($data['type']);
775
            $link->set_ref_id($data['ref_id']);
776
            $link->set_user_id($data['user_id']);
777
            $link->setCourseId(api_get_course_int_id());
778
            $link->set_category_id($data['category_id']);
779
            $link->set_date($data['created_at']);
780
            $link->set_weight($data['weight']);
781
            $link->set_visible($data['visible']);
782
            $link->set_locked($data['locked']);
783
784
            //session id should depend on the category --> $data['category_id']
785
            $session_id = api_get_session_id();
786
            $link->set_session_id($session_id);
787
788
            if ($allow) {
789
                $link->entity = $repo->find($data['id']);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $repo does not seem to be defined for all execution paths leading up to this point.
Loading history...
790
            }
791
            $links[] = $link;
792
        }
793
794
        return $links;
795
    }
796
797
    /**
798
     * Internal function used by get_target_categories().
799
     *
800
     * @param array $targets
801
     * @param int   $level
802
     * @param int   $catid
803
     *
804
     * @return array
805
     */
806
    private function addTargetSubcategories($targets, $level, $catid)
807
    {
808
        $subcats = Category::load(null, null, 0, $catid);
809
        foreach ($subcats as $cat) {
810
            $targets[] = [$cat->get_id(), $cat->get_name(), $level + 1];
811
            $targets = $this->addTargetSubcategories(
812
                $targets,
813
                $level + 1,
814
                $cat->get_id()
815
            );
816
        }
817
818
        return $targets;
819
    }
820
}
821