Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
60.00% |
27 / 45 |
|
88.89% |
8 / 9 |
CRAP | |
0.00% |
0 / 1 |
Tree | |
60.00% |
27 / 45 |
|
88.89% |
8 / 9 |
52.98 | |
0.00% |
0 / 1 |
setAncestorDepth | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setDescendantDepth | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
addAncestors | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
addDescendants | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
addAncestorsOrDescendants | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
hasAncestorsOrDescendants | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setFormat | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getWikitext | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
90 | |||
getTreeSource | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
4 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\Genealogy; |
4 | |
5 | use ExtensionRegistry; |
6 | use Html; |
7 | use Parser; |
8 | use Title; |
9 | |
10 | class Tree { |
11 | |
12 | /** @var string The tree's format, either 'graphviz' or 'mermaid'. */ |
13 | protected $format = 'graphviz'; |
14 | |
15 | /** @var Person[] */ |
16 | protected $ancestors = []; |
17 | |
18 | /** @var Person[] */ |
19 | protected $descendants = []; |
20 | |
21 | /** @var int */ |
22 | protected $ancestorDepth; |
23 | |
24 | /** @var int */ |
25 | protected $descendantDepth; |
26 | |
27 | /** |
28 | * Set the number of levels the tree will go up to from the ancestors' starting points. |
29 | * @param int $ancestorDepth The new ancestor depth. |
30 | */ |
31 | public function setAncestorDepth( $ancestorDepth ) { |
32 | $this->ancestorDepth = (int)$ancestorDepth; |
33 | } |
34 | |
35 | /** |
36 | * Set the number of levels the tree will go down to from the descendants' starting points. |
37 | * @param int $descendantDepth The new descendant depth. |
38 | */ |
39 | public function setDescendantDepth( $descendantDepth ) { |
40 | $this->descendantDepth = (int)$descendantDepth; |
41 | } |
42 | |
43 | /** |
44 | * Add ancestor starting points to this tree, from which to traverse upwards. |
45 | * @param string[] $ancestors Array of page titles. |
46 | */ |
47 | public function addAncestors( $ancestors ) { |
48 | $this->addAncestorsOrDescendants( 'ancestors', $ancestors ); |
49 | } |
50 | |
51 | /** |
52 | * Add descendant starting points to this tree, from which to traverse downwards. |
53 | * @param string[] $descendants Array of page titles. |
54 | */ |
55 | public function addDescendants( $descendants ) { |
56 | $this->addAncestorsOrDescendants( 'descendants', $descendants ); |
57 | } |
58 | |
59 | /** |
60 | * Add ancestor or descendant starting points to this tree. |
61 | * @param string $type Either 'ancestors' or 'descendants'. |
62 | * @param string[] $list Array of page titles. |
63 | */ |
64 | protected function addAncestorsOrDescendants( $type, $list ) { |
65 | foreach ( $list as $a ) { |
66 | $title = Title::newFromText( $a ); |
67 | if ( $title ) { |
68 | $person = new Person( $title ); |
69 | $this->{$type}[] = $person; |
70 | } |
71 | } |
72 | } |
73 | |
74 | /** |
75 | * Whether any ancestors or descendants have been added to this tree. |
76 | * @return bool |
77 | */ |
78 | public function hasAncestorsOrDescendants() { |
79 | return ( count( $this->ancestors ) + count( $this->descendants ) ) > 0; |
80 | } |
81 | |
82 | /** |
83 | * Set the output format for the tree. |
84 | * |
85 | * @param string $format Either 'graphviz' or 'mermaid' (case insensitive). |
86 | * @return void |
87 | */ |
88 | public function setFormat( $format ) { |
89 | $this->format = strtolower( $format ); |
90 | } |
91 | |
92 | /** |
93 | * Get the wikitext output for the tree. |
94 | * |
95 | * @param Parser $parser The parser. |
96 | * @return string Unsafe half-parsed HTML, as returned by Parser::recursiveTagParse(). |
97 | */ |
98 | public function getWikitext( Parser $parser ) { |
99 | // If there's nothing to render, give up. |
100 | if ( !$this->hasAncestorsOrDescendants() ) { |
101 | return ''; |
102 | } |
103 | |
104 | $extenstionRegistry = ExtensionRegistry::getInstance(); |
105 | $diagramsInstalled = $extenstionRegistry->isLoaded( 'Diagrams' ); |
106 | $graphvizInstalled = $extenstionRegistry->isLoaded( 'GraphViz' ) |
107 | || $diagramsInstalled; |
108 | $mermaidInstalled = $extenstionRegistry->isLoaded( 'Mermaid' ); |
109 | $treeSource = $this->getTreeSource(); |
110 | if ( $this->format === 'mermaid' && $mermaidInstalled ) { |
111 | $wikitext = "{{#mermaid:$treeSource|config.flowchart.useMaxWidth=0|config.theme=neutral}}"; |
112 | $out = $parser->recursiveTagParse( $wikitext ); |
113 | } elseif ( $this->format === 'mermaid' && $diagramsInstalled ) { |
114 | $out = $parser->recursiveTagParse( "<mermaid>$treeSource</mermaid>" ); |
115 | } elseif ( $this->format === 'graphviz' && $graphvizInstalled ) { |
116 | $out = $parser->recursiveTagParse( "<graphviz>$treeSource</graphviz>" ); |
117 | } else { |
118 | $err = wfMessage( 'genealogy-invalid-tree-format', $this->format )->text(); |
119 | return Html::element( 'p', [ 'class' => 'error' ], $err ); |
120 | } |
121 | |
122 | // Debugging. |
123 | // $out .= $parser->recursiveTagParse( "<pre>$treeSource</pre>" ); |
124 | |
125 | return $out; |
126 | } |
127 | |
128 | /** |
129 | * @return string |
130 | */ |
131 | public function getTreeSource() { |
132 | $traverser = new Traverser(); |
133 | $formatter = $this->format === 'mermaid' |
134 | ? new MermaidTreeFormatter( $this->ancestors, $this->descendants ) |
135 | : new GraphVizTreeFormatter( $this->ancestors, $this->descendants ); |
136 | $formatter->setName( md5( |
137 | implode( '', $this->ancestors ) |
138 | . implode( '', $this->descendants ) |
139 | . $this->ancestorDepth |
140 | . $this->descendantDepth |
141 | ) ); |
142 | $traverser->register( [ $formatter, 'visit' ] ); |
143 | |
144 | foreach ( $this->ancestors as $ancestor ) { |
145 | $traverser->ancestors( $ancestor, $this->ancestorDepth ); |
146 | } |
147 | |
148 | foreach ( $this->descendants as $descendant ) { |
149 | $traverser->descendants( $descendant, $this->descendantDepth ); |
150 | } |
151 | |
152 | return $formatter->getOutput(); |
153 | } |
154 | } |