Completed
Push — master ( 7bef58...5c053f )
by Julito
25:30
created

Career::renderDiagramByColumn()   F

Complexity

Conditions 39
Paths > 20000

Size

Total Lines 292
Code Lines 184

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 39
eloc 184
c 0
b 0
f 0
nop 2
dl 0
loc 292
rs 2
nc 1440505

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Fhaculty\Graph\Graph;
5
use Fhaculty\Graph\Vertex;
6
7
/**
8
 * Class Career.
9
 */
10
class Career extends Model
11
{
12
    public $table;
13
    public $columns = [
14
        'id',
15
        'name',
16
        'description',
17
        'status',
18
        'created_at',
19
        'updated_at',
20
    ];
21
22
    /**
23
     * Constructor.
24
     */
25
    public function __construct()
26
    {
27
        $this->table = Database::get_main_table(TABLE_CAREER);
28
    }
29
30
    /**
31
     * Get the count of elements.
32
     *
33
     * @return int
34
     */
35
    public function get_count()
36
    {
37
        $row = Database::select(
38
            'count(*) as count',
39
            $this->table,
40
            [],
41
            'first'
42
        );
43
44
        return $row['count'];
45
    }
46
47
    /**
48
     * @param array $where_conditions
49
     *
50
     * @return array
51
     */
52
    public function get_all($where_conditions = [])
53
    {
54
        return Database::select(
55
            '*',
56
            $this->table,
57
            ['where' => $where_conditions, 'order' => 'name ASC']
58
        );
59
    }
60
61
    /**
62
     * Update all promotion status by career.
63
     *
64
     * @param int $career_id
65
     * @param int $status    (1 or 0)
66
     */
67
    public function update_all_promotion_status_by_career_id($career_id, $status)
68
    {
69
        $promotion = new Promotion();
70
        $promotion_list = $promotion->get_all_promotions_by_career_id($career_id);
71
        if (!empty($promotion_list)) {
72
            foreach ($promotion_list as $item) {
73
                $params['id'] = $item['id'];
74
                $params['status'] = $status;
75
                $promotion->update($params);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $params seems to be defined later in this foreach loop on line 73. Are you sure it is defined here?
Loading history...
76
                $promotion->update_all_sessions_status_by_promotion_id($params['id'], $status);
77
            }
78
        }
79
    }
80
81
    /**
82
     * Returns HTML the title + grid.
83
     *
84
     * @return string
85
     */
86
    public function display()
87
    {
88
        $html = '<div class="actions" style="margin-bottom:20px">';
89
        $html .= '<a href="career_dashboard.php">'.
90
            Display::return_icon('back.png', get_lang('Back'), '', ICON_SIZE_MEDIUM).'</a>';
91
        if (api_is_platform_admin()) {
92
            $html .= '<a href="'.api_get_self().'?action=add">'.
93
                    Display::return_icon('new_career.png', get_lang('Add'), '', ICON_SIZE_MEDIUM).'</a>';
94
        }
95
        $html .= '</div>';
96
        $html .= Display::grid_html('careers');
97
98
        return $html;
99
    }
100
101
    /**
102
     * @return array
103
     */
104
    public function get_status_list()
105
    {
106
        return [
107
            CAREER_STATUS_ACTIVE => get_lang('Unarchived'),
108
            CAREER_STATUS_INACTIVE => get_lang('Archived'),
109
        ];
110
    }
111
112
    /**
113
     * Returns a Form validator Obj.
114
     *
115
     * @todo the form should be auto generated
116
     *
117
     * @param string $url
118
     * @param string $action add, edit
119
     *
120
     * @return FormValidator
121
     */
122
    public function return_form($url, $action)
123
    {
124
        $form = new FormValidator('career', 'post', $url);
125
        // Setting the form elements
126
        $header = get_lang('Add');
127
        if ($action == 'edit') {
128
            $header = get_lang('Modify');
129
        }
130
131
        $id = isset($_GET['id']) ? intval($_GET['id']) : '';
132
        $form->addHeader($header);
133
        $form->addHidden('id', $id);
134
        $form->addElement('text', 'name', get_lang('Name'), ['size' => '70']);
135
        $form->addHtmlEditor(
136
            'description',
137
            get_lang('Description'),
138
            false,
139
            false,
140
            [
141
                'ToolbarSet' => 'Careers',
142
                'Width' => '100%',
143
                'Height' => '250',
144
            ]
145
        );
146
        $status_list = $this->get_status_list();
147
        $form->addElement('select', 'status', get_lang('Status'), $status_list);
148
        if ($action == 'edit') {
149
            $form->addElement('text', 'created_at', get_lang('CreatedAt'));
150
            $form->freeze('created_at');
151
        }
152
        if ($action == 'edit') {
153
            $form->addButtonSave(get_lang('Modify'), 'submit');
154
        } else {
155
            $form->addButtonCreate(get_lang('Add'), 'submit');
156
        }
157
158
        // Setting the defaults
159
        $defaults = $this->get($id);
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type string; however, parameter $id of Model::get() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

159
        $defaults = $this->get(/** @scrutinizer ignore-type */ $id);
Loading history...
160
161
        if (!empty($defaults['created_at'])) {
162
            $defaults['created_at'] = api_convert_and_format_date($defaults['created_at']);
163
        }
164
        if (!empty($defaults['updated_at'])) {
165
            $defaults['updated_at'] = api_convert_and_format_date($defaults['updated_at']);
166
        }
167
168
        $form->setDefaults($defaults);
169
170
        // Setting the rules
171
        $form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
172
173
        return $form;
174
    }
175
176
    /**
177
     * Copies the career to a new one.
178
     *
179
     * @param   int     Career ID
180
     * @param   bool     Whether or not to copy the promotions inside
181
     *
182
     * @return int New career ID on success, false on failure
183
     */
184
    public function copy($id, $copy_promotions = false)
185
    {
186
        $career = $this->get($id);
187
        $new = [];
188
        foreach ($career as $key => $val) {
189
            switch ($key) {
190
                case 'id':
191
                case 'updated_at':
192
                    break;
193
                case 'name':
194
                    $val .= ' '.get_lang('CopyLabelSuffix');
195
                    $new[$key] = $val;
196
                    break;
197
                case 'created_at':
198
                    $val = api_get_utc_datetime();
199
                    $new[$key] = $val;
200
                    break;
201
                default:
202
                    $new[$key] = $val;
203
                    break;
204
            }
205
        }
206
        $cid = $this->save($new);
207
        if ($copy_promotions) {
208
            //Now also copy each session of the promotion as a new session and register it inside the promotion
209
            $promotion = new Promotion();
210
            $promo_list = $promotion->get_all_promotions_by_career_id($id);
211
            if (!empty($promo_list)) {
212
                foreach ($promo_list as $item) {
213
                    $promotion->copy($item['id'], $cid, true);
214
                }
215
            }
216
        }
217
218
        return $cid;
219
    }
220
221
    /**
222
     * @param int $career_id
223
     *
224
     * @return bool
225
     */
226
    public function get_status($career_id)
227
    {
228
        $table = Database::get_main_table(TABLE_CAREER);
229
        $career_id = intval($career_id);
230
        $sql = "SELECT status FROM $table WHERE id = '$career_id'";
231
        $result = Database::query($sql);
232
        if (Database::num_rows($result) > 0) {
233
            $data = Database::fetch_array($result);
234
235
            return $data['status'];
236
        } else {
237
            return false;
238
        }
239
    }
240
241
    /**
242
     * @param array $params
243
     * @param bool  $show_query
244
     *
245
     * @return int
246
     */
247
    public function save($params, $show_query = false)
248
    {
249
        if (isset($params['description'])) {
250
            $params['description'] = Security::remove_XSS($params['description']);
251
        }
252
253
        $id = parent::save($params);
254
        if (!empty($id)) {
255
            Event::addEvent(
256
                LOG_CAREER_CREATE,
257
                LOG_CAREER_ID,
258
                $id,
259
                api_get_utc_datetime(),
260
                api_get_user_id()
261
            );
262
        }
263
264
        return $id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $id could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

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

Loading history...
265
    }
266
267
    /**
268
     * Delete a record from the career table and report in the default events log table.
269
     *
270
     * @param int $id The ID of the career to delete
271
     *
272
     * @return bool True if the career could be deleted, false otherwise
273
     */
274
    public function delete($id)
275
    {
276
        $res = parent::delete($id);
277
        if ($res) {
278
            $extraFieldValues = new ExtraFieldValue('career');
279
            $extraFieldValues->deleteValuesByItem($id);
280
            Event::addEvent(
281
                LOG_CAREER_DELETE,
282
                LOG_CAREER_ID,
283
                $id,
284
                api_get_utc_datetime(),
285
                api_get_user_id()
286
            );
287
        }
288
289
        return $res;
290
    }
291
292
    /**
293
     * {@inheritdoc}
294
     */
295
    public function update($params, $showQuery = false)
296
    {
297
        if (isset($params['description'])) {
298
            $params['description'] = Security::remove_XSS($params['description']);
299
        }
300
301
        return parent::update($params, $showQuery);
302
    }
303
304
    /**
305
     * @param array
306
     * @param Graph $graph
307
     *
308
     * @return string
309
     */
310
    public static function renderDiagram($careerInfo, $graph)
0 ignored issues
show
Unused Code introduced by
The parameter $careerInfo is not used and could be removed. ( Ignorable by Annotation )

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

310
    public static function renderDiagram(/** @scrutinizer ignore-unused */ $careerInfo, $graph)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
311
    {
312
        if (!($graph instanceof Graph)) {
0 ignored issues
show
introduced by
$graph is always a sub-type of Fhaculty\Graph\Graph.
Loading history...
313
            return '';
314
        }
315
316
        // Getting max column
317
        $maxColumn = 0;
318
        foreach ($graph->getVertices() as $vertex) {
319
            $groupId = (int) $vertex->getGroup();
320
            if ($groupId > $maxColumn) {
321
                $maxColumn = $groupId;
322
            }
323
        }
324
325
        $list = [];
326
        /** @var Vertex $vertex */
327
        foreach ($graph->getVertices() as $vertex) {
328
            $group = $vertex->getAttribute('Group');
329
            $groupData = explode(':', $group);
330
            $group = $groupData[0];
331
            $groupLabel = isset($groupData[1]) ? $groupData[1] : '';
332
            $subGroup = $vertex->getAttribute('SubGroup');
333
            $subGroupData = explode(':', $subGroup);
334
            $column = $vertex->getGroup();
335
            $row = $vertex->getAttribute('Row');
336
            $subGroupId = $subGroupData[0];
337
            $label = isset($subGroupData[1]) ? $subGroupData[1] : '';
338
            $list[$group][$subGroupId]['columns'][$column][$row] = $vertex;
339
            $list[$group][$subGroupId]['label'] = $label;
340
            $list[$group]['label'] = $groupLabel;
341
        }
342
343
        $maxGroups = count($list);
344
        $widthGroup = 30;
345
        if (!empty($maxGroups)) {
346
            $widthGroup = 85 / $maxGroups;
347
        }
348
349
        $connections = '';
350
        $groupDrawLine = [];
351
        $groupCourseList = [];
352
        // Read Connections column
353
        foreach ($list as $group => $subGroupList) {
354
            foreach ($subGroupList as $subGroupData) {
355
                $columns = isset($subGroupData['columns']) ? $subGroupData['columns'] : [];
356
                $showGroupLine = true;
357
                if (count($columns) == 1) {
358
                    $showGroupLine = false;
359
                }
360
                $groupDrawLine[$group] = $showGroupLine;
361
362
                //if ($showGroupLine == false) {
363
                /** @var Vertex $vertex */
364
                foreach ($columns as $row => $items) {
365
                    foreach ($items as $vertex) {
366
                        if ($vertex instanceof Vertex) {
367
                            $groupCourseList[$group][] = $vertex->getId();
368
                            $connectionList = $vertex->getAttribute(
369
                                'Connections'
370
                            );
371
                            $firstConnection = '';
372
                            $secondConnection = '';
373
                            if (!empty($connectionList)) {
374
                                $explode = explode('-', $connectionList);
375
                                $pos = strpos($explode[0], 'SG');
376
                                if ($pos === false) {
377
                                    $pos = strpos($explode[0], 'G');
378
                                    if (is_numeric($pos)) {
379
                                        // group_123 id
380
                                        $groupValueId = (int) str_replace(
381
                                            'G',
382
                                            '',
383
                                            $explode[0]
384
                                        );
385
                                        $firstConnection = 'group_'.$groupValueId;
386
                                        $groupDrawLine[$groupValueId] = true;
387
                                    } else {
388
                                        // Course block (row_123 id)
389
                                        if (!empty($explode[0])) {
390
                                            $firstConnection = 'row_'.(int) $explode[0];
391
                                        }
392
                                    }
393
                                } else {
394
                                    // subgroup__123 id
395
                                    $firstConnection = 'subgroup_'.(int) str_replace('SG', '', $explode[0]);
396
                                }
397
398
                                $pos = strpos($explode[1], 'SG');
399
                                if ($pos === false) {
400
                                    $pos = strpos($explode[1], 'G');
401
                                    if (is_numeric($pos)) {
402
                                        $groupValueId = (int) str_replace(
403
                                            'G',
404
                                            '',
405
                                            $explode[1]
406
                                        );
407
                                        $secondConnection = 'group_'.$groupValueId;
408
                                        $groupDrawLine[$groupValueId] = true;
409
                                    } else {
410
                                        // Course block (row_123 id)
411
                                        if (!empty($explode[0])) {
412
                                            $secondConnection = 'row_'.(int) $explode[1];
413
                                        }
414
                                    }
415
                                } else {
416
                                    $secondConnection = 'subgroup_'.(int) str_replace('SG', '', $explode[1]);
417
                                }
418
419
                                if (!empty($firstConnection) && !empty($firstConnection)) {
420
                                    $connections .= self::createConnection(
421
                                        $firstConnection,
422
                                        $secondConnection,
423
                                        ['Left', 'Right']
424
                                    );
425
                                }
426
                            }
427
                        }
428
                    }
429
                }
430
                //}
431
            }
432
        }
433
434
        $graphHtml = '<div class="container">';
435
        foreach ($list as $group => $subGroupList) {
436
            $showGroupLine = false;
437
            if (isset($groupDrawLine[$group]) && $groupDrawLine[$group]) {
438
                $showGroupLine = true;
439
            }
440
            $graphHtml .= self::parseSubGroups(
441
                $groupCourseList,
442
                $group,
443
                $list[$group]['label'],
444
                $showGroupLine,
445
                $subGroupList,
446
                $widthGroup
447
            );
448
        }
449
        $graphHtml .= '</div>';
450
        $graphHtml .= $connections;
451
452
        return $graphHtml;
453
    }
454
455
    /**
456
     * @param Graph    $graph
457
     * @param Template $tpl
458
     *
459
     * @return string
460
     */
461
    public static function renderDiagramByColumn($graph, $tpl)
462
    {
463
        if (!($graph instanceof Graph)) {
0 ignored issues
show
introduced by
$graph is always a sub-type of Fhaculty\Graph\Graph.
Loading history...
464
            return '';
465
        }
466
467
        // Getting max column
468
        $maxColumn = 0;
469
        foreach ($graph->getVertices() as $vertex) {
470
            $groupId = (int) $vertex->getGroup();
471
            if ($groupId > $maxColumn) {
472
                $maxColumn = $groupId;
473
            }
474
        }
475
476
        $list = [];
477
        $subGroups = [];
478
        /** @var Vertex $vertex */
479
        foreach ($graph->getVertices() as $vertex) {
480
            $column = $vertex->getGroup();
481
            $group = $vertex->getAttribute('Group');
482
483
            $groupData = explode(':', $group);
484
            $group = $groupData[0];
485
            $groupLabel = isset($groupData[1]) ? $groupData[1] : '';
486
487
            $subGroup = $vertex->getAttribute('SubGroup');
488
            $subGroupData = explode(':', $subGroup);
489
490
            $row = $vertex->getAttribute('Row');
491
            $subGroupId = $subGroupData[0];
492
            $subGroupLabel = isset($subGroupData[1]) ? $subGroupData[1] : '';
493
494
            if (!empty($subGroupId) && !in_array($subGroupId, $subGroups)) {
495
                //$subGroups[$subGroupId][] = $vertex->getId();
496
                $subGroups[$subGroupId]['items'][] = $vertex->getId();
497
                $subGroups[$subGroupId]['label'] = $subGroupLabel;
498
            }
499
500
            $list[$column]['rows'][$row]['items'][] = $vertex;
501
            $list[$column]['rows'][$row]['label'] = $subGroupId;
502
            $list[$column]['rows'][$row]['group'] = $group;
503
            $list[$column]['rows'][$row]['group_label'] = $groupLabel;
504
            $list[$column]['rows'][$row]['subgroup'] = $subGroup;
505
            $list[$column]['rows'][$row]['subgroup_label'] = $subGroupLabel;
506
            //$list[$column]['label'] = $subGroupLabel;
507
            $list[$column]['label'] = $groupLabel;
508
            $list[$column]['column'] = $column;
509
        }
510
511
        $connections = '';
512
        $groupDrawLine = [];
513
        $groupCourseList = [];
514
        $simpleConnectionList = [];
515
516
        // Read Connections column
517
        foreach ($list as $column => $groupList) {
518
            foreach ($groupList['rows'] as $subGroupList) {
519
                /** @var Vertex $vertex */
520
                foreach ($subGroupList['items'] as $vertex) {
521
                    if ($vertex instanceof Vertex) {
522
                        $rowId = $vertex->getId();
523
                        $groupCourseList[$vertex->getAttribute('Column')][] = $vertex->getId();
524
                        $connectionList = $vertex->getAttribute('Connections');
525
                        if (empty($connectionList)) {
526
                            continue;
527
                        }
528
                        $firstConnection = '';
529
                        $secondConnection = '';
530
                        $simpleFirstConnection = '';
531
                        $simpleSecondConnection = '';
532
533
                        $explode = explode('-', $connectionList);
534
                        $pos = strpos($explode[0], 'SG');
535
                        if ($pos === false) {
536
                            $pos = strpos($explode[0], 'G');
537
                            if (is_numeric($pos)) {
538
                                // group_123 id
539
                                $groupValueId = (int) str_replace(
540
                                    'G',
541
                                    '',
542
                                    $explode[0]
543
                                );
544
                                $secondConnection = 'group_'.$groupValueId;
545
                                $firstConnection = 'row_'.(int) $rowId;
546
                                $groupDrawLine[$groupValueId] = true;
547
548
                                $simpleSecondConnection = 'g'.$groupValueId;
549
                                $simpleFirstConnection = 'v'.(int) $rowId;
550
                            } else {
551
                                // Course block (row_123 id)
552
                                if (!empty($explode[0])) {
553
                                    $firstConnection = 'row_'.(int) $explode[0];
554
                                    $simpleFirstConnection = 'v'.(int) $explode[0];
555
                                }
556
                            }
557
                        } else {
558
                            // subgroup__123 id
559
                            $firstConnection = 'subgroup_'.(int) str_replace('SG', '', $explode[0]);
560
                            $simpleFirstConnection = 'sg'.(int) str_replace('SG', '', $explode[0]);
561
                        }
562
563
                        $pos = false;
564
                        if (isset($explode[1])) {
565
                            $pos = strpos($explode[1], 'SG');
566
                        }
567
                        if ($pos === false) {
568
                            if (isset($explode[1])) {
569
                                $pos = strpos($explode[1], 'G');
570
                                $value = $explode[1];
571
                            }
572
                            if (is_numeric($pos)) {
573
                                $groupValueId = (int) str_replace(
574
                                    'G',
575
                                    '',
576
                                    $value
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $value does not seem to be defined for all execution paths leading up to this point.
Loading history...
577
                                );
578
                                $secondConnection = 'group_'.$groupValueId;
579
                                $simpleSecondConnection = 'g'.(int) $groupValueId;
580
                                $groupDrawLine[$groupValueId] = true;
581
                            } else {
582
                                // Course block (row_123 id)
583
                                if (!empty($explode[0]) && isset($explode[1])) {
584
                                    $secondConnection = 'row_'.(int) $explode[1];
585
                                    $simpleSecondConnection = 'v'.(int) $explode[1];
586
                                }
587
                            }
588
                        } else {
589
                            $secondConnection = 'subgroup_'.(int) str_replace('SG', '', $explode[1]);
590
                            $simpleSecondConnection = 'sg'.(int) str_replace('SG', '', $explode[1]);
591
                        }
592
593
                        if (!empty($firstConnection) && !empty($firstConnection)) {
594
                            $simpleConnectionList[] = [
595
                                'from' => $simpleFirstConnection,
596
                                'to' => $simpleSecondConnection,
597
                            ];
598
                            $connections .= self::createConnection(
599
                                $firstConnection,
600
                                $secondConnection,
601
                                ['Left', 'Right']
602
                            );
603
                        }
604
                    }
605
                }
606
            }
607
        }
608
609
        $graphHtml = '<div id ="career_grid">';
610
        $groupsBetweenColumns = [];
611
        foreach ($list as $column => $columnList) {
612
            foreach ($columnList['rows'] as $subGroupList) {
613
                $newGroup = $subGroupList['group'];
614
                $label = $subGroupList['group_label'];
615
                $newOrder[$newGroup]['items'][] = $subGroupList;
616
                $newOrder[$newGroup]['label'] = $label;
617
                $groupsBetweenColumns[$newGroup][] = $subGroupList;
618
            }
619
        }
620
621
        // Creates graph
622
        $graph = new stdClass();
623
        $graph->blockWidth = 240;
624
        $graph->blockHeight = 120;
625
        $graph->xGap = 70;
626
        $graph->yGap = 40;
627
        $graph->xDiff = 70;
628
        $graph->yDiff = 40;
629
        $graph->groupXGap = 50;
630
631
        foreach ($groupsBetweenColumns as $group => $items) {
632
            self::parseColumnList($groupCourseList, $items, '', $graph, $simpleConnectionList);
633
        }
634
635
        $graphHtml .= '</div>';
636
//        $graphHtml .= $connections;
637
        $graphHtml .= '<style>
638
            panel-title
639
             #career_grid {
640
                 display: grid;
641
                 grid-gap: 40px;
642
                 grid-template-columns: repeat(6, [col] auto ) ;
643
                 grid-template-rows: repeat(2, [row] auto);
644
                 background-color: #fff;
645
                 color: #444;
646
                 justify-items: stretch;
647
                 align-items: start;
648
                 align-content: start;
649
                 justify-content: stretch;
650
             }
651
             .group_class {
652
                 border: solid 2px;
653
                 padding: 8px;
654
             }
655
             .panel-title {
656
                font-size: 11px;
657
             }
658
             </style>
659
             ';
660
661
        // Create groups
662
        if (!empty($graph->groupList)) {
663
            $groupList = [];
664
            $groupDiffX = 20;
665
            $groupDiffY = 10;
666
            $style = 'whiteSpace=wrap;rounded;strokeColor=red;fillColor=none;strokeWidth=2;align=left;verticalAlign=top;';
667
            foreach ($graph->groupList as $id => $data) {
668
                if (empty($id)) {
669
                    continue;
670
                }
671
672
                $x = $data['min_x'] - $groupDiffX;
673
                $y = $data['min_y'] - $groupDiffY;
674
                $width = $data['max_width'] + ($groupDiffX * 2);
675
                $height = $data['max_height'] + $groupDiffY * 2;
676
                $label = '<h4>'.$data['label'].'</h4>';
677
                $vertexData = "var g$id = graph.insertVertex(parent, null, '$label', $x, $y, $width, $height, '$style');";
678
                $groupList[] = $vertexData;
679
            }
680
            $tpl->assign('group_list', $groupList);
681
        }
682
683
        // Create subgroups
684
        $subGroupList = [];
685
        $subGroupListData = [];
686
        foreach ($subGroups as $subGroupId => $vertexData) {
687
            $label = $vertexData['label'];
688
            $vertexIdList = $vertexData['items'];
689
            foreach ($vertexIdList as $rowId) {
690
                $data = $graph->allData[$rowId];
691
                $originalRow = $data['row'];
692
                $column = $data['column'];
693
                $x = $data['x'];
694
                $y = $data['y'];
695
                $width = $data['width'];
696
                $height = $data['height'];
697
698
                if (!isset($subGroupListData[$subGroupId])) {
699
                    $subGroupListData[$subGroupId]['min_x'] = 1000;
700
                    $subGroupListData[$subGroupId]['min_y'] = 1000;
701
                    $subGroupListData[$subGroupId]['max_width'] = 0;
702
                    $subGroupListData[$subGroupId]['max_height'] = 0;
703
                    $subGroupListData[$subGroupId]['label'] = $label;
704
                }
705
706
                if ($x < $subGroupListData[$subGroupId]['min_x']) {
707
                    $subGroupListData[$subGroupId]['min_x'] = $x;
708
                }
709
710
                if ($y < $subGroupListData[$subGroupId]['min_y']) {
711
                    $subGroupListData[$subGroupId]['min_y'] = $y;
712
                }
713
714
                /*$originalRow--;
715
                $column--;*/
716
                $subGroupListData[$subGroupId]['max_width'] = ($column + 1) * ($width + $graph->xGap) - $subGroupListData[$subGroupId]['min_x'];
717
                $subGroupListData[$subGroupId]['max_height'] = ($originalRow + 1) * ($height + $graph->yGap) - $subGroupListData[$subGroupId]['min_y'];
718
            }
719
720
            $style = 'whiteSpace=wrap;rounded;dashed=1;strokeColor=blue;fillColor=none;strokeWidth=2;align=left;verticalAlign=bottom;';
721
            $subGroupDiffX = 5;
722
            foreach ($subGroupListData as $subGroupId => $data) {
0 ignored issues
show
Comprehensibility Bug introduced by
$subGroupId is overwriting a variable from outer foreach loop.
Loading history...
723
                $x = $data['min_x'] - $subGroupDiffX;
724
                $y = $data['min_y'] - $subGroupDiffX;
725
                $width = $data['max_width'] + $subGroupDiffX * 2;
726
                $height = $data['max_height'] + $subGroupDiffX * 2;
727
                $label = '<h4>'.$data['label'].'</h4>';
728
                $vertexData = "var sg$subGroupId = graph.insertVertex(parent, null, '$label', $x, $y, $width, $height, '$style');";
729
                $subGroupList[] = $vertexData;
730
            }
731
        }
732
733
        // Create connections (arrows)
734
        if (!empty($simpleConnectionList)) {
735
            $connectionList = [];
736
            //$style = 'endArrow=classic;html=1;strokeWidth=4;exitX=1;exitY=0.5;entryX=0;entryY=0.5;';
737
            $style = '';
738
            foreach ($simpleConnectionList as $connection) {
739
                $from = $connection['from'];
740
                $to = $connection['to'];
741
                $vertexData = "var e1 = graph.insertEdge(parent, null, '', $from, $to, '$style')";
742
                $connectionList[] = $vertexData;
743
            }
744
            $tpl->assign('connections', $connectionList);
745
        }
746
747
        $tpl->assign('subgroup_list', $subGroupList);
748
        $tpl->assign('vertex_list', $graph->elementList);
749
750
        $graphHtml .= '<div id="graphContainer"></div>';
751
752
        return $graphHtml;
753
    }
754
755
    public static function parseColumnList($groupCourseList, $columnList, $width, &$graph, &$connections)
0 ignored issues
show
Unused Code introduced by
The parameter $width is not used and could be removed. ( Ignorable by Annotation )

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

755
    public static function parseColumnList($groupCourseList, $columnList, /** @scrutinizer ignore-unused */ $width, &$graph, &$connections)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
756
    {
757
        $graphHtml = '';
758
        $oldGroup = null;
759
        $newOrder = [];
760
        foreach ($columnList as $key => $subGroupList) {
761
            $newGroup = $subGroupList['group'];
762
            $label = $subGroupList['group_label'];
763
            $newOrder[$newGroup]['items'][] = $subGroupList;
764
            $newOrder[$newGroup]['label'] = $label;
765
        }
766
767
        foreach ($newOrder as $newGroup => $data) {
768
            $label = $data['label'];
769
            $subGroupList = $data['items'];
770
771
            if (!isset($graph->groupList[$newGroup])) {
772
                $graph->groupList[$newGroup]['min_x'] = 1000;
773
                $graph->groupList[$newGroup]['min_y'] = 1000;
774
                $graph->groupList[$newGroup]['max_width'] = 0;
775
                $graph->groupList[$newGroup]['max_height'] = 0;
776
                $graph->groupList[$newGroup]['label'] = $label;
777
            }
778
779
            $maxColumn = 0;
780
            $maxRow = 0;
781
            $minColumn = 100;
782
            $minRow = 100;
783
            foreach ($subGroupList as $item) {
784
                /** @var Vertex $vertex */
785
                foreach ($item['items'] as $vertex) {
786
                    $column = $vertex->getAttribute('Column');
787
                    $realRow = $vertex->getAttribute('Row');
788
789
                    if ($column > $maxColumn) {
790
                        $maxColumn = $column;
791
                    }
792
                    if ($realRow > $maxRow) {
793
                        $maxRow = $realRow;
794
                    }
795
796
                    if ($column < $minColumn) {
797
                        $minColumn = $column;
798
                    }
799
                    if ($realRow < $minRow) {
800
                        $minRow = $realRow;
801
                    }
802
                }
803
            }
804
805
            if (!empty($newGroup)) {
806
                $graphHtml .= '<div 
807
                    id ="group_'.$newGroup.'"
808
                    class="group'.$newGroup.' group_class" 
809
                    style="display:grid; 
810
                        align-self: start;
811
                        grid-gap: 10px;                                     
812
                        justify-items: stretch;
813
                        align-items: start;
814
                        align-content: start;	
815
                        justify-content: stretch;	
816
                        grid-area:'.$minRow.'/'.$minColumn.'/'.$maxRow.'/'.$maxColumn.'">'; //style="display:grid"
817
            }
818
819
            $addRow = 0;
820
            if (!empty($label)) {
821
                $graphHtml .= "<div class='my_label' style='grid-area:$minRow/$minColumn/$maxRow/$maxColumn'>$label</div>";
822
                $addRow = 1;
823
            }
824
825
            foreach ($subGroupList as $item) {
826
                $graphHtml .= self::parseVertexList(
827
                    $groupCourseList,
828
                    $item['items'],
829
                    $addRow,
830
                    $graph,
831
                    $newGroup,
832
                    $connections
833
                );
834
            }
835
836
            if (!empty($newGroup)) {
837
                $graphHtml .= '</div >';
838
            }
839
        }
840
841
        return $graphHtml;
842
    }
843
844
    public static function parseVertexList($groupCourseList, $vertexList, $addRow = 0, &$graph, $group, &$connections)
845
    {
846
        if (empty($vertexList)) {
847
            return '';
848
        }
849
850
        $graphHtml = '';
851
        /** @var Vertex $vertex */
852
        foreach ($vertexList as $vertex) {
853
            $column = $vertex->getAttribute('Column');
854
            $realRow = $originalRow = $vertex->getAttribute('Row');
855
            if ($addRow) {
856
                $realRow = $realRow + $addRow;
857
            }
858
            $id = $vertex->getId();
859
            $area = "$realRow/$column";
860
            $graphHtml .= '<div 
861
                id = "row_wrapper_'.$id.'"   
862
                data= "'.$originalRow.'-'.$column.'"                            
863
                style="
864
                    align-self: start;
865
                    justify-content: stretch; 
866
                    grid-area:'.$area.'"
867
            >';
868
            $color = '';
869
            if (!empty($vertex->getAttribute('DefinedColor'))) {
870
                $color = $vertex->getAttribute('DefinedColor');
871
            }
872
            $content = '<div class="pull-left">'.$vertex->getAttribute('Notes').'</div>';
873
            $content .= '<div class="pull-right">['.$id.']</div>';
874
875
            $title = $vertex->getAttribute('graphviz.label');
876
            if (!empty($vertex->getAttribute('LinkedElement'))) {
877
                $title = Display::url($title, $vertex->getAttribute('LinkedElement'));
878
            }
879
880
            $originalRow--;
881
            $column--;
882
            //$title = "$originalRow / $column";
883
            $graphHtml .= Display::panel(
884
                $content,
885
                $title,
886
                null,
887
                null,
888
                null,
889
                "row_$id",
890
                $color
891
            );
892
893
            $panel = Display::panel(
894
                $content,
895
                $title,
896
                null,
897
                null,
898
                null,
899
                "row_$id",
900
                $color
901
            );
902
903
            $x = $column * $graph->blockWidth + $graph->xDiff;
904
            $y = $originalRow * $graph->blockHeight + $graph->yDiff;
905
906
            $width = $graph->blockWidth - $graph->xGap;
907
            $height = $graph->blockHeight - $graph->yGap;
908
909
            $style = 'text;html=1;strokeColor=green;fillColor=#ffffff;overflow=fill;rounded=0;align=left;';
910
911
            $panel = str_replace(["\n", "\r"], '', $panel);
912
            //$panel = $title.' - '.$group.' row: '.$originalRow.' heigh: '.$height.' id: '.$id;
913
            $vertexData = "var v$id = graph.insertVertex(parent, null, '".addslashes($panel)."', $x, $y, $width, $height, '$style');";
914
915
            $graph->elementList[$id] = $vertexData;
916
            $graph->allData[$id] = [
917
                'x' => $x,
918
                'y' => $y,
919
                'width' => $width,
920
                'height' => $height,
921
                'row' => $originalRow,
922
                'column' => $column,
923
                'label' => $title,
924
            ];
925
926
            if ($x < $graph->groupList[$group]['min_x']) {
927
                $graph->groupList[$group]['min_x'] = $x;
928
            }
929
930
            if ($y < $graph->groupList[$group]['min_y']) {
931
                $graph->groupList[$group]['min_y'] = $y;
932
            }
933
934
            $graph->groupList[$group]['max_width'] = ($column + 1) * ($width + $graph->xGap) - $graph->groupList[$group]['min_x'];
935
            $graph->groupList[$group]['max_height'] = ($originalRow + 1) * ($height + ($graph->yGap)) - $graph->groupList[$group]['min_y'];
936
937
            $graphHtml .= '</div>';
938
            $arrow = $vertex->getAttribute('DrawArrowFrom');
939
            $found = false;
940
            if (!empty($arrow)) {
941
                $pos = strpos($arrow, 'SG');
942
                if ($pos === false) {
943
                    $pos = strpos($arrow, 'G');
944
                    if (is_numeric($pos)) {
945
                        $parts = explode('G', $arrow);
946
                        if (empty($parts[0]) && count($parts) == 2) {
947
                            $groupArrow = $parts[1];
948
                            $graphHtml .= self::createConnection(
949
                                "group_$groupArrow",
950
                                "row_$id",
951
                                ['Left', 'Right']
952
                            );
953
                            $found = true;
954
                            $connections[] = [
955
                              'from' => "g$groupArrow",
956
                              'to' => "v$id",
957
                            ];
958
                        }
959
                    }
960
                } else {
961
                    // Case is only one subgroup value example: SG1
962
                    $parts = explode('SG', $arrow);
963
                    if (empty($parts[0]) && count($parts) == 2) {
964
                        $subGroupArrow = $parts[1];
965
                        $graphHtml .= self::createConnection(
966
                            "subgroup_$subGroupArrow",
967
                            "row_$id",
968
                            ['Left', 'Right']
969
                        );
970
                        $found = true;
971
                        $connections[] = [
972
                            'from' => "sg$subGroupArrow",
973
                            'to' => "v$id",
974
                        ];
975
                    }
976
                }
977
978
                if ($found == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
979
                    // case is connected to 2 subgroups: Example SG1-SG2
980
                    $parts = explode('-', $arrow);
981
                    if (count($parts) == 2 && !empty($parts[0]) && !empty($parts[1])) {
982
                        $defaultArrow = ['Top', 'Bottom'];
983
                        $firstPrefix = '';
984
                        $firstId = '';
985
                        $secondId = '';
986
                        $secondPrefix = '';
987
                        if (is_numeric($pos = strpos($parts[0], 'SG'))) {
988
                            $firstPrefix = 'sg';
989
                            $firstId = str_replace('SG', '', $parts[0]);
990
                        }
991
992
                        if (is_numeric($pos = strpos($parts[1], 'SG'))) {
993
                            $secondPrefix = 'sg';
994
                            $secondId = str_replace('SG', '', $parts[1]);
995
                        }
996
                        if (!empty($secondId) && !empty($firstId)) {
997
                            $connections[] = [
998
                                'from' => $firstPrefix.$firstId,
999
                                'to' => $secondPrefix.$secondId,
1000
                                $defaultArrow,
1001
                            ];
1002
                            $found = true;
1003
                        }
1004
                    }
1005
                }
1006
1007
                if ($found == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1008
                    // case DrawArrowFrom is an integer
1009
                    $defaultArrow = ['Left', 'Right'];
1010
                    if (isset($groupCourseList[$column]) &&
1011
                        in_array($arrow, $groupCourseList[$column])
1012
                    ) {
1013
                        $defaultArrow = ['Top', 'Bottom'];
1014
                    }
1015
                    $graphHtml .= self::createConnection(
1016
                        "row_$arrow",
1017
                        "row_$id",
1018
                        $defaultArrow
1019
                    );
1020
1021
                    $connections[] = [
1022
                        'from' => "v$arrow",
1023
                        'to' => "v$id",
1024
                    ];
1025
                }
1026
            }
1027
        }
1028
1029
        return $graphHtml;
1030
    }
1031
1032
    /**
1033
     * @param array  $groupCourseList list of groups and their courses
1034
     * @param int    $group
1035
     * @param string $groupLabel
1036
     * @param bool   $showGroupLine
1037
     * @param array  $subGroupList
1038
     * @param $widthGroup
1039
     *
1040
     * @return string
1041
     */
1042
    public static function parseSubGroups(
1043
        $groupCourseList,
1044
        $group,
1045
        $groupLabel,
1046
        $showGroupLine,
1047
        $subGroupList,
1048
        $widthGroup
1049
    ) {
1050
        $topValue = 90;
1051
        $defaultSpace = 40;
1052
        $leftGroup = $defaultSpace.'px';
1053
        if ($group == 1) {
1054
            $leftGroup = 0;
1055
        }
1056
1057
        $groupIdTag = "group_$group";
1058
        $borderLine = $showGroupLine === true ? 'border-style:solid;' : '';
1059
1060
        $graphHtml = '<div 
1061
            id="'.$groupIdTag.'" class="career_group" 
1062
            style=" '.$borderLine.' padding:15px; float:left; margin-left:'.$leftGroup.'; width:'.$widthGroup.'%">';
1063
1064
        if (!empty($groupLabel)) {
1065
            $graphHtml .= '<h3>'.$groupLabel.'</h3>';
1066
        }
1067
1068
        foreach ($subGroupList as $subGroup => $subGroupData) {
1069
            $subGroupLabel = isset($subGroupData['label']) ? $subGroupData['label'] : '';
1070
            $columnList = isset($subGroupData['columns']) ? $subGroupData['columns'] : [];
1071
1072
            if (empty($columnList)) {
1073
                continue;
1074
            }
1075
1076
            $line = '';
1077
            if (!empty($subGroup)) {
1078
                $line = 'border-style:solid;';
1079
            }
1080
1081
            // padding:15px;
1082
            $graphHtml .= '<div 
1083
                id="subgroup_'.$subGroup.'" class="career_subgroup" 
1084
                style="'.$line.' margin-bottom:20px; padding:15px; float:left; margin-left:0px; width:100%">';
1085
            if (!empty($subGroupLabel)) {
1086
                $graphHtml .= '<h3>'.$subGroupLabel.'</h3>';
1087
            }
1088
            foreach ($columnList as $column => $rows) {
1089
                $leftColumn = $defaultSpace.'px';
1090
                if ($column == 1) {
1091
                    $leftColumn = 0;
1092
                }
1093
                if (count($columnList) == 1) {
1094
                    $leftColumn = 0;
1095
                }
1096
1097
                $widthColumn = 85 / count($columnList);
1098
                $graphHtml .= '<div 
1099
                    id="col_'.$column.'" class="career_column" 
1100
                    style="padding:15px;float:left; margin-left:'.$leftColumn.'; width:'.$widthColumn.'%">';
1101
                $maxRow = 0;
1102
                foreach ($rows as $row => $vertex) {
1103
                    if ($row > $maxRow) {
1104
                        $maxRow = $row;
1105
                    }
1106
                }
1107
1108
                $newRowList = [];
1109
                $defaultSubGroup = -1;
1110
                $subGroupCountList = [];
1111
                for ($i = 0; $i < $maxRow; $i++) {
1112
                    /** @var Vertex $vertex */
1113
                    $vertex = isset($rows[$i + 1]) ? $rows[$i + 1] : null;
1114
                    if (!is_null($vertex)) {
1115
                        $subGroup = $vertex->getAttribute('SubGroup');
1116
                        if ($subGroup == '' || empty($subGroup)) {
1117
                            $defaultSubGroup = 0;
1118
                        } else {
1119
                            $defaultSubGroup = (int) $subGroup;
1120
                        }
1121
                    }
1122
                    $newRowList[$i + 1][$defaultSubGroup][] = $vertex;
1123
                    if (!isset($subGroupCountList[$defaultSubGroup])) {
1124
                        $subGroupCountList[$defaultSubGroup] = 1;
1125
                    } else {
1126
                        $subGroupCountList[$defaultSubGroup]++;
1127
                    }
1128
                }
1129
1130
                $subGroup = null;
1131
                $subGroupAdded = [];
1132
                /** @var Vertex $vertex */
1133
                foreach ($newRowList as $row => $subGroupList) {
0 ignored issues
show
introduced by
$subGroupList is overwriting one of the parameters of this function.
Loading history...
1134
                    foreach ($subGroupList as $subGroup => $vertexList) {
0 ignored issues
show
Comprehensibility Bug introduced by
$subGroup is overwriting a variable from outer foreach loop.
Loading history...
1135
                        if (!empty($subGroup) && $subGroup != -1) {
1136
                            if (!isset($subGroupAdded[$subGroup])) {
1137
                                $subGroupAdded[$subGroup] = 1;
1138
                            } else {
1139
                                $subGroupAdded[$subGroup]++;
1140
                            }
1141
                        }
1142
1143
                        foreach ($vertexList as $vertex) {
1144
                            if (is_null($vertex)) {
1145
                                $graphHtml .= '<div class="career_empty" style="height: 130px">';
1146
                                $graphHtml .= '</div>';
1147
                                continue;
1148
                            }
1149
1150
                            $id = $vertex->getId();
1151
                            $rowId = "row_$row";
1152
                            $graphHtml .= '<div id = "row_'.$id.'" class="'.$rowId.' career_row" >';
1153
                            $color = '';
1154
                            if (!empty($vertex->getAttribute('DefinedColor'))) {
1155
                                $color = $vertex->getAttribute('DefinedColor');
1156
                            }
1157
                            $content = $vertex->getAttribute('Notes');
1158
                            $content .= '<div class="pull-right">['.$id.']</div>';
1159
1160
                            $title = $vertex->getAttribute('graphviz.label');
1161
                            if (!empty($vertex->getAttribute('LinkedElement'))) {
1162
                                $title = Display::url($title, $vertex->getAttribute('LinkedElement'));
1163
                            }
1164
1165
                            $graphHtml .= Display::panel(
1166
                                $content,
1167
                                $title,
1168
                                null,
1169
                                null,
1170
                                null,
1171
                                null,
1172
                                $color
1173
                            );
1174
                            $graphHtml .= '</div>';
1175
1176
                            $arrow = $vertex->getAttribute('DrawArrowFrom');
1177
                            $found = false;
1178
                            if (!empty($arrow)) {
1179
                                $pos = strpos($arrow, 'SG');
1180
                                if ($pos === false) {
1181
                                    $pos = strpos($arrow, 'G');
1182
                                    if (is_numeric($pos)) {
1183
                                        $parts = explode('G', $arrow);
1184
                                        if (empty($parts[0]) && count($parts) == 2) {
1185
                                            $groupArrow = $parts[1];
1186
                                            $graphHtml .= self::createConnection(
1187
                                                "group_$groupArrow",
1188
                                                "row_$id",
1189
                                                ['Left', 'Right']
1190
                                            );
1191
                                            $found = true;
1192
                                        }
1193
                                    }
1194
                                } else {
1195
                                    $parts = explode('SG', $arrow);
1196
                                    if (empty($parts[0]) && count($parts) == 2) {
1197
                                        $subGroupArrow = $parts[1];
1198
                                        $graphHtml .= self::createConnection(
1199
                                            "subgroup_$subGroupArrow",
1200
                                            "row_$id",
1201
                                            ['Left', 'Right']
1202
                                        );
1203
                                        $found = true;
1204
                                    }
1205
                                }
1206
                            }
1207
1208
                            if ($found == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1209
                                $defaultArrow = ['Left', 'Right'];
1210
                                if (isset($groupCourseList[$group]) &&
1211
                                    in_array($arrow, $groupCourseList[$group])
1212
                                ) {
1213
                                    $defaultArrow = ['Top', 'Bottom'];
1214
                                }
1215
                                $graphHtml .= self::createConnection(
1216
                                    "row_$arrow",
1217
                                    "row_$id",
1218
                                    $defaultArrow
1219
                                );
1220
                            }
1221
                        }
1222
                    }
1223
                }
1224
                $graphHtml .= '</div>';
1225
            }
1226
            $graphHtml .= '</div>';
1227
        }
1228
        $graphHtml .= '</div>';
1229
1230
        return $graphHtml;
1231
    }
1232
1233
    /**
1234
     * @param string $source
1235
     * @param string $target
1236
     * @param array  $anchor
1237
     *
1238
     * @return string
1239
     */
1240
    public static function createConnection($source, $target, $anchor = [])
1241
    {
1242
        if (empty($anchor)) {
1243
            // Default
1244
            $anchor = ['Bottom', 'Right'];
1245
        }
1246
1247
        $anchor = implode('","', $anchor);
1248
        $html = '<script>
1249
1250
        var connectorPaintStyle = {
1251
            strokeWidth: 2,
1252
            stroke: "#a31ed3",
1253
            joinstyle: "round",
1254
            outlineStroke: "white",
1255
            outlineWidth: 2
1256
        },
1257
        // .. and this is the hover style.
1258
        connectorHoverStyle = {
1259
            strokeWidth: 3,
1260
            stroke: "#216477",
1261
            outlineWidth: 5,
1262
            outlineStroke: "white"
1263
        },
1264
        endpointHoverStyle = {
1265
            fill: "#E80CAF",
1266
            stroke: "#E80CAF"
1267
        };
1268
        jsPlumb.ready(function() { ';
1269
        $html .= 'jsPlumb.connect({
1270
            source:"'.$source.'",
1271
            target:"'.$target.'",
1272
            endpoint:[ "Rectangle", { width:1, height:1 }],                                        
1273
            connector: ["Flowchart"],             
1274
            paintStyle: connectorPaintStyle,    
1275
            hoverPaintStyle: endpointHoverStyle,                
1276
            anchor: ["'.$anchor.'"],
1277
            overlays: [
1278
                [ 
1279
                    "Arrow", 
1280
                    { 
1281
                        location:1,  
1282
                        width:11, 
1283
                        length:11 
1284
                    } 
1285
                ],
1286
            ],
1287
        });';
1288
        $html .= '});</script>'.PHP_EOL;
1289
1290
        return $html;
1291
    }
1292
}
1293