Passed
Push — 1.11.x ( fe49af...9b3f36 )
by Julito
12:53 queued 02:17
created

Career::get_count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Fhaculty\Graph\Graph;
6
use Fhaculty\Graph\Vertex;
7
8
/**
9
 * Class Career.
10
 */
11
class Career extends Model
12
{
13
    public $table;
14
    public $columns = [
15
        'id',
16
        'name',
17
        'description',
18
        'status',
19
        'created_at',
20
        'updated_at',
21
    ];
22
23
    public function __construct()
24
    {
25
        $this->table = Database::get_main_table(TABLE_CAREER);
26
    }
27
28
    public function getFromExternalExtraField($careerId, $extraFieldVariable = 'external_career_id')
29
    {
30
        $careerExtraFieldValue = new ExtraFieldValue('career');
31
        $careerValue = $careerExtraFieldValue->get_item_id_from_field_variable_and_field_value(
32
            $extraFieldVariable,
33
            $careerId
34
        );
35
36
        $careerInfo = [];
37
        if (isset($careerValue['item_id'])) {
38
            $careerInfo = $this->get($careerValue['item_id']);
39
        }
40
41
        return $careerInfo;
42
    }
43
44
    /**
45
     * Get the count of elements.
46
     *
47
     * @return int
48
     */
49
    public function get_count()
50
    {
51
        $row = Database::select(
52
            'count(*) as count',
53
            $this->table,
54
            [],
55
            'first'
56
        );
57
58
        return $row['count'];
59
    }
60
61
    /**
62
     * @param array $where_conditions
63
     *
64
     * @return array
65
     */
66
    public function get_all($where_conditions = [])
67
    {
68
        return Database::select(
69
            '*',
70
            $this->table,
71
            ['where' => $where_conditions, 'order' => 'name ASC']
72
        );
73
    }
74
75
    /**
76
     * Update all promotion status by career.
77
     *
78
     * @param int $career_id
79
     * @param int $status    (1 or 0)
80
     */
81
    public function update_all_promotion_status_by_career_id($career_id, $status)
82
    {
83
        $promotion = new Promotion();
84
        $promotion_list = $promotion->get_all_promotions_by_career_id($career_id);
85
        if (!empty($promotion_list)) {
86
            foreach ($promotion_list as $item) {
87
                $params['id'] = $item['id'];
88
                $params['status'] = $status;
89
                $promotion->update($params);
90
                $promotion->update_all_sessions_status_by_promotion_id($params['id'], $status);
91
            }
92
        }
93
    }
94
95
    /**
96
     * Returns HTML the title + grid.
97
     *
98
     * @return string
99
     */
100
    public function display()
101
    {
102
        $html = '<div class="actions" style="margin-bottom:20px">';
103
        $html .= '<a href="career_dashboard.php">'.
104
            Display::return_icon('back.png', get_lang('Back'), '', ICON_SIZE_MEDIUM).'</a>';
105
        if (api_is_platform_admin()) {
106
            $html .= '<a href="'.api_get_self().'?action=add">'.
107
                    Display::return_icon('new_career.png', get_lang('Add'), '', ICON_SIZE_MEDIUM).'</a>';
108
        }
109
        $html .= '</div>';
110
        $html .= Display::grid_html('careers');
111
112
        return $html;
113
    }
114
115
    /**
116
     * @return array
117
     */
118
    public function get_status_list()
119
    {
120
        return [
121
            CAREER_STATUS_ACTIVE => get_lang('Unarchived'),
122
            CAREER_STATUS_INACTIVE => get_lang('Archived'),
123
        ];
124
    }
125
126
    /**
127
     * Returns a Form validator Obj.
128
     *
129
     * @todo the form should be auto generated
130
     *
131
     * @param string $url
132
     * @param string $action add, edit
133
     *
134
     * @return FormValidator
135
     */
136
    public function return_form($url, $action)
137
    {
138
        $form = new FormValidator('career', 'post', $url);
139
        // Setting the form elements
140
        $header = get_lang('Add');
141
        if ($action == 'edit') {
142
            $header = get_lang('Modify');
143
        }
144
145
        $id = isset($_GET['id']) ? (int) $_GET['id'] : '';
146
        $form->addHeader($header);
147
        $form->addHidden('id', $id);
148
        $form->addElement('text', 'name', get_lang('Name'), ['size' => '70']);
149
        $form->addHtmlEditor(
150
            'description',
151
            get_lang('Description'),
152
            false,
153
            false,
154
            [
155
                'ToolbarSet' => 'Careers',
156
                'Width' => '100%',
157
                'Height' => '250',
158
            ]
159
        );
160
        $status_list = $this->get_status_list();
161
        $form->addElement('select', 'status', get_lang('Status'), $status_list);
162
163
        if ($action == 'edit') {
164
            $extraField = new ExtraField('career');
165
            $extraField->addElements($form, $id);
166
167
            $form->addElement('text', 'created_at', get_lang('CreatedAt'));
168
            $form->freeze('created_at');
169
            $form->addButtonSave(get_lang('Modify'));
170
        } else {
171
            $form->addButtonCreate(get_lang('Add'));
172
        }
173
174
        // Setting the defaults
175
        $defaults = $this->get($id);
176
177
        if (!empty($defaults['created_at'])) {
178
            $defaults['created_at'] = api_convert_and_format_date($defaults['created_at']);
179
        }
180
        if (!empty($defaults['updated_at'])) {
181
            $defaults['updated_at'] = api_convert_and_format_date($defaults['updated_at']);
182
        }
183
184
        $form->setDefaults($defaults);
185
186
        // Setting the rules
187
        $form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
188
189
        return $form;
190
    }
191
192
    /**
193
     * Copies the career to a new one.
194
     *
195
     * @param   int     Career ID
196
     * @param   bool     Whether or not to copy the promotions inside
197
     *
198
     * @return int New career ID on success, false on failure
199
     */
200
    public function copy($id, $copy_promotions = false)
201
    {
202
        $career = $this->get($id);
203
        $new = [];
204
        foreach ($career as $key => $val) {
205
            switch ($key) {
206
                case 'id':
207
                case 'updated_at':
208
                    break;
209
                case 'name':
210
                    $val .= ' '.get_lang('CopyLabelSuffix');
211
                    $new[$key] = $val;
212
                    break;
213
                case 'created_at':
214
                    $val = api_get_utc_datetime();
215
                    $new[$key] = $val;
216
                    break;
217
                default:
218
                    $new[$key] = $val;
219
                    break;
220
            }
221
        }
222
        $cid = $this->save($new);
223
        if ($copy_promotions) {
224
            //Now also copy each session of the promotion as a new session and register it inside the promotion
225
            $promotion = new Promotion();
226
            $promo_list = $promotion->get_all_promotions_by_career_id($id);
227
            if (!empty($promo_list)) {
228
                foreach ($promo_list as $item) {
229
                    $promotion->copy($item['id'], $cid, true);
230
                }
231
            }
232
        }
233
234
        return $cid;
235
    }
236
237
    /**
238
     * @param int $career_id
239
     *
240
     * @return bool
241
     */
242
    public function get_status($career_id)
243
    {
244
        $table = Database::get_main_table(TABLE_CAREER);
245
        $career_id = intval($career_id);
246
        $sql = "SELECT status FROM $table WHERE id = '$career_id'";
247
        $result = Database::query($sql);
248
        if (Database::num_rows($result) > 0) {
249
            $data = Database::fetch_array($result);
250
251
            return $data['status'];
252
        } else {
253
            return false;
254
        }
255
    }
256
257
    /**
258
     * @param array $params
259
     * @param bool  $show_query
260
     *
261
     * @return int
262
     */
263
    public function save($params, $show_query = false)
264
    {
265
        if (isset($params['description'])) {
266
            $params['description'] = Security::remove_XSS($params['description']);
267
        }
268
269
        $id = parent::save($params);
270
        if (!empty($id)) {
271
            Event::addEvent(
272
                LOG_CAREER_CREATE,
273
                LOG_CAREER_ID,
274
                $id,
275
                api_get_utc_datetime(),
276
                api_get_user_id()
277
            );
278
        }
279
280
        return $id;
281
    }
282
283
    /**
284
     * Delete a record from the career table and report in the default events log table.
285
     *
286
     * @param int $id The ID of the career to delete
287
     *
288
     * @return bool True if the career could be deleted, false otherwise
289
     */
290
    public function delete($id)
291
    {
292
        $res = parent::delete($id);
293
        if ($res) {
294
            $extraFieldValues = new ExtraFieldValue('career');
295
            $extraFieldValues->deleteValuesByItem($id);
296
            Event::addEvent(
297
                LOG_CAREER_DELETE,
298
                LOG_CAREER_ID,
299
                $id,
300
                api_get_utc_datetime(),
301
                api_get_user_id()
302
            );
303
        }
304
305
        return $res;
306
    }
307
308
    /**
309
     * {@inheritdoc}
310
     */
311
    public function update($params, $showQuery = false)
312
    {
313
        if (isset($params['description'])) {
314
            $params['description'] = Security::remove_XSS($params['description']);
315
        }
316
317
        return parent::update($params, $showQuery);
318
    }
319
320
    /**
321
     * @param array
322
     * @param Graph $graph
323
     *
324
     * @return string
325
     */
326
    public static function renderDiagram($careerInfo, $graph)
327
    {
328
        if (!($graph instanceof Graph)) {
329
            return '';
330
        }
331
332
        // Getting max column
333
        $maxColumn = 0;
334
        foreach ($graph->getVertices() as $vertex) {
335
            $groupId = (int) $vertex->getGroup();
336
            if ($groupId > $maxColumn) {
337
                $maxColumn = $groupId;
338
            }
339
        }
340
341
        $list = [];
342
        /** @var Vertex $vertex */
343
        foreach ($graph->getVertices() as $vertex) {
344
            $group = $vertex->getAttribute('Group');
345
            $groupData = explode(':', $group);
346
            $group = $groupData[0];
347
            $groupLabel = isset($groupData[1]) ? $groupData[1] : '';
348
            $subGroup = $vertex->getAttribute('SubGroup');
349
            $subGroupData = explode(':', $subGroup);
350
            $column = $vertex->getGroup();
351
            $row = $vertex->getAttribute('Row');
352
            $subGroupId = $subGroupData[0];
353
            $label = isset($subGroupData[1]) ? $subGroupData[1] : '';
354
            $list[$group][$subGroupId]['columns'][$column][$row] = $vertex;
355
            $list[$group][$subGroupId]['label'] = $label;
356
            $list[$group]['label'] = $groupLabel;
357
        }
358
359
        $maxGroups = count($list);
360
        $widthGroup = 30;
361
        if (!empty($maxGroups)) {
362
            $widthGroup = 85 / $maxGroups;
363
        }
364
365
        $connections = '';
366
        $groupDrawLine = [];
367
        $groupCourseList = [];
368
        // Read Connections column
369
        foreach ($list as $group => $subGroupList) {
370
            foreach ($subGroupList as $subGroupData) {
371
                $columns = isset($subGroupData['columns']) ? $subGroupData['columns'] : [];
372
                $showGroupLine = true;
373
                if (count($columns) == 1) {
374
                    $showGroupLine = false;
375
                }
376
                $groupDrawLine[$group] = $showGroupLine;
377
378
                //if ($showGroupLine == false) {
379
                /** @var Vertex $vertex */
380
                foreach ($columns as $row => $items) {
381
                    foreach ($items as $vertex) {
382
                        if ($vertex instanceof Vertex) {
383
                            $groupCourseList[$group][] = $vertex->getId();
384
                            $connectionList = $vertex->getAttribute('Connections');
385
                            $firstConnection = '';
386
                            $secondConnection = '';
387
                            if (!empty($connectionList)) {
388
                                $explode = explode('-', $connectionList);
389
                                $pos = strpos($explode[0], 'SG');
390
                                if ($pos === false) {
391
                                    $pos = strpos($explode[0], 'G');
392
                                    if (is_numeric($pos)) {
393
                                        // group_123 id
394
                                        $groupValueId = (int) str_replace(
395
                                            'G',
396
                                            '',
397
                                            $explode[0]
398
                                        );
399
                                        $firstConnection = 'group_'.$groupValueId;
400
                                        $groupDrawLine[$groupValueId] = true;
401
                                    } else {
402
                                        // Course block (row_123 id)
403
                                        if (!empty($explode[0])) {
404
                                            $firstConnection = 'row_'.(int) $explode[0];
405
                                        }
406
                                    }
407
                                } else {
408
                                    // subgroup__123 id
409
                                    $firstConnection = 'subgroup_'.(int) str_replace('SG', '', $explode[0]);
410
                                }
411
412
                                $pos = strpos($explode[1], 'SG');
413
                                if ($pos === false) {
414
                                    $pos = strpos($explode[1], 'G');
415
                                    if (is_numeric($pos)) {
416
                                        $groupValueId = (int) str_replace(
417
                                            'G',
418
                                            '',
419
                                            $explode[1]
420
                                        );
421
                                        $secondConnection = 'group_'.$groupValueId;
422
                                        $groupDrawLine[$groupValueId] = true;
423
                                    } else {
424
                                        // Course block (row_123 id)
425
                                        if (!empty($explode[0])) {
426
                                            $secondConnection = 'row_'.(int) $explode[1];
427
                                        }
428
                                    }
429
                                } else {
430
                                    $secondConnection = 'subgroup_'.(int) str_replace('SG', '', $explode[1]);
431
                                }
432
433
                                if (!empty($firstConnection) && !empty($firstConnection)) {
434
                                    $connections .= self::createConnection(
435
                                        $firstConnection,
436
                                        $secondConnection,
437
                                        ['Left', 'Right']
438
                                    );
439
                                }
440
                            }
441
                        }
442
                    }
443
                }
444
                //}
445
            }
446
        }
447
448
        $graphHtml = '<div class="container">';
449
        foreach ($list as $group => $subGroupList) {
450
            $showGroupLine = false;
451
            if (isset($groupDrawLine[$group]) && $groupDrawLine[$group]) {
452
                $showGroupLine = true;
453
            }
454
            $graphHtml .= self::parseSubGroups(
455
                $groupCourseList,
456
                $group,
457
                $list[$group]['label'],
458
                $showGroupLine,
459
                $subGroupList,
460
                $widthGroup
461
            );
462
        }
463
        $graphHtml .= '</div>';
464
        $graphHtml .= $connections;
465
466
        return $graphHtml;
467
    }
468
469
    /**
470
     * @param array    $careerInfo
471
     * @param Template $tpl
472
     * @param int      $loadUserIdData
473
     *
474
     * @return string
475
     */
476
    public static function renderDiagramByColumn($careerInfo, $tpl, $loadUserIdData = 0)
477
    {
478
        $careerId = isset($careerInfo['id']) ? $careerInfo['id'] : 0;
479
        if (empty($careerId)) {
480
            return '';
481
        }
482
483
        $extraFieldValue = new ExtraFieldValue('career');
484
        $item = $extraFieldValue->get_values_by_handler_and_field_variable(
485
            $careerId,
486
            'career_diagram',
487
            false,
488
            false,
489
            false
490
        );
491
492
        $graph = null;
493
        if (!empty($item) && isset($item['value']) && !empty($item['value'])) {
494
            /** @var Graph $graph */
495
            $graph = UnserializeApi::unserialize('career', $item['value']);
496
        }
497
498
        if (!($graph instanceof Graph)) {
499
            return '';
500
        }
501
502
        // Getting max column
503
        $maxColumn = 0;
504
        foreach ($graph->getVertices() as $vertex) {
505
            $groupId = (int) $vertex->getGroup();
506
            if ($groupId > $maxColumn) {
507
                $maxColumn = $groupId;
508
            }
509
        }
510
511
        $userResult = [];
512
        if (!empty($loadUserIdData)) {
513
            $careerData = UserManager::getUserCareer($loadUserIdData, $careerId);
514
            if (isset($careerData['extra_data']) && !empty($careerData['extra_data'])) {
515
                $userResult = unserialize($careerData['extra_data']);
516
            }
517
        }
518
519
        $list = [];
520
        $subGroups = [];
521
        /** @var Vertex $vertex */
522
        foreach ($graph->getVertices() as $vertex) {
523
            $column = $vertex->getGroup();
524
            $group = $vertex->getAttribute('Group');
525
526
            $groupData = explode(':', $group);
527
            $group = $groupData[0];
528
            $groupLabel = isset($groupData[1]) ? $groupData[1] : '';
529
530
            $subGroup = $vertex->getAttribute('SubGroup');
531
            $subGroupData = explode(':', $subGroup);
532
533
            $row = $vertex->getAttribute('Row');
534
            $subGroupId = $subGroupData[0];
535
            $subGroupLabel = isset($subGroupData[1]) ? $subGroupData[1] : '';
536
537
            if (!empty($subGroupId) && !in_array($subGroupId, $subGroups)) {
538
                $subGroups[$subGroupId]['items'][] = $vertex->getId();
539
                $subGroups[$subGroupId]['label'] = $subGroupLabel;
540
            }
541
542
            $list[$column]['rows'][$row]['items'][] = $vertex;
543
            $list[$column]['rows'][$row]['label'] = $subGroupId;
544
            $list[$column]['rows'][$row]['group'] = $group;
545
            $list[$column]['rows'][$row]['group_label'] = $groupLabel;
546
            $list[$column]['rows'][$row]['subgroup'] = $subGroup;
547
            $list[$column]['rows'][$row]['subgroup_label'] = $subGroupLabel;
548
            $list[$column]['label'] = $groupLabel;
549
            $list[$column]['column'] = $column;
550
        }
551
552
        $groupCourseList = [];
553
        $simpleConnectionList = [];
554
555
        // Read Connections column
556
        foreach ($list as $column => $groupList) {
557
            foreach ($groupList['rows'] as $subGroupList) {
558
                /** @var Vertex $vertex */
559
                foreach ($subGroupList['items'] as $vertex) {
560
                    if ($vertex instanceof Vertex) {
561
                        $groupCourseList[$vertex->getAttribute('Column')][] = $vertex->getId();
562
                        $connectionList = $vertex->getAttribute('Connections');
563
                        if (empty($connectionList)) {
564
                            continue;
565
                        }
566
                        $simpleFirstConnection = '';
567
                        $simpleSecondConnection = '';
568
569
                        $explode = explode('-', $connectionList);
570
                        $pos = strpos($explode[0], 'SG');
571
                        if ($pos === false) {
572
                            $pos = strpos($explode[0], 'G');
573
                            if (is_numeric($pos)) {
574
                                // Is group
575
                                $groupValueId = (int) str_replace(
576
                                    'G',
577
                                    '',
578
                                    $explode[0]
579
                                );
580
                                $simpleFirstConnection = 'g'.(int) $groupValueId;
581
                            } else {
582
                                // Course block (row_123 id)
583
                                if (!empty($explode[0])) {
584
                                    $simpleFirstConnection = 'v'.$explode[0];
585
                                }
586
                            }
587
                        } else {
588
                            // subgroup__123 id
589
                            $simpleFirstConnection = 'sg'.(int) str_replace('SG', '', $explode[0]);
590
                        }
591
592
                        $pos = false;
593
                        if (isset($explode[1])) {
594
                            $pos = strpos($explode[1], 'SG');
595
                        }
596
                        if ($pos === false) {
597
                            if (isset($explode[1])) {
598
                                $pos = strpos($explode[1], 'G');
599
                                $value = $explode[1];
600
                            }
601
                            if (is_numeric($pos)) {
602
                                $groupValueId = (int) str_replace(
603
                                    'G',
604
                                    '',
605
                                    $value
606
                                );
607
                                $simpleSecondConnection = 'g'.(int) $groupValueId;
608
                            } else {
609
                                // Course block (row_123 id)
610
                                if (!empty($explode[0]) && isset($explode[1])) {
611
                                    $simpleSecondConnection = 'v'.(int) $explode[1];
612
                                }
613
                            }
614
                        } else {
615
                            $simpleSecondConnection = 'sg'.(int) str_replace('SG', '', $explode[1]);
616
                        }
617
618
                        if (!empty($simpleFirstConnection) && !empty($simpleSecondConnection)) {
619
                            $simpleConnectionList[] = [
620
                                'from' => $simpleFirstConnection,
621
                                'to' => $simpleSecondConnection,
622
                            ];
623
                        }
624
                    }
625
                }
626
            }
627
        }
628
629
        $graphHtml = '';
630
        $groupsBetweenColumns = [];
631
        foreach ($list as $column => $columnList) {
632
            foreach ($columnList['rows'] as $subGroupList) {
633
                $newGroup = $subGroupList['group'];
634
                $label = $subGroupList['group_label'];
635
                $newOrder[$newGroup]['items'][] = $subGroupList;
636
                $newOrder[$newGroup]['label'] = $label;
637
                $groupsBetweenColumns[$newGroup][] = $subGroupList;
638
            }
639
        }
640
641
        // Creates graph
642
        $graph = new stdClass();
643
        $graph->blockWidth = 280;
644
        $graph->blockHeight = 150;
645
646
        $graph->xGap = 70;
647
        $graph->yGap = 55;
648
649
        $graph->xDiff = 70;
650
        $graph->yDiff = 55;
651
652
        if (!empty($userResult)) {
653
            $graph->blockHeight = 180;
654
            $graph->yGap = 60;
655
            $graph->yDiff = 60;
656
        }
657
658
        foreach ($groupsBetweenColumns as $group => $items) {
659
            self::parseColumnList($groupCourseList, $items, $graph, $simpleConnectionList, $userResult);
660
        }
661
662
        $graphHtml .= '<style>
663
             .panel-title {
664
                font-size: 11px;
665
                height: 40px;
666
             }
667
668
             .panel-body{
669
                min-height: 55px;
670
             }
671
             </style>';
672
673
        // Create groups
674
        if (!empty($graph->groupList)) {
675
            $groupList = [];
676
            $groupDiffX = 20;
677
            $groupDiffY = 50;
678
            $style = 'whiteSpace=wrap;rounded;html=1;strokeColor=red;fillColor=none;strokeWidth=2;align=left;verticalAlign=top;';
679
            foreach ($graph->groupList as $id => $data) {
680
                if (empty($id)) {
681
                    continue;
682
                }
683
684
                $x = $data['min_x'] - $groupDiffX;
685
                $y = $data['min_y'] - $groupDiffY;
686
                $width = $data['max_width'] + ($groupDiffX * 2);
687
                $height = $data['max_height'] + $groupDiffY * 2;
688
                $label = '<h4>'.$data['label'].'</h4>';
689
                $vertexData = "var g$id = graph.insertVertex(parent, null, '$label', $x, $y, $width, $height, '$style');";
690
                $groupList[] = $vertexData;
691
            }
692
            $tpl->assign('group_list', $groupList);
693
        }
694
695
        // Create subgroups
696
        $subGroupList = [];
697
        $subGroupListData = [];
698
        foreach ($subGroups as $subGroupId => $vertexData) {
699
            $label = $vertexData['label'];
700
            $vertexIdList = $vertexData['items'];
701
            foreach ($vertexIdList as $rowId) {
702
                $data = $graph->allData[$rowId];
703
                $originalRow = $data['row'];
704
                $column = $data['column'];
705
                $x = $data['x'];
706
                $y = $data['y'];
707
                $width = $data['width'];
708
                $height = $data['height'];
709
710
                if (!isset($subGroupListData[$subGroupId])) {
711
                    $subGroupListData[$subGroupId]['min_x'] = 1000;
712
                    $subGroupListData[$subGroupId]['min_y'] = 1000;
713
                    $subGroupListData[$subGroupId]['max_width'] = 0;
714
                    $subGroupListData[$subGroupId]['max_height'] = 0;
715
                    $subGroupListData[$subGroupId]['label'] = $label;
716
                }
717
718
                if ($x < $subGroupListData[$subGroupId]['min_x']) {
719
                    $subGroupListData[$subGroupId]['min_x'] = $x;
720
                }
721
722
                if ($y < $subGroupListData[$subGroupId]['min_y']) {
723
                    $subGroupListData[$subGroupId]['min_y'] = $y;
724
                }
725
726
                $subGroupListData[$subGroupId]['max_width'] = ($column + 1) * ($width + $graph->xGap) - $subGroupListData[$subGroupId]['min_x'];
727
                $subGroupListData[$subGroupId]['max_height'] = ($originalRow + 1) * ($height + $graph->yGap) - $subGroupListData[$subGroupId]['min_y'];
728
            }
729
730
            $style = 'whiteSpace=wrap;rounded;dashed=1;strokeColor=blue;fillColor=none;strokeWidth=2;align=left;verticalAlign=bottom;';
731
            $subGroupDiffX = 5;
732
            foreach ($subGroupListData as $subGroupId => $data) {
733
                $x = $data['min_x'] - $subGroupDiffX;
734
                $y = $data['min_y'] - $subGroupDiffX;
735
736
                $spaceForSubGroupTitle = 0;
737
                if (!empty($data['label'])) {
738
                    $spaceForSubGroupTitle = 40;
739
                }
740
741
                $width = $data['max_width'] + $subGroupDiffX * 2;
742
                $height = $data['max_height'] + $subGroupDiffX * 2 + $spaceForSubGroupTitle;
743
744
                $label = '<h4 style="background: white">'.$data['label'].'</h4>';
745
                $vertexData = "var sg$subGroupId = graph.insertVertex(parent, null, '$label', $x, $y, $width, $height, '$style');";
746
                $subGroupList[] = $vertexData;
747
            }
748
        }
749
750
        // Create connections (arrows)
751
        if (!empty($simpleConnectionList)) {
752
            $connectionList = [];
753
            //$style = 'endArrow=classic;html=1;strokeWidth=4;exitX=1;exitY=0.5;entryX=0;entryY=0.5;';
754
            $style = '';
755
            foreach ($simpleConnectionList as $connection) {
756
                $from = $connection['from'];
757
                $to = $connection['to'];
758
                $vertexData = "var e1 = graph.insertEdge(parent, null, '', $from, $to, '$style')";
759
                $connectionList[] = $vertexData;
760
            }
761
            $tpl->assign('connections', $connectionList);
762
        }
763
764
        $tpl->assign('subgroup_list', $subGroupList);
765
        $tpl->assign('vertex_list', $graph->elementList);
766
767
        $graphHtml .= '<div id="graphContainer"></div>';
768
769
        return $graphHtml;
770
    }
771
772
    /**
773
     * @param $groupCourseList
774
     * @param $columnList
775
     * @param $graph
776
     * @param $connections
777
     * @param $userResult
778
     *
779
     * @return string
780
     */
781
    public static function parseColumnList($groupCourseList, $columnList, &$graph, &$connections, $userResult)
782
    {
783
        $graphHtml = '';
784
        $oldGroup = null;
785
        $newOrder = [];
786
        foreach ($columnList as $key => $subGroupList) {
787
            $newGroup = $subGroupList['group'];
788
            $label = $subGroupList['group_label'];
789
            $newOrder[$newGroup]['items'][] = $subGroupList;
790
            $newOrder[$newGroup]['label'] = $label;
791
        }
792
793
        foreach ($newOrder as $newGroup => $data) {
794
            $label = $data['label'];
795
            $subGroupList = $data['items'];
796
797
            if (!isset($graph->groupList[$newGroup])) {
798
                $graph->groupList[$newGroup]['min_x'] = 1000;
799
                $graph->groupList[$newGroup]['min_y'] = 1000;
800
                $graph->groupList[$newGroup]['max_width'] = 0;
801
                $graph->groupList[$newGroup]['max_height'] = 0;
802
                $graph->groupList[$newGroup]['label'] = $label;
803
            }
804
805
            $maxColumn = 0;
806
            $maxRow = 0;
807
            $minColumn = 100;
808
            $minRow = 100;
809
            foreach ($subGroupList as $item) {
810
                /** @var Vertex $vertex */
811
                foreach ($item['items'] as $vertex) {
812
                    $column = $vertex->getAttribute('Column');
813
                    $realRow = $vertex->getAttribute('Row');
814
815
                    if ($column > $maxColumn) {
816
                        $maxColumn = $column;
817
                    }
818
                    if ($realRow > $maxRow) {
819
                        $maxRow = $realRow;
820
                    }
821
822
                    if ($column < $minColumn) {
823
                        $minColumn = $column;
824
                    }
825
                    if ($realRow < $minRow) {
826
                        $minRow = $realRow;
827
                    }
828
                }
829
            }
830
831
            if (!empty($newGroup)) {
832
                $graphHtml .= '<div
833
                    id ="group_'.$newGroup.'"
834
                    class="group'.$newGroup.' group_class"
835
                    style="display:grid;
836
                        align-self: start;
837
                        grid-gap: 10px;
838
                        justify-items: stretch;
839
                        align-items: start;
840
                        align-content: start;
841
                        justify-content: stretch;
842
                        grid-area:'.$minRow.'/'.$minColumn.'/'.$maxRow.'/'.$maxColumn.'">'; //style="display:grid"
843
            }
844
845
            $addRow = 0;
846
            if (!empty($label)) {
847
                $graphHtml .= "<div class='my_label' style='grid-area:$minRow/$minColumn/$maxRow/$maxColumn'>$label</div>";
848
                $addRow = 1;
849
            }
850
851
            foreach ($subGroupList as $item) {
852
                $graphHtml .= self::parseVertexList(
853
                    $groupCourseList,
854
                    $item['items'],
855
                    $addRow,
856
                    $graph,
857
                    $newGroup,
858
                    $connections,
859
                    $userResult
860
                );
861
            }
862
863
            if (!empty($newGroup)) {
864
                $graphHtml .= '</div >';
865
            }
866
        }
867
868
        return $graphHtml;
869
    }
870
871
    /**
872
     * @param array    $groupCourseList
873
     * @param array    $vertexList
874
     * @param int      $addRow
875
     * @param stdClass $graph
876
     * @param int      $group
877
     * @param array    $connections
878
     * @param array    $userResult
879
     *
880
     * @return string
881
     */
882
    public static function parseVertexList($groupCourseList, $vertexList, $addRow, &$graph, $group, &$connections, $userResult)
883
    {
884
        if (empty($vertexList)) {
885
            return '';
886
        }
887
888
        $graphHtml = '';
889
        /** @var Vertex $vertex */
890
        foreach ($vertexList as $vertex) {
891
            $borderColor = 'green';
892
            $column = $vertex->getAttribute('Column');
893
            $realRow = $originalRow = $vertex->getAttribute('Row');
894
            if ($addRow) {
895
                $realRow = $realRow + $addRow;
896
            }
897
            $id = $vertex->getId();
898
            $area = "$realRow/$column";
899
            $graphHtml .= '<div
900
                id = "row_wrapper_'.$id.'"
901
                data= "'.$originalRow.'-'.$column.'"
902
                style="
903
                    align-self: start;
904
                    justify-content: stretch;
905
                    grid-area:'.$area.'"
906
            >';
907
            $color = '';
908
            if (!empty($vertex->getAttribute('DefinedColor'))) {
909
                $color = $vertex->getAttribute('DefinedColor');
910
            }
911
            $content = '<div class="pull-left">'.$vertex->getAttribute('Notes').'</div>';
912
            $content .= '<div class="pull-right">['.$id.']</div>';
913
914
            if (!empty($userResult) && isset($userResult[$id])) {
915
                $lastItem = end($userResult[$id]);
916
                if ($lastItem && isset($lastItem['BgColor']) && !empty($lastItem['BgColor'])) {
917
                    $color = $lastItem['BgColor'].'; color: '.$lastItem['Color'];
918
                    $borderColor = $lastItem['BorderColor'];
919
                }
920
                $results = '';
921
                $size = 2;
922
                foreach ($userResult[$id] as $resultId => $iconData) {
923
                    $icon = '';
924
                    switch ($iconData['Icon']) {
925
                        case 0:
926
                            $icon = Display::returnFontAwesomeIcon('times-circle', $size);
927
                            break;
928
                        case 1:
929
                            $icon = Display::returnFontAwesomeIcon('check-circle', $size);
930
                            break;
931
                        case 2:
932
                            $icon = Display::returnFontAwesomeIcon('info-circle', $size);
933
                            break;
934
                    }
935
936
                    if (substr($resultId, 0, 1) == 2) {
937
                        $iconData['Description'] = 'Result Id = '.$resultId;
938
                    }
939
940
                    if ('Joe Anonymous' === $iconData['TeacherUsername']) {
941
                        $iconData['TeacherUsername'] = '';
942
                    }
943
944
                    if (!empty($icon)) {
945
                        $params = [
946
                            'id' => 'course_'.$id.'_'.$resultId,
947
                            'data-toggle' => 'popover',
948
                            'title' => 'Popover title',
949
                            'class' => 'popup',
950
                            'data-description' => $iconData['Description'],
951
                            'data-period' => $iconData['Period'],
952
                            'data-teacher-text' => $iconData['TeacherText'],
953
                            'data-teacher' => $iconData['TeacherUsername'],
954
                            'data-score' => $iconData['ScoreText'],
955
                            'data-score-value' => $iconData['ScoreValue'],
956
                            'data-info' => $iconData['Info'],
957
                            'data-background-color' => $iconData['BgColor'],
958
                            'data-color' => $iconData['Color'],
959
                            'data-border-color' => $iconData['BorderColor'],
960
                            'style' => 'color:'.$iconData['IconColor'],
961
                        ];
962
                        $results .= Display::url($icon, 'javascript:void(0);', $params);
963
                    }
964
                }
965
966
                if (!empty($results)) {
967
                    $content .= '<div class="row"></div><div class="pull-left">'.$results.'</div>';
968
                }
969
            }
970
971
            $title = $vertex->getAttribute('graphviz.label');
972
            if (!empty($vertex->getAttribute('LinkedElement'))) {
973
                $title = Display::url($title, $vertex->getAttribute('LinkedElement'));
974
            }
975
976
            $originalRow--;
977
            $column--;
978
979
            $graphHtml .= Display::panel(
980
                $content,
981
                $title,
982
                null,
983
                null,
984
                null,
985
                "row_$id",
986
                $color
987
            );
988
989
            $panel = Display::panel(
990
                $content,
991
                $title,
992
                null,
993
                null,
994
                null,
995
                "row_$id",
996
                $color
997
            );
998
999
            $x = $column * $graph->blockWidth + $graph->xDiff;
1000
            $y = $originalRow * $graph->blockHeight + $graph->yDiff;
1001
1002
            $width = $graph->blockWidth - $graph->xGap;
1003
            $height = $graph->blockHeight - $graph->yGap;
1004
1005
            $style = 'text;html=1;strokeColor='.$borderColor.';fillColor=#ffffff;overflow=fill;rounded=0;align=left;';
1006
1007
            $panel = str_replace(["\n", "\r"], '', $panel);
1008
            $vertexData = "var v$id = graph.insertVertex(parent, null, '".addslashes($panel)."', $x, $y, $width, $height, '$style');";
1009
1010
            $graph->elementList[$id] = $vertexData;
1011
            $graph->allData[$id] = [
1012
                'x' => $x,
1013
                'y' => $y,
1014
                'width' => $width,
1015
                'height' => $height,
1016
                'row' => $originalRow,
1017
                'column' => $column,
1018
                'label' => $title,
1019
            ];
1020
1021
            if ($x < $graph->groupList[$group]['min_x']) {
1022
                $graph->groupList[$group]['min_x'] = $x;
1023
            }
1024
1025
            if ($y < $graph->groupList[$group]['min_y']) {
1026
                $graph->groupList[$group]['min_y'] = $y;
1027
            }
1028
1029
            $graph->groupList[$group]['max_width'] = ($column + 1) * ($width + $graph->xGap) - $graph->groupList[$group]['min_x'];
1030
            $graph->groupList[$group]['max_height'] = ($originalRow + 1) * ($height + ($graph->yGap)) - $graph->groupList[$group]['min_y'];
1031
1032
            $graphHtml .= '</div>';
1033
            $arrow = $vertex->getAttribute('DrawArrowFrom');
1034
            $found = false;
1035
            if (!empty($arrow)) {
1036
                $pos = strpos($arrow, 'SG');
1037
                if ($pos === false) {
1038
                    $pos = strpos($arrow, 'G');
1039
                    if (is_numeric($pos)) {
1040
                        $parts = explode('G', $arrow);
1041
                        if (empty($parts[0]) && count($parts) == 2) {
1042
                            $groupArrow = $parts[1];
1043
                            $graphHtml .= self::createConnection(
1044
                                "group_$groupArrow",
1045
                                "row_$id",
1046
                                ['Left', 'Right']
1047
                            );
1048
                            $found = true;
1049
                            $connections[] = [
1050
                              'from' => "g$groupArrow",
1051
                              'to' => "v$id",
1052
                            ];
1053
                        }
1054
                    }
1055
                } else {
1056
                    // Case is only one subgroup value example: SG1
1057
                    $parts = explode('SG', $arrow);
1058
                    if (empty($parts[0]) && count($parts) == 2) {
1059
                        $subGroupArrow = $parts[1];
1060
                        $graphHtml .= self::createConnection(
1061
                            "subgroup_$subGroupArrow",
1062
                            "row_$id",
1063
                            ['Left', 'Right']
1064
                        );
1065
                        $found = true;
1066
                        $connections[] = [
1067
                            'from' => "sg$subGroupArrow",
1068
                            'to' => "v$id",
1069
                        ];
1070
                    }
1071
                }
1072
1073
                if ($found == false) {
1074
                    // case is connected to 2 subgroups: Example SG1-SG2
1075
                    $parts = explode('-', $arrow);
1076
                    if (count($parts) == 2 && !empty($parts[0]) && !empty($parts[1])) {
1077
                        $defaultArrow = ['Top', 'Bottom'];
1078
                        $firstPrefix = '';
1079
                        $firstId = '';
1080
                        $secondId = '';
1081
                        $secondPrefix = '';
1082
                        if (is_numeric($pos = strpos($parts[0], 'SG'))) {
1083
                            $firstPrefix = 'sg';
1084
                            $firstId = str_replace('SG', '', $parts[0]);
1085
                        }
1086
1087
                        if (is_numeric($pos = strpos($parts[1], 'SG'))) {
1088
                            $secondPrefix = 'sg';
1089
                            $secondId = str_replace('SG', '', $parts[1]);
1090
                        }
1091
                        if (!empty($secondId) && !empty($firstId)) {
1092
                            $connections[] = [
1093
                                'from' => $firstPrefix.$firstId,
1094
                                'to' => $secondPrefix.$secondId,
1095
                                $defaultArrow,
1096
                            ];
1097
                            $found = true;
1098
                        }
1099
                    }
1100
                }
1101
1102
                if ($found == false) {
1103
                    // case DrawArrowFrom is an integer
1104
                    $defaultArrow = ['Left', 'Right'];
1105
                    if (isset($groupCourseList[$column]) &&
1106
                        in_array($arrow, $groupCourseList[$column])
1107
                    ) {
1108
                        $defaultArrow = ['Top', 'Bottom'];
1109
                    }
1110
                    $graphHtml .= self::createConnection(
1111
                        "row_$arrow",
1112
                        "row_$id",
1113
                        $defaultArrow
1114
                    );
1115
1116
                    $connections[] = [
1117
                        'from' => "v$arrow",
1118
                        'to' => "v$id",
1119
                    ];
1120
                }
1121
            }
1122
        }
1123
1124
        return $graphHtml;
1125
    }
1126
1127
    /**
1128
     * @param array  $groupCourseList list of groups and their courses
1129
     * @param int    $group
1130
     * @param string $groupLabel
1131
     * @param bool   $showGroupLine
1132
     * @param array  $subGroupList
1133
     * @param $widthGroup
1134
     *
1135
     * @return string
1136
     */
1137
    public static function parseSubGroups(
1138
        $groupCourseList,
1139
        $group,
1140
        $groupLabel,
1141
        $showGroupLine,
1142
        $subGroupList,
1143
        $widthGroup
1144
    ) {
1145
        $topValue = 90;
1146
        $defaultSpace = 40;
1147
        $leftGroup = $defaultSpace.'px';
1148
        if ($group == 1) {
1149
            $leftGroup = 0;
1150
        }
1151
1152
        $groupIdTag = "group_$group";
1153
        $borderLine = $showGroupLine === true ? 'border-style:solid;' : '';
1154
1155
        $graphHtml = '<div
1156
            id="'.$groupIdTag.'" class="career_group"
1157
            style=" '.$borderLine.' padding:15px; float:left; margin-left:'.$leftGroup.'; width:'.$widthGroup.'%">';
1158
1159
        if (!empty($groupLabel)) {
1160
            $graphHtml .= '<h3>'.$groupLabel.'</h3>';
1161
        }
1162
1163
        foreach ($subGroupList as $subGroup => $subGroupData) {
1164
            $subGroupLabel = isset($subGroupData['label']) ? $subGroupData['label'] : '';
1165
            $columnList = isset($subGroupData['columns']) ? $subGroupData['columns'] : [];
1166
1167
            if (empty($columnList)) {
1168
                continue;
1169
            }
1170
1171
            $line = '';
1172
            if (!empty($subGroup)) {
1173
                $line = 'border-style:solid;';
1174
            }
1175
1176
            // padding:15px;
1177
            $graphHtml .= '<div
1178
                id="subgroup_'.$subGroup.'" class="career_subgroup"
1179
                style="'.$line.' margin-bottom:20px; padding:15px; float:left; margin-left:0px; width:100%">';
1180
            if (!empty($subGroupLabel)) {
1181
                $graphHtml .= '<h3>'.$subGroupLabel.'</h3>';
1182
            }
1183
            foreach ($columnList as $column => $rows) {
1184
                $leftColumn = $defaultSpace.'px';
1185
                if ($column == 1) {
1186
                    $leftColumn = 0;
1187
                }
1188
                if (count($columnList) == 1) {
1189
                    $leftColumn = 0;
1190
                }
1191
1192
                $widthColumn = 85 / count($columnList);
1193
                $graphHtml .= '<div
1194
                    id="col_'.$column.'" class="career_column"
1195
                    style="padding:15px;float:left; margin-left:'.$leftColumn.'; width:'.$widthColumn.'%">';
1196
                $maxRow = 0;
1197
                foreach ($rows as $row => $vertex) {
1198
                    if ($row > $maxRow) {
1199
                        $maxRow = $row;
1200
                    }
1201
                }
1202
1203
                $newRowList = [];
1204
                $defaultSubGroup = -1;
1205
                $subGroupCountList = [];
1206
                for ($i = 0; $i < $maxRow; $i++) {
1207
                    /** @var Vertex $vertex */
1208
                    $vertex = isset($rows[$i + 1]) ? $rows[$i + 1] : null;
1209
                    if (!is_null($vertex)) {
1210
                        $subGroup = $vertex->getAttribute('SubGroup');
1211
                        if ($subGroup == '' || empty($subGroup)) {
1212
                            $defaultSubGroup = 0;
1213
                        } else {
1214
                            $defaultSubGroup = (int) $subGroup;
1215
                        }
1216
                    }
1217
                    $newRowList[$i + 1][$defaultSubGroup][] = $vertex;
1218
                    if (!isset($subGroupCountList[$defaultSubGroup])) {
1219
                        $subGroupCountList[$defaultSubGroup] = 1;
1220
                    } else {
1221
                        $subGroupCountList[$defaultSubGroup]++;
1222
                    }
1223
                }
1224
1225
                $subGroup = null;
1226
                $subGroupAdded = [];
1227
                /** @var Vertex $vertex */
1228
                foreach ($newRowList as $row => $subGroupList) {
1229
                    foreach ($subGroupList as $subGroup => $vertexList) {
1230
                        if (!empty($subGroup) && $subGroup != -1) {
1231
                            if (!isset($subGroupAdded[$subGroup])) {
1232
                                $subGroupAdded[$subGroup] = 1;
1233
                            } else {
1234
                                $subGroupAdded[$subGroup]++;
1235
                            }
1236
                        }
1237
1238
                        foreach ($vertexList as $vertex) {
1239
                            if (is_null($vertex)) {
1240
                                $graphHtml .= '<div class="career_empty" style="height: 130px">';
1241
                                $graphHtml .= '</div>';
1242
                                continue;
1243
                            }
1244
1245
                            $id = $vertex->getId();
1246
                            $rowId = "row_$row";
1247
                            $graphHtml .= '<div id = "row_'.$id.'" class="'.$rowId.' career_row" >';
1248
                            $color = '';
1249
                            if (!empty($vertex->getAttribute('DefinedColor'))) {
1250
                                $color = $vertex->getAttribute('DefinedColor');
1251
                            }
1252
                            $content = $vertex->getAttribute('Notes');
1253
                            $content .= '<div class="pull-right">['.$id.']</div>';
1254
1255
                            $title = $vertex->getAttribute('graphviz.label');
1256
                            if (!empty($vertex->getAttribute('LinkedElement'))) {
1257
                                $title = Display::url($title, $vertex->getAttribute('LinkedElement'));
1258
                            }
1259
1260
                            $graphHtml .= Display::panel(
1261
                                $content,
1262
                                $title,
1263
                                null,
1264
                                null,
1265
                                null,
1266
                                null,
1267
                                $color
1268
                            );
1269
                            $graphHtml .= '</div>';
1270
1271
                            $arrow = $vertex->getAttribute('DrawArrowFrom');
1272
                            $found = false;
1273
                            if (!empty($arrow)) {
1274
                                $pos = strpos($arrow, 'SG');
1275
                                if ($pos === false) {
1276
                                    $pos = strpos($arrow, 'G');
1277
                                    if (is_numeric($pos)) {
1278
                                        $parts = explode('G', $arrow);
1279
                                        if (empty($parts[0]) && count($parts) == 2) {
1280
                                            $groupArrow = $parts[1];
1281
                                            $graphHtml .= self::createConnection(
1282
                                                "group_$groupArrow",
1283
                                                "row_$id",
1284
                                                ['Left', 'Right']
1285
                                            );
1286
                                            $found = true;
1287
                                        }
1288
                                    }
1289
                                } else {
1290
                                    $parts = explode('SG', $arrow);
1291
                                    if (empty($parts[0]) && count($parts) == 2) {
1292
                                        $subGroupArrow = $parts[1];
1293
                                        $graphHtml .= self::createConnection(
1294
                                            "subgroup_$subGroupArrow",
1295
                                            "row_$id",
1296
                                            ['Left', 'Right']
1297
                                        );
1298
                                        $found = true;
1299
                                    }
1300
                                }
1301
                            }
1302
1303
                            if ($found == false) {
1304
                                $defaultArrow = ['Left', 'Right'];
1305
                                if (isset($groupCourseList[$group]) &&
1306
                                    in_array($arrow, $groupCourseList[$group])
1307
                                ) {
1308
                                    $defaultArrow = ['Top', 'Bottom'];
1309
                                }
1310
                                $graphHtml .= self::createConnection(
1311
                                    "row_$arrow",
1312
                                    "row_$id",
1313
                                    $defaultArrow
1314
                                );
1315
                            }
1316
                        }
1317
                    }
1318
                }
1319
                $graphHtml .= '</div>';
1320
            }
1321
            $graphHtml .= '</div>';
1322
        }
1323
        $graphHtml .= '</div>';
1324
1325
        return $graphHtml;
1326
    }
1327
1328
    /**
1329
     * @param string $source
1330
     * @param string $target
1331
     * @param array  $anchor
1332
     *
1333
     * @return string
1334
     */
1335
    public static function createConnection($source, $target, $anchor = [])
1336
    {
1337
        if (empty($anchor)) {
1338
            // Default
1339
            $anchor = ['Bottom', 'Right'];
1340
        }
1341
1342
        $anchor = implode('","', $anchor);
1343
        $html = '<script>
1344
1345
        var connectorPaintStyle = {
1346
            strokeWidth: 2,
1347
            stroke: "#a31ed3",
1348
            joinstyle: "round",
1349
            outlineStroke: "white",
1350
            outlineWidth: 2
1351
        },
1352
        // .. and this is the hover style.
1353
        connectorHoverStyle = {
1354
            strokeWidth: 3,
1355
            stroke: "#216477",
1356
            outlineWidth: 5,
1357
            outlineStroke: "white"
1358
        },
1359
        endpointHoverStyle = {
1360
            fill: "#E80CAF",
1361
            stroke: "#E80CAF"
1362
        };
1363
        jsPlumb.ready(function() { ';
1364
        $html .= 'jsPlumb.connect({
1365
            source:"'.$source.'",
1366
            target:"'.$target.'",
1367
            endpoint:[ "Rectangle", { width:1, height:1 }],
1368
            connector: ["Flowchart"],
1369
            paintStyle: connectorPaintStyle,
1370
            hoverPaintStyle: endpointHoverStyle,
1371
            anchor: ["'.$anchor.'"],
1372
            overlays: [
1373
                [
1374
                    "Arrow",
1375
                    {
1376
                        location:1,
1377
                        width:11,
1378
                        length:11
1379
                    }
1380
                ],
1381
            ],
1382
        });';
1383
        $html .= '});</script>'.PHP_EOL;
1384
1385
        return $html;
1386
    }
1387
}
1388