Passed
Push — master ( dc373e...baaca7 )
by Julito
11:31
created

Skill::addSkillsToForm()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 17
nc 3
nop 3
dl 0
loc 30
rs 8.5806
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\UserBundle\Entity\User;
5
use Chamilo\UserBundle\Entity\Repository\UserRepository;
6
use Fhaculty\Graph\Vertex;
7
use Fhaculty\Graph\Graph;
8
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
9
use Chamilo\SkillBundle\Entity\SkillRelItem;
10
11
/**
12
 * Class SkillProfile
13
 * @package chamilo.library
14
 */
15
class SkillProfile extends Model
16
{
17
    public $columns = ['id', 'name', 'description'];
18
19
    /**
20
     * Constructor
21
     */
22
    public function __construct()
23
    {
24
        $this->table = Database::get_main_table(TABLE_MAIN_SKILL_PROFILE);
25
        $this->table_rel_profile = Database::get_main_table(TABLE_MAIN_SKILL_REL_PROFILE);
26
    }
27
28
    /**
29
     * @return array
30
     */
31
    public function getProfiles()
32
    {
33
        $sql = "SELECT * FROM $this->table p
34
                INNER JOIN $this->table_rel_profile sp
35
                ON(p.id = sp.profile_id) ";
36
        $result = Database::query($sql);
37
        $profiles = Database::store_result($result, 'ASSOC');
38
39
        return $profiles;
40
    }
41
42
    /**
43
     * This function is for editing profile info from profile_id.
44
     * @param int    $profileId
45
     * @param string $name
46
     * @param string $description
47
     * @return bool
48
     */
49
    public function updateProfileInfo($profileId, $name, $description)
50
    {
51
        $profileId = (int) $profileId;
52
53
        if (empty($profileId)) {
54
            return false;
55
        }
56
57
        $name = Database::escape_string($name);
58
        $description = Database::escape_string($description);
59
60
        $sql = "UPDATE $this->table SET
61
                    name = '$name',
62
                    description = '$description'
63
                WHERE id = $profileId ";
64
        Database::query($sql);
65
66
        return true;
67
    }
68
69
    /**
70
     * Call the save method of the parent class and the SkillRelProfile object
71
     * @param array $params
72
     * @param bool $show_query Whether to show the query in parent save() method
73
     *
74
     * @return mixed Profile ID or false if incomplete params
75
     */
76
    public function save($params, $show_query = false)
77
    {
78
        if (!empty($params)) {
79
            $profile_id = parent::save($params, $show_query);
80
            if ($profile_id) {
81
                $skill_rel_profile = new SkillRelProfile();
82
                if (isset($params['skills'])) {
83
                    foreach ($params['skills'] as $skill_id) {
84
                        $attributes = [
85
                            'skill_id' => $skill_id,
86
                            'profile_id' => $profile_id,
87
                        ];
88
                        $skill_rel_profile->save($attributes);
89
                    }
90
                }
91
                return $profile_id;
92
            }
93
        }
94
95
        return false;
96
    }
97
98
    /**
99
     * Delete a skill profile
100
     * @param int $id The skill profile id
101
     * @return boolean Whether delete a skill profile
102
     */
103
    public function delete($id)
104
    {
105
        Database::delete(
106
            $this->table_rel_profile,
107
            [
108
                'profile_id' => $id,
109
            ]
110
        );
111
112
        return parent::delete($id);
113
    }
114
}
115
116
/**
117
 * Class SkillRelProfile
118
 */
119
class SkillRelProfile extends Model
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
120
{
121
    public $columns = ['id', 'skill_id', 'profile_id'];
122
123
    /**
124
     * Constructor
125
     */
126
    public function __construct()
127
    {
128
        $this->table = Database::get_main_table(TABLE_MAIN_SKILL_REL_PROFILE);
129
        $this->tableProfile = Database::get_main_table(TABLE_MAIN_SKILL_PROFILE);
130
    }
131
132
    /**
133
     * @param int $profileId
134
     * @return array
135
     */
136
    public function getSkillsByProfile($profileId)
137
    {
138
        $profileId = intval($profileId);
139
        $skills = $this->get_all(['where' => ['profile_id = ? ' => $profileId]]);
140
        $return = [];
141
        if (!empty($skills)) {
142
            foreach ($skills as $skill_data) {
143
                $return[] = $skill_data['skill_id'];
144
            }
145
        }
146
147
        return $return;
148
    }
149
150
    /**
151
     * This function is for getting profile info from profile_id.
152
     * @param int $profileId
153
     * @return array
154
     */
155
    public function getProfileInfo($profileId)
156
    {
157
        $sql = "SELECT * FROM $this->table p
158
                INNER JOIN $this->tableProfile pr
159
                ON (pr.id = p.profile_id)
160
                WHERE p.profile_id = ".intval($profileId);
161
        $result = Database::query($sql);
162
        $profileData = Database::fetch_array($result, 'ASSOC');
163
164
        return $profileData;
165
    }
166
}
167
168
/**
169
 * Class SkillRelSkill
170
 */
171
class SkillRelSkill extends Model
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
172
{
173
    public $columns = ['skill_id', 'parent_id', 'relation_type', 'level'];
174
175
    /**
176
     * Constructor
177
     */
178
    public function __construct()
179
    {
180
        $this->table = Database::get_main_table(TABLE_MAIN_SKILL_REL_SKILL);
181
        $this->tableSkill = Database::get_main_table(TABLE_MAIN_SKILL);
182
    }
183
184
    /**
185
     * Gets an element
186
     * @param int $id
187
     * @return array
188
     */
189
    public function getSkillInfo($id)
190
    {
191
        if (empty($id)) {
192
            return [];
193
        }
194
        $result = Database::select(
195
            '*',
196
            $this->table,
197
            ['where' => ['skill_id = ?' => intval($id)]],
198
            'first'
199
        );
200
201
        return $result;
202
    }
203
204
    /**
205
     * @param int $skillId
206
     * @param bool $add_child_info
207
     * @return array
208
     */
209
    public function getSkillParents($skillId, $add_child_info = true)
210
    {
211
        $skillId = intval($skillId);
212
        $sql = 'SELECT child.* FROM '.$this->table.' child
213
                LEFT JOIN '.$this->table.' parent
214
                ON child.parent_id = parent.skill_id
215
                WHERE child.skill_id = '.$skillId.' ';
216
        $result = Database::query($sql);
217
        $skill = Database::store_result($result, 'ASSOC');
218
        $skill = isset($skill[0]) ? $skill[0] : null;
219
220
        $parents = [];
221
        if (!empty($skill)) {
222
            if ($skill['parent_id'] != null) {
223
                $parents = self::getSkillParents($skill['parent_id']);
224
            }
225
            if ($add_child_info) {
226
                $parents[] = $skill;
227
            }
228
        }
229
        return $parents;
230
    }
231
232
    /**
233
     * @param int $skillId
234
     * @return array
235
     */
236
    public function getDirectParents($skillId)
237
    {
238
        $skillId = (int) $skillId;
239
        $sql = 'SELECT parent_id as skill_id 
240
                FROM '.$this->table.'
241
                WHERE skill_id = '.$skillId;
242
        $result = Database::query($sql);
243
        $skill = Database::store_result($result, 'ASSOC');
244
        $skill = isset($skill[0]) ? $skill[0] : null;
245
        $parents = [];
246
        if (!empty($skill)) {
247
            $parents[] = $skill;
248
        }
249
250
        return $parents;
251
    }
252
253
    /**
254
     * @param int $skill_id
255
     * @param bool $load_user_data
256
     * @param bool $user_id
257
     * @return array
258
     */
259
    public function getChildren(
260
        $skill_id,
261
        $load_user_data = false,
262
        $user_id = false,
263
        $order = ''
264
    ) {
265
        $skill_id = (int) $skill_id;
266
        $sql = 'SELECT parent.* FROM '.$this->tableSkill.' skill
267
                INNER JOIN '.$this->table.' parent
268
                ON parent.id = skill.id
269
                WHERE parent_id = '.$skill_id.'
270
                ORDER BY skill.name ASC';
271
        $result = Database::query($sql);
272
        $skills = Database::store_result($result, 'ASSOC');
273
274
        $skill_obj = new Skill();
275
        $skill_rel_user = new SkillRelUser();
276
277
        if ($load_user_data) {
278
            $passed_skills = $skill_rel_user->getUserSkills($user_id);
279
            $done_skills = [];
280
            foreach ($passed_skills as $done_skill) {
281
                $done_skills[] = $done_skill['skill_id'];
282
            }
283
        }
284
285
        if (!empty($skills)) {
286
            foreach ($skills as &$skill) {
287
                $skill['data'] = $skill_obj->get($skill['skill_id']);
288
                if (isset($skill['data']) && !empty($skill['data'])) {
289
                    if (!empty($done_skills)) {
290
                        $skill['data']['passed'] = 0;
291
                        if (in_array($skill['skill_id'], $done_skills)) {
292
                            $skill['data']['passed'] = 1;
293
                        }
294
                    }
295
                } else {
296
                    $skill = null;
297
                }
298
            }
299
        }
300
301
        return $skills;
302
    }
303
304
    /**
305
     * @param array $params
306
     * @return bool
307
     */
308
    public function updateBySkill($params)
309
    {
310
        $result = Database::update(
311
            $this->table,
312
            $params,
313
            ['skill_id = ? ' => $params['skill_id']]
314
        );
315
        if ($result) {
316
            return true;
317
        }
318
319
        return false;
320
    }
321
322
    /**
323
     * @param int $skill_id
324
     * @param int $parent_id
325
     * @return bool
326
     */
327
    public function relationExists($skill_id, $parent_id)
328
    {
329
        $result = $this->find(
330
            'all',
331
            [
332
                'where' => [
333
                    'skill_id = ? AND parent_id = ?' => [
334
                        $skill_id,
335
                        $parent_id,
336
                    ],
337
                ],
338
            ]
339
        );
340
341
        if (!empty($result)) {
342
            return true;
343
        }
344
        return false;
345
    }
346
}
347
348
/**
349
 * Class SkillRelGradebook
350
 */
351
class SkillRelGradebook extends Model
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
352
{
353
    public $columns = ['id', 'gradebook_id', 'skill_id'];
354
355
    /**
356
     * SkillRelGradebook constructor.
357
     */
358
    public function __construct()
359
    {
360
        $this->table = Database::get_main_table(TABLE_MAIN_SKILL_REL_GRADEBOOK);
361
    }
362
363
    /**
364
     * @param int $gradebookId
365
     * @param int $skillId
366
     * @return bool
367
     */
368
    public function existsGradeBookSkill($gradebookId, $skillId)
369
    {
370
        $result = $this->find(
371
            'all',
372
            [
373
                'where' => [
374
                    'gradebook_id = ? AND skill_id = ?' => [
375
                        $gradebookId,
376
                        $skillId,
377
                    ],
378
                ],
379
            ]
380
        );
381
        if (!empty($result)) {
382
            return true;
383
        }
384
        return false;
385
    }
386
387
    /**
388
     * Gets an element
389
     */
390
    public function getSkillInfo($skill_id, $gradebookId)
391
    {
392
        if (empty($skill_id)) {
393
            return [];
394
        }
395
        $result = Database::select(
396
            '*',
397
            $this->table,
398
            [
399
                'where' => [
400
                    'skill_id = ? AND gradebook_id = ? ' => [
401
                        $skill_id,
402
                        $gradebookId,
403
                    ],
404
                ],
405
            ],
406
            'first'
407
        );
408
        return $result;
409
    }
410
411
    /**
412
     * @param int $skill_id
413
     * @param array $gradebook_list
414
     */
415
    public function updateGradeBookListBySkill($skill_id, $gradebook_list)
416
    {
417
        $original_gradebook_list = $this->find(
418
            'all',
419
            ['where' => ['skill_id = ?' => [$skill_id]]]
420
        );
421
        $gradebooks_to_remove = [];
422
        $gradebooks_to_add = [];
423
        $original_gradebook_list_ids = [];
424
425
        if (!empty($original_gradebook_list)) {
426
            foreach ($original_gradebook_list as $gradebook) {
427
                if (!in_array($gradebook['gradebook_id'], $gradebook_list)) {
428
                    $gradebooks_to_remove[] = $gradebook['id'];
429
                }
430
            }
431
            foreach ($original_gradebook_list as $gradebook_item) {
432
                $original_gradebook_list_ids[] = $gradebook_item['gradebook_id'];
433
            }
434
        }
435
436
        if (!empty($gradebook_list)) {
437
            foreach ($gradebook_list as $gradebook_id) {
438
                if (!in_array($gradebook_id, $original_gradebook_list_ids)) {
439
                    $gradebooks_to_add[] = $gradebook_id;
440
                }
441
            }
442
        }
443
444
        if (!empty($gradebooks_to_remove)) {
445
            foreach ($gradebooks_to_remove as $id) {
446
                $this->delete($id);
447
            }
448
        }
449
450
        if (!empty($gradebooks_to_add)) {
451
            foreach ($gradebooks_to_add as $gradebook_id) {
452
                $attributes = [
453
                    'skill_id' => $skill_id,
454
                    'gradebook_id' => $gradebook_id,
455
                ];
456
                $this->save($attributes);
457
            }
458
        }
459
    }
460
461
    /**
462
     * @param array $params
463
     * @return bool|void
464
     */
465
    public function updateBySkill($params)
466
    {
467
        $skillInfo = $this->existsGradeBookSkill(
468
            $params['gradebook_id'],
469
            $params['skill_id']
470
        );
471
472
        if ($skillInfo) {
473
            return;
474
        } else {
475
            $result = $this->save($params);
476
        }
477
        if ($result) {
478
            return true;
479
        }
480
        return false;
481
    }
482
}
483
484
/**
485
 * Class SkillRelUser
486
 */
487
class SkillRelUser extends Model
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
488
{
489
    public $columns = [
490
        'id',
491
        'user_id',
492
        'skill_id',
493
        'acquired_skill_at',
494
        'assigned_by',
495
        'course_id',
496
        'session_id',
497
    ];
498
499
    /**
500
     * Constructor
501
     */
502
    public function __construct()
503
    {
504
        $this->table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
505
    }
506
507
    /**
508
     * @param array $skill_list
509
     * @return array
510
     */
511
    public function getUserBySkills($skill_list)
512
    {
513
        $users = [];
514
        if (!empty($skill_list)) {
515
            $skill_list = array_map('intval', $skill_list);
516
            $skill_list = implode("', '", $skill_list);
517
518
            $sql = "SELECT user_id FROM {$this->table}
519
                    WHERE skill_id IN ('$skill_list') ";
520
521
            $result = Database::query($sql);
522
            $users  = Database::store_result($result, 'ASSOC');
523
        }
524
        return $users;
525
    }
526
527
    /**
528
     * Get the achieved skills for the user
529
     * @param int $userId
530
     * @param int $courseId Optional. The course id
531
     * @param int $sessionId Optional. The session id
532
     * @return array The skill list. Otherwise return false
533
     */
534
    public function getUserSkills($userId, $courseId = 0, $sessionId = 0)
535
    {
536
        if (empty($userId)) {
537
            return [];
538
        }
539
540
        $courseId = intval($courseId);
541
        $sessionId = $sessionId ? intval($sessionId) : null;
542
        $whereConditions = [
543
            'user_id = ? ' => intval($userId),
544
        ];
545
546
        if ($courseId > 0) {
547
            $whereConditions['AND course_id = ? '] = $courseId;
548
            $whereConditions['AND session_id = ?'] = $sessionId;
549
        }
550
551
        $result = Database::select(
552
            'skill_id',
553
            $this->table,
554
            [
555
                'where' => $whereConditions,
556
            ],
557
            'all'
558
        );
559
        return $result;
560
    }
561
562
    /**
563
     * Get the relation data between user and skill
564
     * @param int $userId The user id
565
     * @param int $skillId The skill id
566
     * @param int $courseId The course id
567
     * @param int $sessionId Optional. The session id
568
     * @return array The relation data. Otherwise return false
569
     */
570
    public function getByUserAndSkill($userId, $skillId, $courseId, $sessionId = 0)
571
    {
572
        $where = [
573
            'user_id = ? AND skill_id = ? AND course_id = ? AND session_id = ?' => [
574
                intval($userId),
575
                intval($skillId),
576
                intval($courseId),
577
                $sessionId ? intval($sessionId) : null,
578
            ],
579
        ];
580
581
        return Database::select('*', $this->table, [
582
            'where' => $where,
583
        ], 'first');
584
    }
585
}
586
587
/**
588
 * Class Skill
589
 */
590
class Skill extends Model
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
591
{
592
    public $columns = [
593
        'id',
594
        'name',
595
        'description',
596
        'access_url_id',
597
        'short_code',
598
        'icon',
599
        'criteria',
600
    ];
601
    public $required = ['name'];
602
603
    /** Array of colours by depth, for the coffee wheel. Each depth has 4 col */
604
    /*var $colours = array(
605
      0 => array('#f9f0ab', '#ecc099', '#e098b0', '#ebe378'),
606
      1 => array('#d5dda1', '#4a5072', '#8dae43', '#72659d'),
607
      2 => array('#b28647', '#2e6093', '#393e64', '#1e8323'),
608
      3 => array('#9f6652', '#9f6652', '#9f6652', '#9f6652'),
609
      4 => array('#af643c', '#af643c', '#af643c', '#af643c'),
610
      5 => array('#72659d', '#72659d', '#72659d', '#72659d'),
611
      6 => array('#8a6e9e', '#8a6e9e', '#8a6e9e', '#8a6e9e'),
612
      7 => array('#92538c', '#92538c', '#92538c', '#92538c'),
613
      8 => array('#2e6093', '#2e6093', '#2e6093', '#2e6093'),
614
      9 => array('#3a5988', '#3a5988', '#3a5988', '#3a5988'),
615
     10 => array('#393e64', '#393e64', '#393e64', '#393e64'),
616
    );*/
617
    public function __construct()
618
    {
619
        $this->table = Database::get_main_table(TABLE_MAIN_SKILL);
620
        $this->table_user = Database::get_main_table(TABLE_MAIN_USER);
621
        $this->table_skill_rel_gradebook = Database::get_main_table(TABLE_MAIN_SKILL_REL_GRADEBOOK);
622
        $this->table_skill_rel_user = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
623
        $this->table_course = Database::get_main_table(TABLE_MAIN_COURSE);
624
        $this->table_skill_rel_skill = Database::get_main_table(TABLE_MAIN_SKILL_REL_SKILL);
625
        $this->table_gradebook = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
626
        $this->sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
627
    }
628
629
    /**
630
     * Gets an element
631
     * @param int $id
632
     *
633
     * @return array|mixed
634
     */
635
    public function get($id)
636
    {
637
        $result = parent::get($id);
638
        if (empty($result)) {
639
            return [];
640
        }
641
642
        $path = api_get_path(WEB_UPLOAD_PATH).'badges/';
643
644
        if (!empty($result['icon'])) {
645
            $iconSmall = sprintf(
646
                "%s-small.png",
647
                sha1($result['name'])
648
            );
649
650
            $iconBig = sprintf(
651
                "%s.png",
652
                sha1($result['name'])
653
            );
654
655
            $iconMini = $path.$iconSmall;
656
            $iconSmall = $path.$iconSmall;
657
            $iconBig = $path.$iconBig;
658
        } else {
659
            $iconMini = Display::returnIconPath('badges-default.png', ICON_SIZE_MEDIUM);
660
            $iconSmall = Display::returnIconPath('badges-default.png', ICON_SIZE_BIG);
661
            $iconBig = Display::returnIconPath('badges-default.png', ICON_SIZE_HUGE);
662
        }
663
664
        $result['icon_mini'] = $iconMini;
665
        $result['icon_small'] = $iconSmall;
666
        $result['icon_big'] = $iconBig;
667
668
        $result['img_mini'] = Display::img($iconBig, $result['name'], ['width' => ICON_SIZE_MEDIUM]);
669
        $result['img_big'] = Display::img($iconBig, $result['name']);
670
        $result['img_small'] = Display::img($iconSmall, $result['name']);
671
        $result['name'] = self::translateName($result['name']);
672
        $result['short_code'] = self::translateCode($result['short_code']);
673
674
        return $result;
675
    }
676
677
    /**
678
     * @param array $skills
679
     * @param string $imageSize mini|small|big
680
     * @param bool $addDivWrapper
681
     * @return string
682
     */
683
    public function processSkillList($skills, $imageSize = '', $addDivWrapper = true)
684
    {
685
        if (empty($skills)) {
686
            return '';
687
        }
688
689
        if (empty($imageSize)) {
690
            $imageSize = 'img_small';
691
        } else {
692
            $imageSize = "img_$imageSize";
693
        }
694
695
        $html = '';
696
        if ($addDivWrapper) {
697
            $html = '<div class="scrollbar-inner badges-sidebar">';
698
        }
699
        $html .= '<ul class="list-unstyled list-badges">';
700
        foreach ($skills as $skill) {
701
            if (isset($skill['data'])) {
702
                $skill = $skill['data'];
703
            }
704
            $html .= '<li class="thumbnail">';
705
            $item = $skill[$imageSize];
706
            $item .= '<div class="caption">
707
                        <p class="text-center">'.$skill['name'].'</p>
708
                      </div>';
709
            if (isset($skill['url'])) {
710
                $html .= Display::url($item, $skill['url'], ['target' => '_blank']);
711
            } else {
712
                $html .= $item;
713
            }
714
            $html .= '</li>';
715
        }
716
        $html .= '</ul>';
717
718
        if ($addDivWrapper) {
719
            $html .= '</div>';
720
        }
721
722
        return $html;
723
    }
724
725
    /**
726
     * @param $skills
727
     * @param string $imageSize mini|small|big
728
     * @param string $style
729
     * @param bool $showBadge
730
     * @param bool $showTitle
731
     *
732
     * @return string
733
     */
734
    public function processSkillListSimple($skills, $imageSize = '', $style = '', $showBadge = true, $showTitle = true)
735
    {
736
        if (empty($skills)) {
737
            return '';
738
        }
739
740
        $isHierarchicalTable = api_get_configuration_value('table_of_hierarchical_skill_presentation');
741
742
        if (empty($imageSize)) {
743
            $imageSize = 'img_small';
744
        } else {
745
            $imageSize = "img_$imageSize";
746
        }
747
748
        $html = '';
749
        foreach ($skills as $skill) {
750
            if (isset($skill['data'])) {
751
                $skill = $skill['data'];
752
            }
753
754
            $item = '';
755
            if ($showBadge) {
756
                $item = $skill[$imageSize];
757
            }
758
759
            $name = $skill['name'];
760
            if (!empty($skill['short_code'])) {
761
                $name = $skill['short_code'];
762
            }
763
764
            if (!$isHierarchicalTable) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
765
                //$item .= '<br />';
766
            }
767
768
            if ($showTitle) {
769
                $item .= $name;
770
            }
771
772
            if (isset($skill['url'])) {
773
                $html .= Display::url($item, $skill['url'], ['target' => '_blank', 'style' => $style]);
774
            } else {
775
                $html .= Display::url($item, '#', ['target' => '_blank', 'style' => $style]);
776
            }
777
        }
778
779
        return $html;
780
    }
781
782
    /**
783
     * @param int $id
784
     * @return array
785
     */
786
    public function getSkillInfo($id)
787
    {
788
        $skillRelSkill = new SkillRelSkill();
789
        $skillInfo = $this->get($id);
790
        if (!empty($skillInfo)) {
791
            $skillInfo['extra'] = $skillRelSkill->getSkillInfo($id);
792
            $skillInfo['gradebooks'] = self::getGradebooksBySkill($id);
793
        }
794
        return $skillInfo;
795
    }
796
797
    /**
798
     * @param array $skill_list
799
     * @return array
800
     */
801
    public function getSkillsInfo($skill_list)
802
    {
803
        $skill_list = array_map('intval', $skill_list);
804
        $skill_list = implode("', '", $skill_list);
805
806
        $sql = "SELECT * FROM {$this->table}
807
                WHERE id IN ('$skill_list') ";
808
809
        $result = Database::query($sql);
810
        $skills  = Database::store_result($result, 'ASSOC');
811
812
        foreach ($skills as &$skill) {
813
            if (!$skill['icon']) {
814
                continue;
815
            }
816
817
            $skill['icon_small'] = sprintf(
818
                "badges/%s-small.png",
819
                sha1($skill['name'])
820
            );
821
            $skill['name'] = self::translateName($skill['name']);
822
            $skill['short_code'] = self::translateCode($skill['short_code']);
823
        }
824
825
        return $skills;
826
    }
827
828
    /**
829
     * @param bool $load_user_data
830
     * @param bool $user_id
831
     * @param int $id
832
     * @param int $parent_id
833
     * @return array
834
     */
835
    public function get_all(
836
        $load_user_data = false,
837
        $user_id = false,
838
        $id = null,
839
        $parent_id = null
840
    ) {
841
        $id_condition = '';
842
        if (!empty($id)) {
843
            $id = intval($id);
844
            $id_condition = " WHERE s.id = $id";
845
        }
846
847
        if (!empty($parent_id)) {
848
            $parent_id = intval($parent_id);
849
            if (empty($id_condition)) {
850
                $id_condition = " WHERE ss.parent_id = $parent_id";
851
            } else {
852
                $id_condition = " AND ss.parent_id = $parent_id";
853
            }
854
        }
855
856
        $sql = "SELECT
857
                    s.id,
858
                    s.name,
859
                    s.description,
860
                    ss.parent_id,
861
                    ss.relation_type,
862
                    s.icon,
863
                    s.short_code,
864
                    s.status
865
                FROM {$this->table} s
866
                INNER JOIN {$this->table_skill_rel_skill} ss
867
                ON (s.id = ss.skill_id) $id_condition
868
                ORDER BY ss.id, ss.parent_id";
869
870
        $result = Database::query($sql);
871
        $skills = [];
872
        $webPath = api_get_path(WEB_UPLOAD_PATH);
873
        if (Database::num_rows($result)) {
874
            while ($row = Database::fetch_array($result, 'ASSOC')) {
875
                $skillInfo = self::get($row['id']);
876
877
                $row['img_mini'] = $skillInfo['img_mini'];
878
                $row['img_big'] = $skillInfo['img_big'];
879
                $row['img_small'] = $skillInfo['img_small'];
880
881
                $row['name'] = self::translateName($row['name']);
882
                $row['short_code'] = self::translateCode($row['short_code']);
883
                $skillRelSkill = new SkillRelSkill();
884
                $parents = $skillRelSkill->getSkillParents($row['id']);
885
                $row['level'] = count($parents) - 1;
886
                $row['gradebooks'] = self::getGradebooksBySkill($row['id']);
887
                $skills[$row['id']] = $row;
888
            }
889
        }
890
891
        // Load all children of the parent_id
892
        if (!empty($skills) && !empty($parent_id)) {
893
            foreach ($skills as $skill) {
894
                $children = self::get_all($load_user_data, $user_id, $id, $skill['id']);
895
                if (!empty($children)) {
896
                    //$skills = array_merge($skills, $children);
897
                    $skills = $skills + $children;
898
                }
899
            }
900
        }
901
        return $skills;
902
    }
903
904
    /**
905
     * @param int $skill_id
906
     * @return array|resource
907
     */
908
    public function getGradebooksBySkill($skill_id)
909
    {
910
        $skill_id = intval($skill_id);
911
        $sql = "SELECT g.* FROM {$this->table_gradebook} g
912
                INNER JOIN {$this->table_skill_rel_gradebook} sg
913
                ON g.id = sg.gradebook_id
914
                WHERE sg.skill_id = $skill_id";
915
        $result = Database::query($sql);
916
        $result = Database::store_result($result, 'ASSOC');
917
        return $result;
918
    }
919
920
    /**
921
     * Get one level children
922
     *
923
     * @param int $skill_id
924
     * @param bool $load_user_data
925
     * @return array
926
     */
927
    public function getChildren($skill_id, $load_user_data = false)
928
    {
929
        $skillRelSkill = new SkillRelSkill();
930
        if ($load_user_data) {
931
            $user_id = api_get_user_id();
932
            $skills = $skillRelSkill->getChildren($skill_id, true, $user_id);
933
        } else {
934
            $skills = $skillRelSkill->getChildren($skill_id);
935
        }
936
        return $skills;
937
    }
938
939
    /**
940
     * Get all children of the current node (recursive)
941
     * @param int $skillId
942
     * @return array
943
     */
944
    public function getAllChildren($skillId)
945
    {
946
        $skillRelSkill = new SkillRelSkill();
947
        $children = $skillRelSkill->getChildren($skillId);
948
        foreach ($children as $child) {
949
            $subChildren = $this->getAllChildren($child['id']);
950
        }
951
952
        if (!empty($subChildren)) {
953
            $children = array_merge($children, $subChildren);
954
        }
955
956
        return $children;
957
    }
958
959
    /**
960
     * Gets all parents from from the wanted skill
961
     */
962
    public function get_parents($skillId)
963
    {
964
        $skillRelSkill = new SkillRelSkill();
965
        $skills = $skillRelSkill->getSkillParents($skillId, true);
966
        foreach ($skills as &$skill) {
967
            $skill['data'] = $this->get($skill['skill_id']);
968
        }
969
        return $skills;
970
    }
971
972
    /**
973
     * All direct parents
974
     * @param int $skillId
975
     * @return array
976
     */
977
    public function getDirectParents($skillId)
978
    {
979
        $skillRelSkill = new SkillRelSkill();
980
        $skills = $skillRelSkill->getDirectParents($skillId, true);
981
        if (!empty($skills)) {
982
            foreach ($skills as &$skill) {
983
                $skillData = $this->get($skill['skill_id']);
984
                if (empty($skillData)) {
985
                    continue;
986
                }
987
                $skill['data'] = $skillData;
988
                $skill_info2 = $skillRelSkill->getSkillInfo($skill['skill_id']);
989
                $parentId = isset($skill_info2['parent_id']) ? isset($skill_info2['parent_id']) : 0;
990
                $skill['data']['parent_id'] = $parentId;
991
            }
992
993
            return $skills;
994
        }
995
996
        return [];
997
    }
998
999
    /**
1000
     * Adds a new skill
1001
     * @param array $params
1002
     * @return bool|null
1003
     */
1004
    public function add($params)
1005
    {
1006
        if (!isset($params['parent_id'])) {
1007
            $params['parent_id'] = 1;
1008
        }
1009
1010
        if (!is_array($params['parent_id'])) {
1011
            $params['parent_id'] = [$params['parent_id']];
1012
        }
1013
1014
        $skillRelSkill = new SkillRelSkill();
1015
        $skillRelGradebook = new SkillRelGradebook();
1016
1017
        // Saving name, description
1018
        $skill_id = $this->save($params);
1019
        if ($skill_id) {
1020
            //Saving skill_rel_skill (parent_id, relation_type)
1021
            foreach ($params['parent_id'] as $parent_id) {
1022
                $relation_exists = $skillRelSkill->relationExists($skill_id, $parent_id);
1023
                if (!$relation_exists) {
1024
                    $attributes = [
1025
                        'skill_id' => $skill_id,
1026
                        'parent_id' => $parent_id,
1027
                        'relation_type' => (isset($params['relation_type']) ? $params['relation_type'] : 0),
1028
                        //'level'         => $params['level'],
1029
                    ];
1030
                    $skillRelSkill->save($attributes);
1031
                }
1032
            }
1033
1034
            if (!empty($params['gradebook_id'])) {
1035
                foreach ($params['gradebook_id'] as $gradebook_id) {
1036
                    $attributes = [];
1037
                    $attributes['gradebook_id'] = $gradebook_id;
1038
                    $attributes['skill_id'] = $skill_id;
1039
                    $skillRelGradebook->save($attributes);
1040
                }
1041
            }
1042
            return $skill_id;
1043
        }
1044
        return null;
1045
    }
1046
1047
    /**
1048
     * @param int $user_id
1049
     * @param int $gradebookId
1050
     * @param int $courseId
1051
     * @param int $sessionId
1052
     */
1053
    public function addSkillToUser(
1054
        $user_id,
1055
        $gradebookId,
1056
        $courseId = 0,
1057
        $sessionId = 0
1058
    ) {
1059
        $skill_gradebook = new SkillRelGradebook();
1060
        $skill_rel_user = new SkillRelUser();
1061
1062
        $skill_gradebooks = $skill_gradebook->get_all(
1063
            ['where' => ['gradebook_id = ?' => $gradebookId]]
1064
        );
1065
        if (!empty($skill_gradebooks)) {
1066
            foreach ($skill_gradebooks as $skill_gradebook) {
1067
                $user_has_skill = $this->userHasSkill(
1068
                    $user_id,
1069
                    $skill_gradebook['skill_id'],
1070
                    $courseId,
1071
                    $sessionId
1072
                );
1073
                if (!$user_has_skill) {
1074
                    $params = [
1075
                        'user_id' => $user_id,
1076
                        'skill_id' => $skill_gradebook['skill_id'],
1077
                        'acquired_skill_at' => api_get_utc_datetime(),
1078
                        'course_id' => intval($courseId),
1079
                        'session_id' => $sessionId ? intval($sessionId) : null,
1080
                    ];
1081
1082
                    $skill_rel_user->save($params);
1083
                }
1084
            }
1085
        }
1086
    }
1087
1088
    /* Deletes a skill */
1089
    public function delete($skill_id)
1090
    {
1091
        /*$params = array('skill_id' => $skill_id);
1092
1093
        $skillRelSkill     = new SkillRelSkill();
1094
        $skills = $skillRelSkill->get_all(array('where'=>array('skill_id = ?' =>$skill_id)));
1095
1096
        $skill_rel_profile     = new SkillRelProfile();
1097
        $skillRelGradebook = new SkillRelGradebook();
1098
        $skill_rel_user     = new SkillRelUser();
1099
1100
        $this->delete($skill_id);
1101
1102
        $skillRelGradebook->delete($params);*/
1103
    }
1104
1105
    /**
1106
     * @param array $params
1107
     * @return null
1108
     */
1109
    public function edit($params)
1110
    {
1111
        if (!isset($params['parent_id'])) {
1112
            $params['parent_id'] = 1;
1113
        }
1114
1115
        $params['gradebook_id'] = isset($params['gradebook_id']) ? $params['gradebook_id'] : [];
1116
1117
        $skillRelSkill = new SkillRelSkill();
1118
        $skillRelGradebook = new SkillRelGradebook();
1119
1120
        // Saving name, description
1121
        $this->update($params);
1122
        $skillId = $params['id'];
1123
1124
        if ($skillId) {
1125
            // Saving skill_rel_skill (parent_id, relation_type)
1126
            if (!is_array($params['parent_id'])) {
1127
                $params['parent_id'] = [$params['parent_id']];
1128
            }
1129
1130
            // Cannot change parent of root
1131
            if ($skillId == 1) {
1132
                $params['parent_id'] = 0;
1133
            }
1134
1135
            foreach ($params['parent_id'] as $parent_id) {
1136
                $relation_exists = $skillRelSkill->relationExists($skillId, $parent_id);
1137
                if (!$relation_exists) {
1138
                    $attributes = [
1139
                        'skill_id' => $skillId,
1140
                        'parent_id' => $parent_id,
1141
                        'relation_type' => $params['relation_type'],
1142
                        //'level'         => $params['level'],
1143
                    ];
1144
                    $skillRelSkill->updateBySkill($attributes);
1145
                }
1146
            }
1147
1148
            $skillRelGradebook->updateGradeBookListBySkill(
1149
                $skillId,
1150
                $params['gradebook_id']
1151
            );
1152
            return $skillId;
1153
        }
1154
        return null;
1155
    }
1156
1157
    /**
1158
     * Get user's skills
1159
     *
1160
     * @param int $userId User's id
1161
     * @param bool $getSkillData
1162
     * @param int $courseId
1163
     * @param int $sessionId
1164
     *
1165
     * @return array
1166
     */
1167
    public function getUserSkills($userId, $getSkillData = false, $courseId = 0, $sessionId = 0)
1168
    {
1169
        $userId = (int) $userId;
1170
        $courseId = (int) $courseId;
1171
        $sessionId = (int) $sessionId;
1172
1173
        $courseCondition = '';
1174
        if (!empty($courseId)) {
1175
            $courseCondition = " AND course_id = $courseId ";
1176
        }
1177
1178
        $sessionCondition = '';
1179
        if (!empty($sessionId)) {
1180
            $sessionCondition = " AND course_id = $sessionId ";
1181
        }
1182
1183
        $sql = 'SELECT DISTINCT
1184
                    s.id,
1185
                    s.name,
1186
                    s.icon,
1187
                    u.id as issue,
1188
                    u.acquired_skill_at,
1189
                    u.course_id
1190
                FROM '.$this->table_skill_rel_user.' u
1191
                INNER JOIN '.$this->table.' s
1192
                ON u.skill_id = s.id
1193
                WHERE
1194
                    user_id = '.$userId.' '.$sessionCondition.' '.$courseCondition;
1195
1196
        $result = Database::query($sql);
1197
        $skills = Database::store_result($result, 'ASSOC');
1198
        $skillList = [];
1199
        if (!empty($skills)) {
1200
            foreach ($skills as $skill) {
1201
                if ($getSkillData) {
1202
                    $skillData = $this->get($skill['id']);
1203
                    $skillData['url'] = api_get_path(WEB_PATH).'badge/'.$skill['issue'].'/user/'.$userId;
1204
                    $skillList[$skill['id']] = array_merge($skill, $skillData);
1205
                } else {
1206
                    $skillList[$skill['id']] = $skill['id'];
1207
                }
1208
            }
1209
        }
1210
1211
        return $skillList;
1212
    }
1213
1214
    /**
1215
     * @param Vertex $vertex
1216
     * @param array $skills
1217
     * @param int $level
1218
     *
1219
     * @return string
1220
     */
1221
    public function processVertex(Vertex $vertex, $skills = [], $level = 0)
1222
    {
1223
        $isHierarchicalTable = api_get_configuration_value('table_of_hierarchical_skill_presentation');
1224
        $subTable = '';
1225
        if ($vertex->getVerticesEdgeTo()->count() > 0) {
1226
            if ($isHierarchicalTable) {
1227
                $subTable .= '<ul>';
1228
            }
1229
            foreach ($vertex->getVerticesEdgeTo() as $subVertex) {
1230
                $data = $subVertex->getAttribute('graphviz.data');
1231
                $passed = in_array($data['id'], array_keys($skills));
1232
                $transparency = '';
1233
                if ($passed === false) {
1234
                    // @todo use css class
1235
                    $transparency = 'opacity: 0.4; filter: alpha(opacity=40);';
1236
                }
1237
1238
                if ($isHierarchicalTable) {
1239
                    $label = $this->processSkillListSimple([$data], 'mini', $transparency);
1240
                    $subTable .= '<li>'.$label;
1241
                    $subTable .= $this->processVertex($subVertex, $skills, $level + 1);
1242
                    $subTable .= '</li>';
1243
                } else {
1244
                    $imageSize = 'mini';
1245
                    if ($level == 2) {
1246
                        $imageSize = 'small';
1247
                    }
1248
                    $showTitle = true;
1249
                    if ($level > 2) {
1250
                        $showTitle = false;
1251
                    }
1252
1253
                    $label = $this->processSkillListSimple([$data], $imageSize, $transparency, true, $showTitle);
1254
                    $subTable .= '<div class="thumbnail" style="float:left; margin-right:5px; ">';
1255
                    $subTable .= '<div style="'.$transparency.'">';
1256
1257
                    $subTable .= '<div style="text-align: center">';
1258
                    $subTable .= $label;
1259
                    $subTable .= '</div>';
1260
1261
1262
                    $subTable .= '</div>';
1263
                    $subTable .= $this->processVertex($subVertex, $skills, $level + 1);
1264
                    $subTable .= '</div>';
1265
                }
1266
            }
1267
1268
            if ($isHierarchicalTable) {
1269
                $subTable .= '</ul>';
1270
            }
1271
        }
1272
1273
        return $subTable;
1274
    }
1275
1276
    /**
1277
     * @param int $userId
1278
     * @param int $courseId
1279
     * @param int $sessionId
1280
     * @param bool $addTitle
1281
     * @return array
1282
     */
1283
    public function getUserSkillsTable($userId, $courseId = 0, $sessionId = 0, $addTitle = true)
1284
    {
1285
        $skills = $this->getUserSkills($userId, true, $courseId, $sessionId);
1286
1287
        $courseTempList = [];
1288
        $tableRows = [];
1289
        $skillParents = [];
1290
        foreach ($skills as $resultData) {
1291
            $parents = $this->get_parents($resultData['id']);
1292
            foreach ($parents as $parentData) {
1293
                $parentData['passed'] = in_array($parentData['id'], array_keys($skills));
1294
                if ($parentData['passed'] && isset($skills[$parentData['id']]['url'])) {
1295
                    $parentData['data']['url'] = $skills[$parentData['id']]['url'];
1296
                }
1297
                $skillParents[$resultData['id']][$parentData['id']] = $parentData;
1298
            }
1299
        }
1300
1301
        foreach ($skills as $resultData) {
1302
            $courseId = $resultData['course_id'];
1303
            if (!empty($courseId)) {
1304
                if (isset($courseTempList[$courseId])) {
1305
                    $courseInfo = $courseTempList[$courseId];
1306
                } else {
1307
                    $courseInfo = api_get_course_info_by_id($courseId);
1308
                    $courseTempList[$courseId] = $courseInfo;
1309
                }
1310
            }
1311
1312
            $tableRow = [
1313
                'skill_badge' => $resultData['img_mini'],
1314
                'skill_name' => self::translateName($resultData['name']),
1315
                'short_code' => $resultData['short_code'],
1316
                'achieved_at' => api_get_local_time($resultData['acquired_skill_at']),
1317
                'course_image' => '',
1318
                'course_name' => '',
1319
            ];
1320
1321
            if (!empty($courseInfo)) {
1322
                $tableRow['course_image'] = $courseInfo['course_image_source'];
1323
                $tableRow['course_name'] = $courseInfo['title'];
1324
            }
1325
            $tableRows[] = $tableRow;
1326
        }
1327
1328
        $isHierarchicalTable = api_get_configuration_value('table_of_hierarchical_skill_presentation');
1329
        $allowLevels = api_get_configuration_value('skill_levels_names');
1330
1331
        $tableResult = '<div id="skillList">';
1332
        if ($isHierarchicalTable) {
1333
            $tableResult = '<div class="table-responsive">';
1334
        }
1335
1336
        if ($addTitle) {
1337
            $tableResult .= '
1338
                    <table class="table">
1339
                        <thead>
1340
                            <tr>
1341
                                <th>'.get_lang('AchievedSkills').'</th>
1342
                            </tr>
1343
                        </thead>
1344
                        <tbody>
1345
                        <tr><td>';
1346
        }
1347
1348
        if (!empty($skillParents)) {
1349
            if (empty($allowLevels)) {
1350
                $tableResult .= $this->processSkillListSimple($skills);
1351
            } else {
1352
                $graph = new Graph();
1353
                $graph->setAttribute('graphviz.graph.rankdir', 'LR');
1354
                foreach ($skillParents as $skillId => $parentList) {
1355
                    $old = null;
1356
                    foreach ($parentList as $parent) {
1357
                        if ($graph->hasVertex($parent['id'])) {
1358
                            $current = $graph->getVertex($parent['id']);
1359
                        } else {
1360
                            $current = $graph->createVertex($parent['id']);
1361
                            $current->setAttribute('graphviz.data', $parent['data']);
1362
                        }
1363
1364
                        if (!empty($old)) {
1365
                            if ($graph->hasVertex($old['id'])) {
1366
                                $nextVertex = $graph->getVertex($old['id']);
1367
                            } else {
1368
                                $nextVertex = $graph->createVertex($old['id']);
1369
                                $nextVertex->setAttribute('graphviz.data', $old['data']);
1370
                            }
1371
1372
                            if (!$nextVertex->hasEdgeTo($current)) {
1373
                                $nextVertex->createEdgeTo($current);
1374
                            }
1375
                        }
1376
                        $old = $parent;
1377
                    }
1378
                }
1379
1380
                if ($isHierarchicalTable) {
1381
                    $table = '<table class ="table table-bordered">';
1382
                    // Getting "root" vertex
1383
                    $root = $graph->getVertex(1);
1384
                    $table .= '<tr>';
1385
                    /** @var Vertex $vertex */
1386
                    foreach ($root->getVerticesEdgeTo() as $vertex) {
1387
                        $data = $vertex->getAttribute('graphviz.data');
1388
1389
                        $passed = in_array($data['id'], array_keys($skills));
1390
                        $transparency = '';
1391
                        if ($passed === false) {
1392
                            // @todo use a css class
1393
                            $transparency = 'opacity: 0.4; filter: alpha(opacity=40);';
1394
                        }
1395
1396
                        $label = $this->processSkillListSimple([$data], 'mini', $transparency);
1397
                        $table .= '<td >';
1398
1399
                        $table .= '<div class="skills_chart"> <ul><li>'.$label;
1400
                        $table .= $this->processVertex($vertex, $skills);
1401
                        $table .= '</ul></li></div>';
1402
                        $table .= '</td>';
1403
                    }
1404
                    $table .= '</tr></table>';
1405
                } else {
1406
                    // Getting "root" vertex
1407
                    $root = $graph->getVertex(1);
1408
                    $table = '';
1409
                    /** @var Vertex $vertex */
1410
                    foreach ($root->getVerticesEdgeTo() as $vertex) {
1411
                        $data = $vertex->getAttribute('graphviz.data');
1412
1413
                        $passed = in_array($data['id'], array_keys($skills));
1414
                        $transparency = '';
1415
                        if ($passed === false) {
1416
                            // @todo use a css class
1417
                            $transparency = 'opacity: 0.4; filter: alpha(opacity=40);';
1418
                        }
1419
1420
                        $label = $this->processSkillListSimple([$data], 'mini', $transparency, false);
1421
1422
                        $skillTable = $this->processVertex($vertex, $skills, 2);
1423
                        $table .= "<h3>$label</h3>";
1424
1425
                        if (!empty($skillTable)) {
1426
                            $table .= '<table class ="table table-bordered">';
1427
                            $table .= '<tr>';
1428
                            $table .= '<td>';
1429
                            $table .= '<div>';
1430
                            $table .= $skillTable;
1431
                            $table .= '</div>';
1432
                            $table .= '</td>';
1433
                            $table .= '</tr></table>';
1434
                        }
1435
                    }
1436
                }
1437
1438
                $tableResult .= $table;
1439
            }
1440
        } else {
1441
            $tableResult .= get_lang('WithoutAchievedSkills');
1442
        }
1443
1444
        if ($addTitle) {
1445
            $tableResult .= '</td>
1446
                            </tr>
1447
                        </tbody>
1448
                    </table>
1449
                ';
1450
        }
1451
        $tableResult .= '</div>';
1452
1453
        return [
1454
            'skills' => $tableRows,
1455
            'table' => $tableResult,
1456
        ];
1457
    }
1458
1459
    /**
1460
     * @param int $user_id
1461
     * @param int $skill_id
1462
     * @param bool $return_flat_array
1463
     * @param bool $add_root
1464
     * @return array|null
1465
     */
1466
    public function getSkillsTree(
1467
        $user_id = null,
1468
        $skill_id = null,
1469
        $return_flat_array = false,
1470
        $add_root = false
1471
    ) {
1472
        if ($skill_id == 1) {
1473
            $skill_id = 0;
1474
        }
1475
        if (isset($user_id) && !empty($user_id)) {
1476
            $skills = $this->get_all(true, $user_id, null, $skill_id);
1477
        } else {
1478
            $skills = $this->get_all(false, false, null, $skill_id);
1479
        }
1480
1481
        $original_skill = $this->list = $skills;
1482
1483
        // Show 1 item
1484
        if (!empty($skill_id)) {
1485
            if ($add_root) {
1486
                if (!empty($skill_id)) {
1487
                    // Default root node
1488
                    $skills[1] = [
1489
                        'id' => '1',
1490
                        'name' => get_lang('Root'),
1491
                        'parent_id' => '0',
1492
                    ];
1493
                    $skillInfo = $this->getSkillInfo($skill_id);
1494
1495
                    // 2nd node
1496
                    $skills[$skill_id] = $skillInfo;
1497
                    // Uncomment code below to hide the searched skill
1498
                    $skills[$skill_id]['data']['parent_id'] = $skillInfo['extra']['parent_id'];
1499
                    $skills[$skill_id]['parent_id'] = 1;
1500
                }
1501
            }
1502
        }
1503
1504
        $refs = [];
1505
        $skills_tree = null;
1506
1507
        // Create references for all nodes
1508
        $flat_array = [];
1509
        $family = [];
1510
        if (!empty($skills)) {
1511
            foreach ($skills as &$skill) {
1512
                if ($skill['parent_id'] == 0) {
1513
                    $skill['parent_id'] = 'root';
1514
                }
1515
1516
                // because except main keys (id, name, children) others keys
1517
                // are not saved while in the space tree
1518
                $skill['data'] = ['parent_id' => $skill['parent_id']];
1519
1520
                // If a short code was defined, send the short code to replace
1521
                // skill name (to shorten the text in the wheel)
1522
                if (!empty($skill['short_code']) &&
1523
                    api_get_setting('show_full_skill_name_on_skill_wheel') === 'false'
1524
                ) {
1525
                    $skill['data']['short_code'] = $skill['short_code'];
1526
                }
1527
1528
                $skill['data']['name'] = $skill['name'];
1529
                $skill['data']['status'] = $skill['status'];
1530
1531
                // In order to paint all members of a family with the same color
1532
                if (empty($skill_id)) {
1533
                    if ($skill['parent_id'] == 1) {
1534
                        $family[$skill['id']] = $this->getAllChildren($skill['id']);
1535
                    }
1536
                } else {
1537
                    if ($skill['parent_id'] == $skill_id) {
1538
                        $family[$skill['id']] = $this->getAllChildren($skill['id']);
1539
                    }
1540
                    /*if ($skill_id == $skill['id']) {
1541
                        $skill['parent_id'] = 1;
1542
                    }*/
1543
                }
1544
1545
                if (!isset($skill['data']['real_parent_id'])) {
1546
                    $skill['data']['real_parent_id'] = $skill['parent_id'];
1547
                }
1548
1549
                // User achieved the skill (depends in the gradebook with certification)
1550
                $skill['data']['achieved'] = false;
1551
                if ($user_id) {
1552
                    $skill['data']['achieved'] = $this->userHasSkill(
1553
                        $user_id,
1554
                        $skill['id']
1555
                    );
1556
                }
1557
1558
                // Check if the skill has related gradebooks
1559
                $skill['data']['skill_has_gradebook'] = false;
1560
                if (isset($skill['gradebooks']) && !empty($skill['gradebooks'])) {
1561
                    $skill['data']['skill_has_gradebook'] = true;
1562
                }
1563
                $refs[$skill['id']] = &$skill;
1564
                $flat_array[$skill['id']] = &$skill;
1565
            }
1566
1567
            // Checking family value
1568
1569
            $family_id = 1;
1570
            $new_family_array = [];
1571
            foreach ($family as $main_family_id => $family_items) {
1572
                if (!empty($family_items)) {
1573
                    foreach ($family_items as $item) {
1574
                        $new_family_array[$item['id']] = $family_id;
1575
                    }
1576
                }
1577
                $new_family_array[$main_family_id] = $family_id;
1578
                $family_id++;
1579
            }
1580
1581
            if (empty($original_skill)) {
1582
                $refs['root']['children'][0] = $skills[1];
1583
                $skills[$skill_id]['data']['family_id'] = 1;
1584
                $refs['root']['children'][0]['children'][0] = $skills[$skill_id];
1585
                $flat_array[$skill_id] = $skills[$skill_id];
1586
            } else {
1587
                // Moving node to the children index of their parents
1588
                foreach ($skills as $my_skill_id => &$skill) {
1589
                    if (isset($new_family_array[$skill['id']])) {
1590
                        $skill['data']['family_id'] = $new_family_array[$skill['id']];
1591
                    }
1592
                    $refs[$skill['parent_id']]['children'][] = &$skill;
1593
                    $flat_array[$my_skill_id] = $skill;
1594
                }
1595
            }
1596
1597
            $skills_tree = [
1598
                'name' => get_lang('SkillRootName'),
1599
                'id' => 'root',
1600
                'children' => $refs['root']['children'],
1601
                'data' => [],
1602
            ];
1603
        }
1604
1605
        if ($return_flat_array) {
1606
            return $flat_array;
1607
        }
1608
        unset($skills);
1609
1610
        return $skills_tree;
1611
    }
1612
1613
    /**
1614
     * Get skills tree as a simplified JSON structure
1615
     * @param int user id
1616
     * @param int skill id
1617
     * @param bool return a flat array or not
1618
     * @param int depth of the skills
1619
     * @return string json
1620
     */
1621
    public function getSkillsTreeToJson(
1622
        $user_id = null,
1623
        $skill_id = null,
1624
        $return_flat_array = false,
1625
        $main_depth = 2
1626
    ) {
1627
        $tree = $this->getSkillsTree(
1628
            $user_id,
1629
            $skill_id,
1630
            $return_flat_array,
1631
            true
1632
        );
1633
        $simple_tree = [];
1634
        if (!empty($tree['children'])) {
1635
            foreach ($tree['children'] as $element) {
1636
                $children = [];
1637
                if (isset($element['children'])) {
1638
                    $children = $this->getSkillToJson($element['children'], 1, $main_depth);
1639
                }
1640
                $simple_tree[] = [
1641
                    'name' => $element['name'],
1642
                    'children' => $children,
1643
                ];
1644
            }
1645
        }
1646
1647
        return json_encode($simple_tree[0]['children']);
1648
    }
1649
1650
    /**
1651
     * Get JSON element
1652
     * @param array $subtree
1653
     * @param int $depth
1654
     * @param int $max_depth
1655
     * @return array|null
1656
     */
1657
    public function getSkillToJson($subtree, $depth = 1, $max_depth = 2)
1658
    {
1659
        $simple_sub_tree = [];
1660
        if (is_array($subtree)) {
1661
            $counter = 1;
1662
            foreach ($subtree as $elem) {
1663
                $tmp = [];
1664
                $tmp['name'] = $elem['name'];
1665
                $tmp['id'] = $elem['id'];
1666
                $tmp['isSearched'] = self::isSearched($elem['id']);
1667
1668
                if (isset($elem['children']) && is_array($elem['children'])) {
1669
                    $tmp['children'] = $this->getSkillToJson(
1670
                        $elem['children'],
1671
                        $depth + 1,
1672
                        $max_depth
1673
                    );
1674
                } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
1675
                    //$tmp['colour'] = $this->colours[$depth][rand(0,3)];
1676
                }
1677
1678
                if ($depth > $max_depth) {
1679
                    continue;
1680
                }
1681
1682
                $tmp['depth'] = $depth;
1683
                $tmp['counter'] = $counter;
1684
                $counter++;
1685
1686
                if (isset($elem['data']) && is_array($elem['data'])) {
1687
                    foreach ($elem['data'] as $key => $item) {
1688
                        $tmp[$key] = $item;
1689
                    }
1690
                }
1691
                $simple_sub_tree[] = $tmp;
1692
            }
1693
            return $simple_sub_tree;
1694
        }
1695
        return null;
1696
    }
1697
1698
    /**
1699
     * @param int $user_id
1700
     * @return bool
1701
     */
1702
    public function getUserSkillRanking($user_id)
1703
    {
1704
        $user_id = intval($user_id);
1705
        $sql = "SELECT count(skill_id) count FROM {$this->table} s
1706
                INNER JOIN {$this->table_skill_rel_user} su
1707
                ON (s.id = su.skill_id)
1708
                WHERE user_id = $user_id";
1709
        $result = Database::query($sql);
1710
        if (Database::num_rows($result)) {
1711
            $result = Database::fetch_row($result);
1712
            return $result[0];
1713
        }
1714
        return false;
1715
    }
1716
1717
    /**
1718
     * @param $start
1719
     * @param $limit
1720
     * @param $sidx
1721
     * @param $sord
1722
     * @param $where_condition
1723
     * @return array
1724
     */
1725
    public function getUserListSkillRanking(
1726
        $start,
1727
        $limit,
1728
        $sidx,
1729
        $sord,
1730
        $where_condition
1731
    ) {
1732
        $start = intval($start);
1733
        $limit = intval($limit);
1734
        /*  ORDER BY $sidx $sord */
1735
        $sql = "SELECT *, @rownum:=@rownum+1 rank FROM (
1736
                    SELECT u.user_id, firstname, lastname, count(username) skills_acquired
1737
                    FROM {$this->table} s INNER JOIN {$this->table_skill_rel_user} su ON (s.id = su.skill_id)
1738
                    INNER JOIN {$this->table_user} u ON u.user_id = su.user_id, (SELECT @rownum:=0) r
1739
                    WHERE 1=1 $where_condition
1740
                    GROUP BY username
1741
                    ORDER BY skills_acquired desc
1742
                    LIMIT $start , $limit)  AS T1, (SELECT @rownum:=0) r";
1743
        $result = Database::query($sql);
1744
        if (Database::num_rows($result)) {
1745
            return Database::store_result($result, 'ASSOC');
1746
        }
1747
1748
        return [];
1749
    }
1750
1751
    /**
1752
     * @return int
1753
     */
1754
    public function getUserListSkillRankingCount()
1755
    {
1756
        $sql = "SELECT count(*) FROM (
1757
                    SELECT count(distinct 1)
1758
                    FROM {$this->table} s
1759
                    INNER JOIN {$this->table_skill_rel_user} su
1760
                    ON (s.id = su.skill_id)
1761
                    INNER JOIN {$this->table_user} u
1762
                    ON u.user_id = su.user_id
1763
                    GROUP BY username
1764
                 ) as T1";
1765
        $result = Database::query($sql);
1766
        if (Database::num_rows($result)) {
1767
            $result = Database::fetch_row($result);
1768
1769
            return $result[0];
1770
        }
1771
1772
        return 0;
1773
    }
1774
1775
    /**
1776
     * @param string $courseCode
1777
     * @return int
1778
     */
1779
    public function getCountSkillsByCourse($courseCode)
1780
    {
1781
        $courseCode = Database::escape_string($courseCode);
1782
        $sql = "SELECT count(skill_id) as count
1783
                FROM {$this->table_gradebook} g
1784
                INNER JOIN {$this->table_skill_rel_gradebook} sg
1785
                ON g.id = sg.gradebook_id
1786
                WHERE course_code = '$courseCode'";
1787
1788
        $result = Database::query($sql);
1789
        if (Database::num_rows($result)) {
1790
            $result = Database::fetch_row($result);
1791
            return $result[0];
1792
        }
1793
        return 0;
1794
    }
1795
1796
    /**
1797
     * @param int $skillId
1798
     * @return array
1799
     */
1800
    public function getCoursesBySkill($skillId)
1801
    {
1802
        $skillId = intval($skillId);
1803
        $sql = "SELECT c.title, c.code
1804
                FROM {$this->table_gradebook} g
1805
                INNER JOIN {$this->table_skill_rel_gradebook} sg
1806
                ON g.id = sg.gradebook_id
1807
                INNER JOIN {$this->table_course} c
1808
                ON c.code = g.course_code
1809
                WHERE sg.skill_id = $skillId
1810
                AND (g.session_id IS NULL OR g.session_id = 0)";
1811
        $result = Database::query($sql);
1812
1813
        return Database::store_result($result, 'ASSOC');
1814
    }
1815
1816
    /**
1817
     * Check if the user has the skill
1818
     * @param int $userId The user id
1819
     * @param int $skillId The skill id
1820
     * @param int $courseId Optional. The course id
1821
     * @param int $sessionId Optional. The session id
1822
     * @return boolean Whether the user has the skill return true. Otherwise return false
1823
     */
1824
    public function userHasSkill($userId, $skillId, $courseId = 0, $sessionId = 0)
1825
    {
1826
        $courseId = intval($courseId);
1827
        $sessionId = intval($sessionId);
1828
1829
        $whereConditions = [
1830
            'user_id = ? ' => intval($userId),
1831
            'AND skill_id = ? ' => intval($skillId),
1832
        ];
1833
1834
        if ($courseId > 0) {
1835
            $whereConditions['AND course_id = ? '] = $courseId;
1836
            $whereConditions['AND session_id = ? '] = $sessionId ? $sessionId : null;
1837
        }
1838
1839
        $result = Database::select(
1840
            'COUNT(1) AS qty',
1841
            $this->table_skill_rel_user,
1842
            [
1843
                'where' => $whereConditions,
1844
            ],
1845
            'first'
1846
        );
1847
1848
        if ($result != false) {
1849
            if ($result['qty'] > 0) {
1850
                return true;
1851
            }
1852
        }
1853
1854
        return false;
1855
    }
1856
1857
    /**
1858
     * Check if a skill is searched
1859
     * @param int $id The skill id
1860
     * @return boolean Whether el skill is searched return true. Otherwise return false
1861
     */
1862
    public static function isSearched($id)
1863
    {
1864
        $id = intval($id);
1865
1866
        if (empty($id)) {
1867
            return false;
1868
        }
1869
1870
        $skillRelProfileTable = Database::get_main_table(TABLE_MAIN_SKILL_REL_PROFILE);
1871
1872
        $result = Database::select(
1873
            'COUNT( DISTINCT `skill_id`) AS qty',
1874
            $skillRelProfileTable,
1875
            [
1876
                'where' => [
1877
                    'skill_id = ?' => $id,
1878
                ],
1879
            ],
1880
            'first'
1881
        );
1882
1883
        if ($result === false) {
1884
            return false;
1885
        }
1886
1887
        if ($result['qty'] > 0) {
1888
            return true;
1889
        }
1890
1891
        return false;
1892
    }
1893
1894
    /**
1895
     * Get the achieved skills by course
1896
     * @param int $courseId The course id
1897
     * @return array The skills list
1898
     */
1899
    public function listAchievedByCourse($courseId)
1900
    {
1901
        $courseId = intval($courseId);
1902
1903
        if ($courseId == 0) {
1904
            return [];
1905
        }
1906
1907
        $list = [];
1908
1909
        $sql = "SELECT
1910
                    course.id c_id,
1911
                    course.title c_name,
1912
                    course.directory c_directory,
1913
                    user.user_id,
1914
                    user.lastname,
1915
                    user.firstname,
1916
                    user.username,
1917
                    skill.id skill_id,
1918
                    skill.name skill_name,
1919
                    sru.acquired_skill_at
1920
                FROM {$this->table_skill_rel_user} AS sru
1921
                INNER JOIN {$this->table_course}
1922
                ON sru.course_id = course.id
1923
                INNER JOIN {$this->table_user}
1924
                ON sru.user_id = user.user_id
1925
                INNER JOIN {$this->table}
1926
                ON sru.skill_id = skill.id
1927
                WHERE course.id = $courseId";
1928
1929
        $result = Database::query($sql);
1930
1931
        while ($row = Database::fetch_assoc($result)) {
1932
            $row['skill_name'] = self::translateName($row['skill_name']);
1933
            $list[] = $row;
1934
        }
1935
1936
        return $list;
1937
    }
1938
1939
    /**
1940
     * Get the users list who achieved a skill
1941
     * @param int $skillId The skill id
1942
     *
1943
     * @return array The users list
1944
     */
1945
    public function listUsersWhoAchieved($skillId)
1946
    {
1947
        $skillId = intval($skillId);
1948
1949
        if ($skillId == 0) {
1950
            return [];
1951
        }
1952
1953
        $list = [];
1954
        $sql = "SELECT
1955
                    course.id c_id,
1956
                    course.title c_name,
1957
                    course.directory c_directory,
1958
                    user.user_id,
1959
                    user.lastname,
1960
                    user.firstname,
1961
                    user.username,
1962
                    skill.id skill_id,
1963
                    skill.name skill_name,
1964
                    sru.acquired_skill_at
1965
                FROM {$this->table_skill_rel_user} AS sru
1966
                INNER JOIN {$this->table_course}
1967
                ON sru.course_id = course.id
1968
                INNER JOIN {$this->table_user}
1969
                ON sru.user_id = user.user_id
1970
                INNER JOIN {$this->table}
1971
                ON sru.skill_id = skill.id
1972
                WHERE skill.id = $skillId ";
1973
1974
        $result = Database::query($sql);
1975
        while ($row = Database::fetch_assoc($result)) {
1976
            $row['skill_name'] = self::translateName($row['skill_name']);
1977
            $list[] = $row;
1978
        }
1979
1980
        return $list;
1981
    }
1982
1983
    /**
1984
     * Get the session list where the user can achieve a skill
1985
     * @param int $skillId The skill id
1986
     * @return array
1987
     */
1988
    public function getSessionsBySkill($skillId)
1989
    {
1990
        $skillId = intval($skillId);
1991
1992
        $sql = "SELECT s.id, s.name
1993
                FROM {$this->table_gradebook} g
1994
                INNER JOIN {$this->table_skill_rel_gradebook} sg
1995
                ON g.id = sg.gradebook_id
1996
                INNER JOIN {$this->sessionTable} s
1997
                ON g.session_id = s.id
1998
                WHERE sg.skill_id = $skillId
1999
                AND g.session_id > 0";
2000
2001
        $result = Database::query($sql);
2002
2003
        return Database::store_result($result, 'ASSOC');
2004
    }
2005
2006
    /**
2007
     * Check if the $fromUser can comment the $toUser skill issue
2008
     * @param User $fromUser
2009
     * @param User $toUser
2010
     * @return boolean
2011
     */
2012
    public static function userCanAddFeedbackToUser($fromUser, $toUser)
2013
    {
2014
        if (api_is_platform_admin()) {
2015
            return true;
2016
        }
2017
2018
        $entityManager = Database::getManager();
2019
        /** @var UserRepository $userRepo */
2020
        $userRepo = $entityManager->getRepository('ChamiloUserBundle:User');
2021
        $fromUserStatus = $fromUser->getStatus();
2022
2023
        switch ($fromUserStatus) {
2024
            case SESSIONADMIN:
2025
                if (api_get_setting('allow_session_admins_to_manage_all_sessions') === 'true') {
2026
                    if ($toUser->getCreatorId() === $fromUser->getId()) {
2027
                        return true;
2028
                    }
2029
                }
2030
2031
                $sessionAdmins = $userRepo->getSessionAdmins($toUser);
2032
2033
                foreach ($sessionAdmins as $sessionAdmin) {
2034
                    if ($sessionAdmin->getId() !== $fromUser->getId()) {
2035
                        continue;
2036
                    }
2037
2038
                    return true;
2039
                }
2040
                break;
2041
            case STUDENT_BOSS:
2042
                $studentBosses = $userRepo->getStudentBosses($toUser);
2043
                foreach ($studentBosses as $studentBoss) {
2044
                    if ($studentBoss->getId() !== $fromUser->getId()) {
2045
                        continue;
2046
                    }
2047
2048
                    return true;
2049
                }
2050
                break;
2051
            case DRH:
2052
                return UserManager::is_user_followed_by_drh(
2053
                    $toUser->getId(),
2054
                    $fromUser->getId()
2055
                );
2056
        }
2057
2058
        return false;
2059
    }
2060
2061
    /**
2062
     * If $studentId is set then check if current user has the right to see
2063
     * the page.
2064
     * @param int $studentId check if current user has access to see $studentId
2065
     * @param bool $blockPage raise a api_not_allowed()
2066
     *
2067
     * @return bool
2068
     */
2069
    public static function isAllowed($studentId = 0, $blockPage = true)
2070
    {
2071
        if (self::isToolAvailable()) {
2072
            if (api_is_platform_admin()) {
2073
                return true;
2074
            }
2075
2076
            if (!empty($studentId)) {
2077
                $currentUserId = api_get_user_id();
2078
                if ((int) $currentUserId === (int) $studentId) {
2079
                    return true;
2080
                }
2081
2082
                $haveAccess = self::hasAccessToUserSkill(
2083
                    $currentUserId,
2084
                    $studentId
2085
                );
2086
2087
                if ($haveAccess) {
2088
                    return true;
2089
                }
2090
            }
2091
        }
2092
2093
        if ($blockPage) {
2094
            api_not_allowed(true);
2095
        }
2096
2097
        return false;
2098
    }
2099
2100
    /**
2101
     * @return bool
2102
     */
2103
    public static function isToolAvailable()
2104
    {
2105
        $allowTool = api_get_setting('allow_skills_tool');
2106
2107
        if ($allowTool === 'true') {
2108
            return true;
2109
        }
2110
2111
        return false;
2112
    }
2113
2114
    /**
2115
     * @param $currentUserId
2116
     * @param $studentId
2117
     * @return bool
2118
     */
2119
    public static function hasAccessToUserSkill($currentUserId, $studentId)
2120
    {
2121
        if (self::isToolAvailable()) {
2122
            if (api_is_platform_admin()) {
2123
                return true;
2124
            }
2125
2126
            if (api_is_student_boss()) {
2127
                $isBoss = UserManager::userIsBossOfStudent($currentUserId, $studentId);
2128
                if ($isBoss) {
2129
                    return true;
2130
                }
2131
            }
2132
2133
            $allow = api_get_configuration_value('allow_private_skills');
2134
            if ($allow === true) {
2135
                if (api_is_teacher()) {
2136
                    return UserManager::isTeacherOfStudent(
2137
                        $currentUserId,
2138
                        $studentId
2139
                    );
2140
                }
2141
2142
                if (api_is_drh()) {
2143
                    return UserManager::is_user_followed_by_drh(
2144
                        $studentId,
2145
                        $currentUserId
2146
                    );
2147
                }
2148
            }
2149
        }
2150
2151
        return false;
2152
    }
2153
2154
    /**
2155
     * Get skills
2156
     * @param int $userId
2157
     * @param int level
2158
     * @return array
2159
     */
2160
    public function getStudentSkills($userId, $level = 0)
2161
    {
2162
        $sql = "SELECT s.id, s.name, sru.acquired_skill_at
2163
                FROM {$this->table} s
2164
                INNER JOIN {$this->table_skill_rel_user} sru
2165
                ON s.id = sru.skill_id
2166
                WHERE sru.user_id = $userId";
2167
2168
        $result = Database::query($sql);
2169
2170
        $skills = [];
2171
        foreach ($result as $item) {
2172
            if (empty($level)) {
2173
                $skills[] = [
2174
                    'name' => self::translateName($item['name']),
2175
                    'acquired_skill_at' => $item['acquired_skill_at'],
2176
                ];
2177
            } else {
2178
                $parents = self::get_parents($item['id']);
2179
                // +2 because it takes into account the root
2180
                if (count($parents) == $level + 1) {
2181
                    $skills[] = [
2182
                        'name' => self::translateName($item['name']),
2183
                        'acquired_skill_at' => $item['acquired_skill_at'],
2184
                    ];
2185
                }
2186
            }
2187
        }
2188
2189
        return $skills;
2190
    }
2191
2192
    /**
2193
     * @param string $name
2194
     * @return string
2195
     */
2196
    public static function translateName($name)
2197
    {
2198
        $variable = ChamiloApi::getLanguageVar($name, 'Skill');
2199
2200
        return isset($GLOBALS[$variable]) ? $GLOBALS[$variable] : $name;
2201
    }
2202
2203
    /**
2204
     * @param string $code
2205
     * @return mixed|string
2206
     */
2207
    public static function translateCode($code)
2208
    {
2209
        if (empty($code)) {
2210
            return '';
2211
        }
2212
2213
        $variable = ChamiloApi::getLanguageVar($code, 'SkillCode');
2214
2215
        return isset($GLOBALS[$variable]) ? $GLOBALS[$variable] : $code;
2216
    }
2217
2218
    /**
2219
     * @param FormValidator $form
2220
     * @param array $skillInfo
2221
     *
2222
     * @return array
2223
     */
2224
    public function setForm(FormValidator &$form, $skillInfo = [])
2225
    {
2226
        $allSkills = $this->get_all();
2227
        $objGradebook = new Gradebook();
2228
2229
        $isAlreadyRootSkill = false;
2230
        foreach ($allSkills as $checkedSkill) {
2231
            if (intval($checkedSkill['parent_id']) > 0) {
2232
                $isAlreadyRootSkill = true;
2233
                break;
2234
            }
2235
        }
2236
2237
        $skillList = $isAlreadyRootSkill ? [] : [0 => get_lang('None')];
2238
2239
        foreach ($allSkills as $skill) {
2240
            if (isset($skillInfo['id']) && $skill['id'] == $skillInfo['id']) {
2241
                continue;
2242
            }
2243
2244
            $skillList[$skill['id']] = $skill['name'];
2245
        }
2246
2247
        $allGradeBooks = $objGradebook->find('all');
2248
2249
        // This procedure is for check if there is already a Skill with no Parent (Root by default)
2250
        $gradeBookList = [];
2251
        foreach ($allGradeBooks as $gradebook) {
2252
            $gradeBookList[$gradebook['id']] = $gradebook['name'];
2253
        }
2254
2255
        $translateUrl = api_get_path(WEB_CODE_PATH).'admin/skill_translate.php?';
2256
        $translateNameButton = '';
2257
        $translateCodeButton = '';
2258
        $skillId = null;
2259
        if (!empty($skillInfo)) {
2260
            $skillId = $skillInfo['id'];
2261
            $translateNameUrl = $translateUrl.http_build_query(['skill' => $skillId, 'action' => 'name']);
2262
            $translateCodeUrl = $translateUrl.http_build_query(['skill' => $skillId, 'action' => 'code']);
2263
            $translateNameButton = Display::toolbarButton(
2264
                get_lang('TranslateThisTerm'),
2265
                $translateNameUrl,
2266
                'language',
2267
                'link'
2268
            );
2269
            $translateCodeButton = Display::toolbarButton(
2270
                get_lang('TranslateThisTerm'),
2271
                $translateCodeUrl,
2272
                'language',
2273
                'link'
2274
            );
2275
        }
2276
2277
        $form->addText('name', [get_lang('Name'), $translateNameButton], true, ['id' => 'name']);
2278
        $form->addText('short_code', [get_lang('ShortCode'), $translateCodeButton], false, ['id' => 'short_code']);
2279
2280
        // Cannot change parent of root
2281
        if ($skillId != 1) {
2282
            $form->addSelect('parent_id', get_lang('Parent'), $skillList, ['id' => 'parent_id']);
2283
        }
2284
2285
        $form->addSelect(
2286
            'gradebook_id',
2287
            [get_lang('Gradebook'), get_lang('WithCertificate')],
2288
            $gradeBookList,
2289
            ['id' => 'gradebook_id', 'multiple' => 'multiple', 'size' => 10]
2290
        );
2291
        $form->addTextarea('description', get_lang('Description'), ['id' => 'description', 'rows' => 7]);
2292
        $form->addTextarea('criteria', get_lang('CriteriaToEarnTheBadge'), ['id' => 'criteria', 'rows' => 7]);
2293
2294
        // EXTRA FIELDS
2295
        $extraField = new ExtraField('skill');
2296
        $returnParams = $extraField->addElements($form, $skillId);
2297
2298
        if (empty($skillInfo)) {
2299
            $form->addButtonCreate(get_lang('Add'));
2300
        } else {
2301
            $form->addButtonUpdate(get_lang('Update'));
2302
        }
2303
        $form->addHidden('id', null);
2304
2305
        return $returnParams;
2306
    }
2307
2308
    /**
2309
     * @return string
2310
     */
2311
    public function getToolBar()
2312
    {
2313
        $toolbar = Display::url(
2314
            Display::return_icon(
2315
                'back.png',
2316
                get_lang('ManageSkills'),
2317
                null,
2318
                ICON_SIZE_MEDIUM
2319
            ),
2320
            api_get_path(WEB_CODE_PATH).'admin/skill_list.php'
2321
        );
2322
        $actions = '<div class="actions">'.$toolbar.'</div>';
2323
2324
        return $actions;
2325
    }
2326
2327
2328
    /**
2329
     * Add skills select ajax for an item (exercise, lp)
2330
     * @param FormValidator $form
2331
     * @param int $typeId see ITEM_TYPE_* constants
2332
     * @param int $itemId
2333
     * @throws Exception
2334
     * @return array
2335
     */
2336
    public static function addSkillsToForm(FormValidator $form, $typeId, $itemId = 0)
2337
    {
2338
        $allowSkillInTools = api_get_configuration_value('allow_skill_rel_items');
2339
        if (!$allowSkillInTools) {
2340
            return [];
2341
        }
2342
2343
        $skillList = [];
2344
        if (!empty($itemId)) {
2345
            $em = Database::getManager();
2346
            $items = $em->getRepository('ChamiloSkillBundle:SkillRelItem')->findBy(
2347
                ['itemId' => $itemId, 'itemType' => $typeId]
2348
            );
2349
            /** @var SkillRelItem $skillRelItem */
2350
            foreach ($items as $skillRelItem) {
2351
                $skillList[$skillRelItem->getSkill()->getId()] = $skillRelItem->getSkill()->getName();
2352
            }
2353
        }
2354
2355
        $form->addSelectAjax(
2356
            'skills',
2357
            get_lang('Skills'),
2358
            $skillList,
2359
            [
2360
                'url' => api_get_path(WEB_AJAX_PATH).'skill.ajax.php?a=search_skills',
2361
                'multiple' => 'multiple',
2362
            ]
2363
        );
2364
2365
        return $skillList;
2366
    }
2367
2368
    /**
2369
     * @param int $typeId
2370
     * @param int $itemId
2371
     * @return array
2372
     */
2373
    public static function getSkillRelItems($typeId, $itemId)
2374
    {
2375
        $allowSkillInTools = api_get_configuration_value('allow_skill_rel_items');
2376
        $skills = [];
2377
        if ($allowSkillInTools) {
2378
            $em = Database::getManager();
2379
            $skills = $em->getRepository('ChamiloSkillBundle:SkillRelItem')->findBy(
2380
                ['itemId' => $itemId, 'itemType' => $typeId]
2381
            );
2382
        }
2383
2384
        return $skills;
2385
    }
2386
2387
    /**
2388
     * @param int $typeId
2389
     * @param int $itemId
2390
     *
2391
     * @return string
2392
     */
2393
    public static function getSkillRelItemsToString($typeId, $itemId)
2394
    {
2395
        $skills = self::getSkillRelItems($typeId, $itemId);
2396
        $skillToString = '';
2397
        if (!empty($skills)) {
2398
            /** @var SkillRelItem $skillRelItem */
2399
            $skillList = [];
2400
            foreach ($skills as $skillRelItem) {
2401
                $skillList[] = Display::label($skillRelItem->getSkill()->getName(), 'success');
2402
            }
2403
            $skillToString = '&nbsp;'.implode(' ', $skillList);
2404
        }
2405
2406
        return $skillToString;
2407
    }
2408
2409
    /**
2410
     * Relate skill with an item (exercise, gradebook, lp, etc)
2411
     * @param FormValidator $form
2412
     * @param int $typeId
2413
     * @param int $itemId
2414
     * @throws \Doctrine\ORM\OptimisticLockException
2415
     */
2416
    public static function saveSkills($form, $typeId, $itemId)
2417
    {
2418
        $allowSkillInTools = api_get_configuration_value('allow_skill_rel_items');
2419
        if ($allowSkillInTools) {
2420
            $userId = api_get_user_id();
2421
            $em = Database::getManager();
2422
            $skills = (array) $form->getSubmitValue('skills');
2423
2424
            // Delete old ones
2425
            $items = $em->getRepository('ChamiloSkillBundle:SkillRelItem')->findBy(
2426
                ['itemId' => $itemId, 'itemType' => $typeId]
2427
            );
2428
            if (!empty($items)) {
2429
                /** @var \Chamilo\SkillBundle\Entity\SkillRelItem $skillRelItem */
2430
                foreach ($items as $skillRelItem) {
2431
                    if (!in_array($skillRelItem->getSkill()->getId(), $skills)) {
2432
                        $em->remove($skillRelItem);
2433
                    }
2434
                }
2435
                $em->flush();
2436
            }
2437
2438
            // Add new one
2439
            if (!empty($skills)) {
2440
                foreach ($skills as $skillId) {
2441
                    /** @var \Chamilo\CoreBundle\Entity\Skill $skill */
2442
                    $skill = $em->getRepository('ChamiloCoreBundle:Skill')->find($skillId);
2443
                    if ($skill) {
2444
                        if (!$skill->hasItem($typeId, $itemId)) {
2445
                            $skillRelItem = new \Chamilo\SkillBundle\Entity\SkillRelItem();
2446
                            $skillRelItem
2447
                                ->setItemType($typeId)
2448
                                ->setItemId($itemId)
2449
                                ->setCreatedBy($userId)
2450
                                ->setUpdatedBy($userId)
2451
                            ;
2452
                            $skill->addItem($skillRelItem);
2453
                            $em->persist($skill);
2454
                            $em->flush();
2455
                        }
2456
                    }
2457
                }
2458
            }
2459
        }
2460
    }
2461
}
2462