Test Failed
Branch master (b38a7a)
by stéphane
12:04
created

NodeList::buildMultiline()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

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