PHP code example of dakujem / oliva

1. Go to this page and download the library: Download dakujem/oliva library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

dakujem / oliva example snippets


use Dakujem\Oliva\TreeNodeContract;

$tree = (new TreeBuilder(
    node: fn(mixed $data) => new Node($data), // A node factory.
))->build(
    input: $anyDataCollection,                // An iterable collection to build a tree from.
);

fn(mixed $data) => new \Dakujem\Oliva\Node($data);

fn(mixed $anyItem) => new MyNode(MyTransformer::transform($anyItem)),

use Dakujem\Oliva\MovableNodeContract;

use Any\Item;
use Dakujem\Oliva\MaterializedPath\Path;
use Dakujem\Oliva\MaterializedPath\TreeBuilder;
use Dakujem\Oliva\Node;

// The input data may be a result of an SQL query or any other iterable collection.
$collection = [
    new Item(id: 0, path: ''), // the root
    new Item(id: 1, path: '000'),
    new Item(id: 2, path: '001'),
    new Item(id: 3, path: '003'),
    new Item(id: 4, path: '000000'),
    new Item(id: 5, path: '002000'),
    new Item(id: 6, path: '002'),
    new Item(id: 7, path: '000001'),
];

$builder = new TreeBuilder(
    node: fn(Item $item) => new Node($item),      // How to create a node.
    vector: Path::fixed(                          // How to extract path vector.
        levelWidth: 3,
        accessor: fn(Item $item) => $item->path,
    ),
);

$root = $builder->build(
    input: $collection,
);

use Any\Item;
use Dakujem\Oliva\MaterializedPath\Path;
use Dakujem\Oliva\MaterializedPath\TreeBuilder;
use Dakujem\Oliva\Node;

$collection = [
    new Item(id: 0, path: null), // the root
    new Item(id: 1, path: '.0'),
    new Item(id: 2, path: '.1'),
    new Item(id: 3, path: '.3'),
    new Item(id: 4, path: '.0.0'),
    new Item(id: 5, path: '.2.0'),
    new Item(id: 6, path: '.2'),
    new Item(id: 7, path: '.0.1'),
];

$builder = new TreeBuilder(
    node: fn(Item $item) => new Node($item),      // How to create a node.
    vector: Path::delimited(                      // How to extract path vector.
        delimiter: '.',
        accessor: fn(Item $item) => $item->path,
    ),
);

$root = $builder->build(
    input: $collection,
);

use Any\Item;
use Dakujem\Oliva\Recursive\TreeBuilder;
use Dakujem\Oliva\Node;

$collection = [
    new Item(id: 0, parent: null),
    new Item(id: 1, parent: 0),
    new Item(id: 2, parent: 0),
    new Item(id: 3, parent: 0),
    new Item(id: 4, parent: 1),
    new Item(id: 5, parent: 6),
    new Item(id: 6, parent: 0),
    new Item(id: 7, parent: 1),
];

$builder = new TreeBuilder(
    node: fn(Item $item) => new Node($item),      // How to create a node.
    selfRef: fn(Item $item) => $item->id,         // How to get ID of self.
    parentRef: fn(Item $item) => $item->parent,   // How to get parent ID.
    root: null,                                   // The root node's parent value.
);

$root = $builder->build(
    input: $collection,
);

use Any\Item;
use Dakujem\Oliva\Simple\TreeWrapper;
use Dakujem\Oliva\Node;

// $json = (new External\ApiConnector())->call('getJsonData');
// $rawData = json_decode($json);

// $rawData = yaml_parse_file('/config.yaml');

$rawData = [
    'children' => [
        [
            'attributes' => [ ... ],
            'children' => [
                [
                    'attributes' => [ ... ],
                    'children' => [],
                ]
            ],
        ],
        [
            'attributes' => [ ... ],
            'children' => [ ... ],
        ],
    ],
];

$builder = new TreeWrapper(
    node: function(array $item) {                                // How to create a node.
        unset($item['children']);                                // Note the unset call optimization.
        return new Node($item);
    },                   
    children: fn(array $item):array => $item['children'] ?? [],  // How to extract children.
);

$root = $builder->wrap($rawData);

use Dakujem\Oliva\Node;
use Dakujem\Oliva\Simple\NodeBuilder;

// Tell the builder how to create a node.
// The `$item` parameter of the node factory
// will contain the first argument to each `NodeBuilder::node` call.
$proxy = new NodeBuilder(
    node: fn(mixed $item) => new Node($item),
);

$root = 
    $proxy->node('root', [
        $proxy->node('first child', [
            $proxy->node('leaf of the first child node'),
            $proxy->node('another leaf of the first child node'),
        ]),
        $proxy->node('second child'), 
    ]);

use Dakujem\Oliva\Node;

$root = new Node('root');
$root->addChild($child1 = new Node('first child'));
$root->addChild($child2 = new Node('second child'));
$child1->setParent($root);
$child2->setParent($root);
$leaf1 = new Node('leaf of the first child node');
$child1->addChild($leaf1);
$leaf1->setParent($child1);
$leaf2 = new Node('another leaf of the first child node');
$child1->addChild($leaf2);
$leaf2->setParent($child1);

use Dakujem\Oliva\Node;
use Dakujem\Oliva\Tree;

$root = new Node('root');
Tree::link(node: $child1 = new Node('first child'), parent: $root);
Tree::link(node: $child2 = new Node('second child'), parent: $root);
Tree::link(node: new Node('leaf of the first child node'), parent: $child1);
Tree::link(node: new Node('another leaf of the first child node'), parent: $child1);

use Dakujem\Oliva\Node;
use Dakujem\Oliva\Tree;

Tree::linkChildren(node: $root = new Node('root'), children: [
    Tree::linkChildren(node: new Node('first child'), children: [
        new Node('leaf of the first child node'),
        new Node('another leaf of the first child node'),
    ]),
    new Node('second child'),
]);

use Dakujem\Oliva\Iterator\Filter;
use Dakujem\Oliva\Node;
use Dakujem\Oliva\Seed;
use Dakujem\Oliva\Tree;

// Create a find-by-id function (see Iterators section below):
$findById = fn(int $id, Node $tree) => Seed::firstOf(
    new Filter($tree, fn(Node $node) => $node->data()?->id === $id)
);

// Move node with ID 7 into node ID 14:
$node = $findById(7, $root);
$parent = $findById(14, $root);
Tree::link($node, $parent);

use Dakujem\Oliva\Iterator\Traversal;
use Dakujem\Oliva\Iterator\PreOrderTraversal;
use Dakujem\Oliva\Iterator\PostOrderTraversal;
use Dakujem\Oliva\Iterator\LevelOrderTraversal;

foreach(Traversal::levelOrder($root) as $node) { /* ... */ }
foreach(new LevelOrderTraversal($root) as $node) { /* ... */ }

use Dakujem\Oliva\Node;

$root = new Node( ... );

foreach ($root as $node) {
    // do something useful with the node
}

use Dakujem\Oliva\Iterator\Filter;
use Dakujem\Oliva\Node;
use Dakujem\Oliva\Seed;

// Filter the input before building a tree.
$filteredCollection = new Filter($sourceCollection, fn(Item $item): bool => $item->id > 5);
$root = (new TreeBuilder( ... ))->build(
    $filteredCollection,
);

// Iterate over leafs only.
$filter = new Filter($root, fn(Node $node): bool => $node->isLeaf());
foreach($filter as $node){
    // ...
}

// Find the first node that matches a criterion (data with ID = 42).
$node = Seed::firstOf(new Filter(
    input: $root,
    accept: fn(Node $node): bool => $node->data()?->id === 42),
);

use Dakujem\Oliva\Iterator\Filter;
use Dakujem\Oliva\Node;
use Dakujem\Oliva\Seed;

// Create a find-by-id function.
$findById = fn(int $id, Node $tree): ?Node => Seed::firstOf(
    new Filter($tree, fn(Node $node) => $node->data()?->id === $id)
);

// Search for any node by ID.
$node_42 = $findById(42, $root);


class TreeFinder
{
    public function __construct(
        public Node $tree,
    ) {
    }
    
    public function byId(int $id){ ... }
    
    public function byName(string $name){ ... }
}

use Dakujem\Oliva\Node;

$root = new Node( ... );

foreach ($root as $key => $node) {
    // The keys will increment 0, 1, 2, 3, ... and so on.
}

use Dakujem\Oliva\Iterator\PreOrderTraversal;
use Dakujem\Oliva\Node;

$iterator = new PreOrderTraversal(
    node: $root,
    key: fn(Node $node, array $vector): string => '.' . implode('.', $vector),
    startingVector: [],
);
$result = iterator_to_array($iterator);
//[
//    '.' => 'F',
//    '.0' => 'B',
//    '.0.0' => 'A',
//    '.0.1' => 'D',
//    '.0.1.0' => 'C',
//    '.0.1.1' => 'E',
//    '.1' => 'G',
//    '.1.0' => 'I',
//    '.1.0.0' => 'H',
//];

use Dakujem\Oliva\Iterator\PreOrderTraversal;
use Dakujem\Oliva\Node;

$iterator = new PreOrderTraversal(
    node: $root,
    key: fn(Node $node): int => $node->data()->id,
);

fn(
    Dakujem\Oliva\TreeNodeContract $node, 
    array $vector, // array<int, string|int>
    int $seq, 
    int $counter
): string|int

use Dakujem\Oliva\MaterializedPath;
use Dakujem\Oliva\Seed;

$source = Sql::getMeTheCommentsFor($article);

// When prepending `null`, care must be taken that both the extractor and the factory are able to cope with `null` values.
// Note the use of `?` nullable type hint indicator and null-safe `?->` operator.
$factory = fn(?Item $item) => new Node($item);
$pathExtractor = fn(?Item $item) => $item?->path;

$builder = new MaterializedPath\TreeBuilder( ... );
$root = $builder->build(
    input: Seed::nullFirst($source),       // `null` is prepended to the data
);

foreach(Seed::omitNull($root) as $node) {  // The node with `null` data is omitted from the iteration
    display($node);
}

use Dakujem\Oliva\MaterializedPath;
use Dakujem\Oliva\Seed;

$source = Sql::getMeTheCommentsFor($article);

// We need not take care of null values anymore.
$factory = fn(Item $item) => new Node($item);
$pathExtractor = fn(Item $item) => $item->path;

$builder = new MaterializedPath\TreeBuilder( ... );
$root = $builder->build(
    input: Seed::merged([new Item(id: 0, path: '')], $source),
);

foreach(Seed::omitRoot($root) as $node) {  // The root node is omitted from the iteration
    display($node);
}

use Any\Item;
use Dakujem\Oliva\Recursive\TreeBuilder;
use Dakujem\Oliva\Node;

$collection = [
    new Item(id: 100, parent: 99),             // Note that no data with ID 99 is present
    new Item(id: 101, parent: 100),
    new Item(id: 102, parent: 100),
    new Item(id: 103, parent: 100),
    new Item(id: 104, parent: 101),
    new Item(id: 105, parent: 106),
    new Item(id: 106, parent: 100),
    new Item(id: 107, parent: 101),
];

$builder = new TreeBuilder(
    node: fn(Item $item) => new Node($item),
    self: fn(Item $item) => $item->id,
    parent: fn(Item $item) => $item->parent,
    root: 99,                                  // Here we indicate what the parent of the root is
);

$root = $builder->build(
    input: $collection,
);