mirror of
https://github.com/cosmocode/dokuwiki-plugin-struct.git
synced 2025-08-13 13:37:20 +00:00
Add indexing support
Using the index keyword, lists can now have an alphabetical Index at the top level.
This commit is contained in:
@ -201,4 +201,53 @@ class NestedResultTest extends StructTest
|
||||
$this->assertCount(3, $tree, '3 root nodes of material expected');
|
||||
$this->assertCount(1, $tree[0]->getChildren()[0]->getResultRows(), '1 metal black row expected');
|
||||
}
|
||||
|
||||
/**
|
||||
* Nest by two multi value levels with indexing
|
||||
*/
|
||||
public function testMultiMultiTwoLevelsIndex()
|
||||
{
|
||||
$result = $this->makeResult($this->multiMultiItems);
|
||||
$nestedResult = new NestedResult($result);
|
||||
$root = $nestedResult->getRoot(2, 1);
|
||||
$tree = $root->getChildren(); // nest: index, material, color, *
|
||||
|
||||
$this->assertCount(3, $tree, '3 root index nodes expected');
|
||||
$this->assertEquals('M', $tree[0]->getValueObject()->getValue(), 'M expected');
|
||||
$this->assertCount(1, $tree[0]->getChildren(), '1 metal sub node under M expected');
|
||||
}
|
||||
|
||||
/**
|
||||
* Index a flat result with no multi values
|
||||
*/
|
||||
public function testSimpleIndex()
|
||||
{
|
||||
$result = $this->makeResult($this->simpleItems);
|
||||
$nestedResult = new NestedResult($result);
|
||||
$root = $nestedResult->getRoot(0, 2);
|
||||
$tree = $root->getChildren();
|
||||
|
||||
$this->assertCount(2, $tree, '2 root index nodes expected');
|
||||
$this->assertEquals('CA', $tree[0]->getValueObject()->getValue(), 'CA(r) index expected');
|
||||
$this->assertEquals('LA', $tree[1]->getValueObject()->getValue(), 'LA(ptop) index expected');
|
||||
|
||||
$this->assertCount(6, $tree[0]->getResultRows(), '6 rows under CA expected');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Index a flat result with multi values
|
||||
*/
|
||||
public function testMultiIndex()
|
||||
{
|
||||
$result = $this->makeResult($this->multiItems);
|
||||
$nestedResult = new NestedResult($result);
|
||||
$root = $nestedResult->getRoot(0, 2);
|
||||
$tree = $root->getChildren();
|
||||
|
||||
$this->assertCount(4, $tree, '4 root index nodes expected');
|
||||
$this->assertEquals('BL', $tree[0]->getValueObject()->getValue(), 'BL(ack|blue) index expected');
|
||||
|
||||
$this->assertCount(4, $tree[0]->getResultRows(), '4 rows under BL expected');
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class AggregationList extends Aggregation
|
||||
$this->startScope();
|
||||
if ($this->result) {
|
||||
$nestedResult = new NestedResult($this->result);
|
||||
$root = $nestedResult->getRoot($this->data['nesting']);
|
||||
$root = $nestedResult->getRoot($this->data['nesting'], $this->data['index']);
|
||||
$this->renderNode($root);
|
||||
} elseif ($showNotFound) {
|
||||
$this->renderer->cdata($this->helper->getLang('none'));
|
||||
|
@ -40,6 +40,7 @@ class ConfigParser
|
||||
'sort' => array(),
|
||||
'csv' => true,
|
||||
'nesting' => 0,
|
||||
'index' => 0,
|
||||
);
|
||||
// parse info
|
||||
foreach ($lines as $line) {
|
||||
@ -121,6 +122,9 @@ class ConfigParser
|
||||
case 'nest':
|
||||
$this->config['nesting'] = (int) $val;
|
||||
break;
|
||||
case 'index':
|
||||
$this->config['index'] = (int) $val;
|
||||
break;
|
||||
default:
|
||||
$data = array('config' => &$this->config, 'key' => $key, 'val' => $val);
|
||||
$ev = new \Doku_Event('PLUGIN_STRUCT_CONFIGPARSER_UNKNOWNKEY', $data);
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
namespace dokuwiki\plugin\struct\meta;
|
||||
|
||||
use dokuwiki\plugin\struct\types\Text;
|
||||
use dokuwiki\Utf8\PhpString;
|
||||
|
||||
/**
|
||||
* This class builds a nested tree from a search result
|
||||
*
|
||||
@ -13,6 +16,9 @@ class NestedResult
|
||||
/** @var NestedValue[] */
|
||||
protected $nodes = [];
|
||||
|
||||
/** @var NestedValue[] */
|
||||
protected $indexNodes = [];
|
||||
|
||||
/** @var Value[][] */
|
||||
protected $result;
|
||||
|
||||
@ -29,20 +35,63 @@ class NestedResult
|
||||
* Get the nested result
|
||||
*
|
||||
* @param int $nesting the nesting level to use
|
||||
* @param int $index the number of characters to use for indexing
|
||||
* @return NestedValue the root node of the nested tree
|
||||
*/
|
||||
public function getRoot($nesting) {
|
||||
public function getRoot($nesting, $index = 0)
|
||||
{
|
||||
$this->nodes = [];
|
||||
$root = new NestedValue(null, -1);
|
||||
|
||||
if(!$this->result) return $root;
|
||||
if (!$this->result) return $root;
|
||||
|
||||
foreach ($this->result as $row) {
|
||||
$this->nestBranch($root, $row, $nesting);
|
||||
}
|
||||
|
||||
$root = $this->createIndex($root, $index);
|
||||
return $root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a top level index to the tree
|
||||
*
|
||||
* @param NestedValue $root Root node of the tree
|
||||
* @param int $index Number of characters to use for indexing
|
||||
* @return NestedValue new root node
|
||||
*/
|
||||
protected function createIndex(NestedValue $root, $index)
|
||||
{
|
||||
if (!$index) return $root;
|
||||
$this->indexNodes = [];
|
||||
|
||||
$children = $root->getChildren();
|
||||
$resultRows = $root->getResultRows();
|
||||
if ($children) {
|
||||
// there are children, so we are a nested result
|
||||
foreach ($children as $child) {
|
||||
$indexValue = $child->getValueObject();
|
||||
$indexNode = $this->getIndexNode($indexValue, $index);
|
||||
$indexNode->addChild($child);
|
||||
$child->setDepth(1); // increase child's depth from 0 to 1
|
||||
}
|
||||
} elseif ($resultRows) {
|
||||
// no children, so we are currently a flat result
|
||||
foreach ($resultRows as $row) {
|
||||
$indexValue = $row[0];
|
||||
$indexNode = $this->getIndexNode($indexValue, $index);
|
||||
$indexNode->addResultRow($row);
|
||||
}
|
||||
}
|
||||
|
||||
// now all results are added to index nodes - use them as children
|
||||
$newRoot = new NestedValue(null, -1);
|
||||
foreach ($this->indexNodes as $node) {
|
||||
$newRoot->addChild($node);
|
||||
}
|
||||
return $newRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates nested nodes for a given result row
|
||||
*
|
||||
@ -96,6 +145,33 @@ class NestedResult
|
||||
}
|
||||
return $this->nodes[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or get an existing Node for indexing
|
||||
*
|
||||
* @param Value $value
|
||||
* @param int $index
|
||||
* @return NestedValue
|
||||
*/
|
||||
protected function getIndexNode(Value $value, $index)
|
||||
{
|
||||
$compare = $value->getCompareValue();
|
||||
if (is_array($compare)) $compare = $compare[0];
|
||||
$key = PhpString::strtoupper(PhpString::substr($compare, 0, $index));
|
||||
|
||||
if (!isset($this->indexNodes[$key])) {
|
||||
$col = new Column(
|
||||
0,
|
||||
new Text([], '%index%', false),
|
||||
-1,
|
||||
true,
|
||||
$value->getColumn()->getTable()
|
||||
);
|
||||
$this->indexNodes[$key] = new NestedValue(new Value($col, $key), 0);
|
||||
}
|
||||
|
||||
return $this->indexNodes[$key];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,6 +44,17 @@ class NestedValue
|
||||
return $this->depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $depth
|
||||
*/
|
||||
public function setDepth($depth)
|
||||
{
|
||||
$this->depth = $depth;
|
||||
foreach ($this->children as $child) {
|
||||
$child->setDepth($depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the stored value
|
||||
*
|
||||
|
@ -19,7 +19,7 @@ class syntax_plugin_struct_table extends DokuWiki_Syntax_Plugin
|
||||
protected $tableclass = AggregationTable::class;
|
||||
|
||||
/** @var string Config options that are not allowed for this syntax mode */
|
||||
protected $illegalOptions = ['nesting'];
|
||||
protected $illegalOptions = ['nesting', 'index'];
|
||||
|
||||
/**
|
||||
* @return string Syntax mode type
|
||||
|
Reference in New Issue
Block a user