NodeList::buildMultiline()   B
last analyzed

Complexity

Conditions 7
Paths 2

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 7.0145

Importance

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