Completed
Push — master ( 8ca68a...b0dc5f )
by Hannes
02:09
created

Enumerator::on()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
1
<?php
2
/**
3
 * This file is part of byrokrat\autogiro.
4
 *
5
 * byrokrat\autogiro is free software: you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License as published
7
 * by the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * byrokrat\autogiro is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with byrokrat\autogiro. If not, see <http://www.gnu.org/licenses/>.
17
 *
18
 * Copyright 2016 Hannes Forsgård
19
 */
20
21
declare(strict_types = 1);
22
23
namespace byrokrat\autogiro;
24
25
use byrokrat\autogiro\Tree\Node;
26
use byrokrat\autogiro\Exception\LogicException;
27
28
/**
29
 * Tool to enumerate tree nodes of specified types
30
 */
31
class Enumerator
32
{
33
    /**
34
     * @var callable[]
35
     */
36
    private $callbacks = [];
37
38
    /**
39
     * Magic method to register enumeration callbacks
40
     *
41
     * Usage: $enumerator->onNodeType($callback);
42
     *
43
     * @param string $name Node type to capure prefixed with on (eg onNodeType)
44
     * @param array  $args First argument must be a capure callback
45
     *
46
     * @throws LogicException If node type or callback is not specified
47
     */
48
    public function __call(string $name, array $args)
49
    {
50
        if (!preg_match('/^on[a-zA-Z0-9_]+$/', $name)) {
51
            throw new LogicException("Unknown method $name");
52
        }
53
54
        if (!isset($args[0]) || !is_callable($args[0])) {
55
            throw new LogicException('Enumeration callback must be callable');
56
        }
57
58
        $this->on(substr($name, 2), $args[0]);
59
    }
60
61
    /**
62
     * Register a callback for node type
63
     */
64
    public function on(string $nodeType, callable $callback)
65
    {
66
        $this->callbacks[$nodeType] = $callback;
67
    }
68
69
    /**
70
     * Enumerate nodes in tree
71
     */
72
    public function enumerate(Node $tree)
73
    {
74
        $this->dispatch($tree);
75
76
        foreach ($tree->getChildren() as $child) {
77
            $this->enumerate($child);
78
        }
79
    }
80
81
    /**
82
     * Invoke callback registered with node type
83
     */
84
    private function dispatch(Node $node)
85
    {
86
        if (isset($this->callbacks[$node->getType()])) {
87
            $this->callbacks[$node->getType()]($node);
88
        }
89
    }
90
}
91