Passed
Push — master ( 42571c...f8295f )
by stéphane
09:20
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
                // return Nodes\Scalar::getScalar($this->buildMultiline());
120 1
                return (new Nodes\Scalar('', 0))->getScalar($this->buildMultiline(), true);
121
        }
122
    }
123
124 2
    public function buildList(&$collector)
125
    {
126 2
        $this->rewind();
127 2
        foreach ($this as $child) {
128 2
            $child->build($collector);
129
        }
130 2
        return $collector;
131
    }
132
133 2
    public function buildMultiline():string
134
    {
135 2
        $output = '';
136 2
        $list = clone $this;
137 2
        if ($list->count() > 0) {
138 2
            $list->rewind();
139 2
            $first = $list->shift();
140 2
            $output = trim($first->raw);
141 2
            foreach ($list as $child) {
142 1
                if ($child instanceof Scalar) {
143 1
                    $separator = isset($output[-1])  && $output[-1] === "\n" ? '' : ' ';
144 1
                    $output .= $separator.trim($child->raw);
145 1
                } elseif ($child instanceof Blank) {
146 1
                    $output .= "\n";
147
                } else {
148
                    $child->build();
149
                }
150
            }
151
        }
152 2
        return trim($output);
153
    }
154
155
    /**
156
     * Remove NodeComment and returns a new one
157
     *
158
     * @return   NodeList  a new NodeList without NodeComment in it
159
     * @todo     double check that NodeComment are built
160
     */
161 2
    public function filterComment():NodeList
162
    {
163 2
        $this->rewind();
164 2
        $out = new NodeList;
165 2
        foreach ($this as $index => $child) {
166 2
            if ($child instanceof Comment) {
167
                // $child->build();
168
            } else {
169 2
                if($child->value instanceof Comment) {
170
                    // $child->value->build();
171
                    // $child->value = null;
172 2
                } elseif($child->value instanceof NodeList) {
173
                    $child->value = $child->value->filterComment();
174
                }
175 2
                $out->push($child);
176
            }
177
        }
178
        // $this->rewind();
179 2
        $out->rewind();
180 2
        return $out;
181
    }
182
183
    /**
184
     * Provides a slimmer output when using var_dump Note: currently PHP ignores it on SPL types
185
     * @todo activate when PHP supports it
186
     */
187
    // public function __debugInfo()
188
    // {
189
    //     return ['type'=> Y::getName($this->type), 'dllist'=> $this->dllist];
190
    // }
191
}
192