Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 39 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
| CargoHierarchyTree | |
0.00% |
0 / 39 |
|
0.00% |
0 / 6 |
240 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| addChild | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| newFromWikiText | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
30 | |||
| getLastNodeForLevel | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
| generateHierarchyStructureTableData | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
12 | |||
| computeLeftRight | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * CargoHierarchyTree - holds the tree for hierarchy inorder to implement Nested Set model for |
| 4 | * efficient storage and query of hierarchy fields. |
| 5 | * |
| 6 | * @author Feroz Ahmad |
| 7 | * @ingroup Cargo |
| 8 | */ |
| 9 | |
| 10 | class CargoHierarchyTree { |
| 11 | public $mRootValue; |
| 12 | public $mChildren; |
| 13 | public $mLeft = 0; |
| 14 | public $mRight = 0; |
| 15 | |
| 16 | public function __construct( $curTitle = '__pseudo_root__' ) { |
| 17 | $this->mRootValue = $curTitle; |
| 18 | $this->mChildren = []; |
| 19 | } |
| 20 | |
| 21 | public function addChild( $child ) { |
| 22 | $this->mChildren[] = $child; |
| 23 | } |
| 24 | |
| 25 | /** |
| 26 | * Turn a manually-created "structure", defined as a bulleted list |
| 27 | * in wikitext, into a tree. This code has been borrowed from PFTree class |
| 28 | * of Page Forms Extension |
| 29 | * |
| 30 | * @param string $wikitext |
| 31 | * @return self |
| 32 | */ |
| 33 | public static function newFromWikiText( $wikitext ) { |
| 34 | // A dummy node (__pseudo_root__ is added so that |
| 35 | // multiple nodes can be added in the first level |
| 36 | $fullTree = new static(); |
| 37 | $lines = explode( "\n", $wikitext ); |
| 38 | foreach ( $lines as $line ) { |
| 39 | $numBullets = 0; |
| 40 | for ( $i = 0; $i < strlen( $line ) && $line[$i] == '*'; $i++ ) { |
| 41 | $numBullets++; |
| 42 | } |
| 43 | if ( $numBullets == 0 ) { |
| 44 | continue; |
| 45 | } |
| 46 | $lineText = trim( substr( $line, $numBullets ) ); |
| 47 | $curParentNode = $fullTree->getLastNodeForLevel( $numBullets ); |
| 48 | $curParentNode->addChild( new static( $lineText ) ); |
| 49 | } |
| 50 | $fullTree->computeLeftRight(); |
| 51 | return $fullTree; |
| 52 | } |
| 53 | |
| 54 | public function getLastNodeForLevel( $level ) { |
| 55 | if ( $level <= 1 || count( $this->mChildren ) == 0 ) { |
| 56 | return $this; |
| 57 | } |
| 58 | $lastNodeOnCurLevel = end( $this->mChildren ); |
| 59 | return $lastNodeOnCurLevel->getLastNodeForLevel( $level - 1 ); |
| 60 | } |
| 61 | |
| 62 | public function generateHierarchyStructureTableData() { |
| 63 | $tableData = []; |
| 64 | // Preorder traversal using Stack data structure |
| 65 | $stack = new SplStack(); |
| 66 | $stack->push( $this ); |
| 67 | while ( !$stack->isEmpty() ) { |
| 68 | /** @var CargoHierarchyTree $node */ |
| 69 | $node = $stack->pop(); |
| 70 | $row = []; |
| 71 | $row['_value'] = $node->mRootValue; |
| 72 | $row['_left'] = $node->mLeft; |
| 73 | $row['_right'] = $node->mRight; |
| 74 | $tableData[] = $row; |
| 75 | foreach ( array_reverse( $node->mChildren ) as $child ) { |
| 76 | $stack->push( $child ); |
| 77 | } |
| 78 | } |
| 79 | return $tableData; |
| 80 | } |
| 81 | |
| 82 | private function computeLeftRight( &$counter = 1 ) { |
| 83 | $this->mLeft = $counter; |
| 84 | $counter += 1; |
| 85 | // Visit mChildren of the current node |
| 86 | foreach ( $this->mChildren as $child ) { |
| 87 | $child->computeLeftRight( $counter ); |
| 88 | } |
| 89 | $this->mRight = $counter; |
| 90 | $counter += 1; |
| 91 | } |
| 92 | } |