Passed
Push — master ( f81cc4...5281ab )
by stéphane
04:50
created

NodeList::has()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 9
ccs 7
cts 7
cp 1
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
namespace Dallgoot\Yaml;
4
5
use Dallgoot\Yaml\Nodes\NodeGeneric;
6
use Dallgoot\Yaml\Nodes\Blank;
7
use Dallgoot\Yaml\Nodes\Comment;
8
use Dallgoot\Yaml\Nodes\Directive;
9
use Dallgoot\Yaml\Nodes\Docstart;
10
use Dallgoot\Yaml\Nodes\Item;
11
use Dallgoot\Yaml\Nodes\Key;
12
use Dallgoot\Yaml\Nodes\SetKey;
13
use Dallgoot\Yaml\Nodes\SetValue;
14
use Dallgoot\Yaml\Nodes\Scalar;
15
16
17
/**
18
 * A collection of Nodes
19
 *
20
 * @author  Stéphane Rebai <[email protected]>
21
 * @license Apache 2.0
22
 * @link    https://github.com/dallgoot/yaml
23
 */
24
class NodeList extends \SplDoublyLinkedList
25
{
26
    const MAPPING   = 1;
27
    const MULTILINE = 2;
28
    const SEQUENCE  = 4;
29
    const SET       = 8;
30
31
    public $type;
32
33
    /**
34
     * NodeList constructor
35
     *
36
     * @param NodeGeneric|null $node (optional) a node that will be pushed as first element
37
     */
38 10
    public function __construct(NodeGeneric $node = null)
39
    {
40
        // parent::__construct();
41
        // $this->setIteratorMode(self::IT_MODE_KEEP);
42 10
        if (!is_null($node)) {
43 10
            $this->push($node);
44
        }
45 10
    }
46
47 1
    public function has(string $nodeType):bool
48
    {
49 1
        $tmp = clone $this;
50 1
        $tmp->rewind();
51 1
        $fqn = __NAMESPACE__."\\Nodes\\$nodeType";
52 1
        foreach ($tmp as $child) {
53 1
            if ($child instanceof $fqn) return true;
54
        }
55 1
        return false;
56
    }
57
58 2
    public function hasContent():bool
59
    {
60 2
        $tmp = clone $this;
61 2
        $tmp->rewind();
62 2
        foreach ($tmp as $child) {
63 2
            if (!($child instanceof Comment)
64 2
                && !($child instanceof Directive)
65 2
                && !($child instanceof Blank)
66 1
                && !($child instanceof Docstart
67 2
                && is_null($child->value)) ) return true;
68
        }
69 1
        return false;
70
    }
71
72 10
    public function push($node)
73
    {
74 10
        $type = null;
75 10
        if     ($node instanceof Item )    $type = self::SEQUENCE;
76 10
        elseif ($node instanceof Key)      $type = self::MAPPING;
77 10
        elseif ($node instanceof SetKey
78 10
             || $node instanceof SetValue) {
79 1
            $type = self::SET;
80 10
        } elseif ($node instanceof Scalar ){
81 3
            $type = self::MULTILINE;
82
        }
83 10
        if (!is_null($type) && $this->checkTypeCoherence($type)) {
84 3
            $this->type = $type;
85
        }
86 10
        parent::push($node);
87 10
    }
88
89
    /**
90
     * Verify that the estimated type is coherent with this list current $type
91
     *
92
     * @param      int      $estimatedType  The estimated type
93
     *
94
     * @return     boolean  True if coherent, False otherwise
95
     * @todo       implement invalid cases
96
     */
97 4
    public function checkTypeCoherence($estimatedType):bool
98
    {
99
       // if ($this->type === self::MAPPING) {
100
       //     if ($estimatedType === self::SEQUENCE) {
101
       //         throw new \ParseError("Error : no coherence in types", 1);
102
       //     }
103
       // }
104 4
       return (bool) $estimatedType;
105
    }
106
107 1
    public function build(&$parent = null)
108
    {
109 1
        switch ($this->type) {
110 1
            case self::MAPPING:  //fall through
111 1
            case self::SET:
112 1
                $collect = $parent ?? new \StdClass;
113 1
                return $this->buildList($collect);
114 1
            case self::SEQUENCE:
115 1
                $collect = $parent ?? [];
116 1
                return $this->buildList($collect);
117
            default:
118 1
                $this->filterComment();
119 1
                return Builder::getScalar($this->buildMultiline());
120
        }
121
    }
122
123 2
    public function buildList(&$collector)
124
    {
125 2
        $this->rewind();
126 2
        foreach ($this as $child) {
127 2
            $child->build($collector);
128
        }
129 2
        return $collector;
130
    }
131
132 2
    public function buildMultiline():string
133
    {
134 2
        $output = '';
135 2
        $list = clone $this;
136 2
        if ($list->count() > 0) {
137 2
            $list->rewind();
138 2
            $first = $list->shift();
139 2
            $output = trim($first->raw);
140 2
            foreach ($list as $child) {
141 1
                if ($child instanceof Scalar) {
142 1
                    $separator = isset($output[-1])  && $output[-1] === "\n" ? '' : ' ';
143 1
                    $output .= $separator.trim($child->raw);
144 1
                } elseif ($child instanceof Blank) {
145 1
                    $output .= "\n";
146
                } else {
147
                    $child->build();
148
                }
149
            }
150
        }
151 2
        return trim($output);
152
    }
153
154
    /**
155
     * Remove NodeComment and returns a new one
156
     *
157
     * @return   NodeList  a new NodeList without NodeComment in it
158
     * @todo     double check that NodeComment are built
159
     */
160 2
    public function filterComment():NodeList
161
    {
162 2
        $this->rewind();
163 2
        $out = new NodeList;
164 2
        foreach ($this as $index => $child) {
165 2
            if ($child instanceof Comment) {
166
                // $child->build();
167
            } else {
168 2
                if($child->value instanceof Comment) {
169
                    // $child->value->build();
170
                    // $child->value = null;
171 2
                } elseif($child->value instanceof NodeList) {
172
                    $child->value = $child->value->filterComment();
173
                }
174 2
                $out->push($child);
175
            }
176
        }
177
        // $this->rewind();
178 2
        $out->rewind();
179 2
        return $out;
180
    }
181
182
    /**
183
     * Provides a slimmer output when using var_dump Note: currently PHP ignores it on SPL types
184
     * @todo activate when PHP supports it
185
     */
186
    // public function __debugInfo()
187
    // {
188
    //     return ['type'=> Y::getName($this->type), 'dllist'=> $this->dllist];
189
    // }
190
}
191