ArrayDefinition::createNode()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 4 Features 1
Metric Value
c 6
b 4
f 1
dl 0
loc 15
rs 9.4285
cc 2
eloc 9
nc 2
nop 0
1
<?php
2
/*
3
 * This file is part of the Borobudur-Config package.
4
 *
5
 * (c) Hexacodelabs <http://hexacodelabs.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Borobudur\Config\Definition\Builder;
12
13
use Borobudur\Config\Definition\ArrayNode;
14
use Borobudur\Config\Definition\NodeInterface;
15
use Borobudur\Config\Definition\PrototypeArrayNode;
16
use Borobudur\Config\Exception\InvalidArgumentException;
17
18
/**
19
 * @author      Iqbal Maulana <[email protected]>
20
 * @created     8/10/15
21
 */
22
class ArrayDefinition extends AbstractDefinition implements NodeDefinitionContainerInterface
23
{
24
    /**
25
     * @var NodeDefinitionInterface[]
26
     */
27
    protected $children = array();
28
29
    /**
30
     * @var NodeDefinitionInterface
31
     */
32
    protected $prototype;
33
34
    /**
35
     * @var array
36
     */
37
    protected $nullEquivalent = array();
38
39
    /**
40
     * @var NodeDefinitionBuilder|null
41
     */
42
    protected $nodeBuilder;
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    public function setBuilder(NodeDefinitionBuilder $builder)
48
    {
49
        $this->nodeBuilder = $builder;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function append(NodeDefinitionInterface $node)
56
    {
57
        if (isset($this->children[$node->getName()])) {
58
            throw new InvalidArgumentException(sprintf(
59
                'Config named "%s" in "%s" already defined.',
60
                $node->getName(),
61
                $this->getName()
62
            ));
63
        }
64
65
        $this->children[$node->getName()] = $node->setParent($this);
66
67
        return $this;
68
    }
69
70
    /**
71
     * Chain children to builder.
72
     *
73
     * @return NodeDefinitionBuilder
74
     */
75
    public function children()
76
    {
77
        return $this->getNodeBuilder();
78
    }
79
80
    /**
81
     * Set array as prototype (numeric array) with definition type of children.
82
     *
83
     * @param string $type
84
     *
85
     * @return NodeDefinitionInterface
86
     */
87
    public function prototype($type)
88
    {
89
        return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
90
    }
91
92
    /**
93
     * Get node definition builder.
94
     *
95
     * @return NodeDefinitionBuilder
96
     */
97
    protected function getNodeBuilder()
98
    {
99
        if (null === $this->nodeBuilder) {
100
            $this->nodeBuilder = new NodeDefinitionBuilder();
101
        }
102
103
        return $this->nodeBuilder->setParent($this);
104
    }
105
106
    /**
107
     * Create and configure node by definition.
108
     *
109
     * @return NodeInterface
110
     */
111
    protected function createNode()
112
    {
113
        $this->assertParentNode();
114
115
        if (null === $this->prototype) {
116
            $node = $this->instantiateArrayNode();
117
        } else {
118
            $node = $this->instantiatePrototypeArrayNode();
119
        }
120
121
        $node->setRequired($this->required);
122
        $node->setAllowOverwrite($this->allowOverwrite);
123
124
        return $node;
125
    }
126
127
    /**
128
     * Create array node.
129
     *
130
     * @return ArrayNode
131
     */
132
    private function instantiateArrayNode()
133
    {
134
        $node = new ArrayNode($this->name, $this->parent);
0 ignored issues
show
Bug introduced by
It seems like $this->parent can also be of type object<Borobudur\Config\...er\DefinitionInterface> or object<Borobudur\Config\...odeDefinitionInterface>; however, Borobudur\Config\Definit...ractNode::__construct() does only seem to accept null|object<Borobudur\Co...finition\NodeInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
135
136
        foreach ($this->children as $child) {
137
            $child->setParent($node);
138
            $node->append($child->getNode());
139
        }
140
141
        return $node;
142
    }
143
144
    /**
145
     * Create prototype array node.
146
     *
147
     * @return PrototypeArrayNode
148
     */
149
    private function instantiatePrototypeArrayNode()
150
    {
151
        $node = new PrototypeArrayNode($this->name, $this->parent);
0 ignored issues
show
Bug introduced by
It seems like $this->parent can also be of type object<Borobudur\Config\...er\DefinitionInterface> or object<Borobudur\Config\...odeDefinitionInterface>; however, Borobudur\Config\Definit...ractNode::__construct() does only seem to accept null|object<Borobudur\Co...finition\NodeInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
152
153
        if ($this->defaultValueSet) {
154
            $node->setDefaultValue($this->defaultValue);
155
        }
156
157
        $this->prototype->setParent($node);
158
        $node->setPrototype($this->prototype->getNode());
0 ignored issues
show
Compatibility introduced by
$this->prototype->getNode() of type object<Borobudur\Config\Definition\NodeInterface> is not a sub-type of object<Borobudur\Config\...PrototypeNodeInterface>. It seems like you assume a child interface of the interface Borobudur\Config\Definition\NodeInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
159
160
        return $node;
161
    }
162
}
163