Completed
Push — master ( c6ecf3...3eacba )
by stéphane
02:27
created

NodeList::buildList()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
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 10
    public function __construct(Node $node = null)
26
    {
27
        // parent::__construct();
28
        // $this->setIteratorMode(self::IT_MODE_KEEP);
29 10
        if (!is_null($node)) {
30 10
            $this->push($node);
31
        }
32 10
    }
33
34 1
    public function has(string $nodeType):bool
35
    {
36 1
        $tmp = clone $this;
37 1
        $tmp->rewind();
38 1
        $fqn = __NAMESPACE__."\\$nodeType";
39 1
        foreach ($tmp as $child) {
40 1
            if ($child instanceof $fqn) return true;
41
        }
42 1
        return false;
43
    }
44
45 2
    public function hasContent():bool
46
    {
47 2
        $tmp = clone $this;
48 2
        $tmp->rewind();
49 2
        foreach ($tmp as $child) {
50 2
            if (!($child instanceof NodeComment)
51 2
                && !($child instanceof NodeDirective)
52 2
                && !($child instanceof NodeBlank)
53 1
                && !($child instanceof NodeDocstart
54 2
                && is_null($child->value)) ) return true;
55
        }
56 1
        return false;
57
    }
58
59 10
    public function push($node)
60
    {
61 10
        $type = null;
62 10
        if     ($node instanceof NodeItem )    $type = self::SEQUENCE;
63 10
        elseif ($node instanceof NodeKey)      $type = self::MAPPING;
64 10
        elseif ($node instanceof NodeSetKey
65 10
             || $node instanceof NodeSetValue) {
66 1
            $type = self::SET;
67 10
        } elseif ($node instanceof NodeScalar ){
68 3
            $type = self::MULTILINE;
69
        }
70 10
        if (!is_null($type) && $this->checkTypeCoherence($type)) {
71 3
            $this->type = $type;
72
        }
73 10
        parent::push($node);
74 10
    }
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 4
    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 4
       return (bool) $estimatedType;
92
    }
93
94 1
    public function build(&$parent = null)
95
    {
96 1
        switch ($this->type) {
97 1
            case self::MAPPING:  //fall through
98 1
            case self::SET:
99 1
                $collect = $parent ?? new \StdClass;
100 1
                return $this->buildList($collect);
101 1
            case self::SEQUENCE:
102 1
                $collect = $parent ?? [];
103 1
                return $this->buildList($collect);
104
            default:
105 1
                $this->filterComment();
106 1
                return Builder::getScalar($this->buildMultiline());
107
        }
108
    }
109
110 2
    public function buildList(&$collector)
111
    {
112 2
        $this->rewind();
113 2
        foreach ($this as $child) {
114 2
            $child->build($collector);
115
        }
116 2
        return $collector;
117
    }
118
119 2
    public function buildMultiline():string
120
    {
121 2
        $output = '';
122 2
        $list = clone $this;
123 2
        if ($list->count() > 0) {
124 2
            $list->rewind();
125 2
            $first = $list->shift();
126 2
            $output = trim($first->raw);
127 2
            foreach ($list as $child) {
128 1
                if ($child instanceof NodeScalar) {
129 1
                    $separator = isset($output[-1])  && $output[-1] === "\n" ? '' : ' ';
130 1
                    $output .= $separator.trim($child->raw);
131 1
                } elseif ($child instanceof NodeBlank) {
132 1
                    $output .= "\n";
133
                } else {
134
                    $child->build();
135
                }
136
            }
137
        }
138 2
        return trim($output);
139
    }
140
141 2
    public function filterComment():NodeList
142
    {
143 2
        $this->rewind();
144 2
        $out = new NodeList;
145 2
        foreach ($this as $index => $child) {
146 2
            if ($child instanceof NodeComment) {
147
                // $child->build();
148
            } else {
149 2
                if($child->value instanceof NodeComment) {
150
                    // $child->value->build();
151
                    // $child->value = null;
152 2
                } elseif($child->value instanceof NodeList) {
153
                    $child->value = $child->value->filterComment();
154
                }
155 2
                $out->push($child);
156
            }
157
        }
158
        // $this->rewind();
159 2
        $out->rewind();
160 2
        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