Passed
Push — 1.11.x ( d9a004...d1dcf0 )
by
unknown
09:54
created

AbstractLink::getCurrentUserRanking()   B

Complexity

Conditions 8
Paths 11

Size

Total Lines 30
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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