Passed
Push — 1.11.x ( 9b3f36...904f74 )
by Julito
11:13
created

Career::getCareerFromId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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