Completed
Push — master ( e666ea...addc16 )
by Richard
05:13
created

QueryImpl::expand_relations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
crap 1
1
<?php
2
/******************************************************************************
3
 * An implementation of dicto (scg.unibe.ch/dicto) in and for PHP.
4
 * 
5
 * Copyright (c) 2016 Richard Klees <[email protected]>
6
 *
7
 * This software is licensed under The MIT License. You should have received 
8
 * a copy of the license along with the code.
9
 */
10
11
namespace Lechimp\Dicto\Graph;
12
13
class QueryImpl implements Query {
14
    /**
15
     * @var Graph
16
     */
17
    protected $graph;
18
19
    /**
20
     * @var array[]
21
     */
22
    protected $steps;
23
24 50
    public function __construct(Graph $graph) {
25 50
        $this->graph = $graph;
26 50
        $this->steps = [];
27 50
    }
28
29
    /**
30
     * @inheritdocs
31
     */
32 25
    public function expand(\Closure $expander) {
33 25
        $clone = clone $this;
34 25
        $clone->steps[] = ["expand", $expander];
35 25
        assert('$this->steps != $clone->steps');
36 25
        return $clone;
37
    }
38
39
    /**
40
     * @inheritdocs
41
     */
42 50
    public function extract(\Closure $extractor) {
43 50
        $clone = clone $this;
44 50
        $clone->steps[] = ["extract", $extractor];
45 50
        assert('$this->steps != $clone->steps');
46 50
        return $clone;
47
    }
48
49
    /**
50
     * @inheritdocs
51
     */
52 44
    public function filter(\Closure $filter) {
53 44
        $clone = clone $this;
54 44
        $clone->steps[] = ["filter", $filter];
55 44
        assert('$this->steps != $clone->steps');
56 44
        return $clone;
57
    }
58
59
    /**
60
     * @inheritdocs
61
     */
62 50
    public function run($result) {
63 50
        $nodes = $this->add_result($this->graph->nodes(), $result);
64
65 50
        foreach ($this->steps as $step) {
66 50
            if (count($nodes) == 0) {
67 14
                return [];
68
            }
69
70 49
            list($cmd,$clsr) = $step;
71 49
            if ($cmd == "expand") {
72 22
                $nodes = $this->run_expand($nodes, $clsr);
73 22
            }
74 48
            elseif ($cmd == "extract") {
75 36
                $this->run_extract($nodes, $clsr);
76 36
            }
77 44
            elseif ($cmd == "filter") {
78 44
                $nodes = $this->run_filter($nodes, $clsr);
79 44
            }
80
            else {
81
                throw new \LogicException("Unknown command: $cmd");
82
            }
83 49
        }
84
85
        return array_values(array_map(function($r) {
86 36
            return $r[1];
87 36
        }, $nodes));
88
    }
89
90 22
    protected function run_expand(array &$nodes, \Closure $clsr) {
91 22
        $new_nodes = [];
92 22
        foreach ($nodes as $r) {
93 22
            list($node, $result) = $r;
94 22
            $new_nodes[] = $this->add_result($clsr($node), $result);
95 22
        }
96 22
        if (count($new_nodes) == 0) {
97
            return [];
98
        }
99 22
        return call_user_func_array("array_merge", $new_nodes);
100
    }
101
102 36
    protected function run_extract(array &$nodes, \Closure $clsr) {
103 36
        foreach ($nodes as $i => $r) {
104 36
            list($node, $result) = $r;
105 36
            if (is_object($result)) {
106
                $clsr($node, clone $result);
107
            }
108
            else {
109 36
                $clsr($node, $result);
110
            }
111 36
            $nodes[$i][1] = $result;
112 36
        }
113 36
    }
114
115 44
    protected function run_filter(array &$nodes, \Closure $clsr) {
116 44
        $res = [];
117 44
        foreach ($nodes as $r) {
118 44
            list($node, $result) = $r;
119 44
            if ($clsr($node, $result)) {
120 42
                $res[] = $r;
121 42
            }
122 44
        }
123 44
        return $res;
124
    }
125
126 50
    protected function add_result(array $nodes, &$result) {
127 50
        $res = [];
128 50
        foreach ($nodes as $node) {
129 49
            $res[] = [$node, $result];
130 50
        }
131 50
        return $res;
132
    }
133
134
    // Convenience Functions
135
136
    /**
137
     * @inheritdocs
138
     */
139 12
    public function filter_by_types(array $types) {
140
        return $this->filter(function(Node $n) use ($types) {
141 12
            return in_array($n->type(), $types);
142 12
        });
143
    }
144
145
    /**
146
     * @inheritdocs
147
     */
148 20
    public function expand_relations(array $types) {
149
        return $this->expand(function(Node $n) use (&$types) {
150
            return array_filter
151 18
                ( $n->relations()
152
                , function(Relation $r) use (&$types) {
153 17
                    return in_array($r->type(), $types);
154 18
                });
155 20
        });
156
    }
157
158
    /**
159
     * @inheritdocs
160
     */
161
    public function expand_target() {
162 13
        return $this->expand(function(Relation $r) {
163 9
            return [$r->target()];
164 13
        });
165
    }
166
}
167