ComponentList::verify_name_uniqueness()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 4
nop 1
dl 0
loc 15
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
namespace Amarkal\UI;
4
5
/**
6
 * Implements a data structure consisting of a list of UI components
7
 */
8
class ComponentList
9
{
10
    /**
11
     * The list of component argument arrays
12
     *
13
     * @var array
14
     */
15
    private $components = array();
16
17
    /**
18
     * Set the components
19
     *
20
     * @param array $components
21
     */
22
    public function __construct( array $components = array() )
23
    {
24
        $this->add_components($components);
25
    }
26
27
    /**
28
     * Get a component by name. Only applicable to value components.
29
     *
30
     * @param string $name
31
     * @return AbstractComponent
32
     */
33
    public function get_by_name( $name )
34
    {
35
        $filtered = $this->filter(function($c) use ($name) {
0 ignored issues
show
Documentation introduced by
function ($c) use($name)...& $c->name === $name; } is of type object<Closure>, but the function expects a object<Amarkal\UI\function>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
36
            return $c instanceof ValueComponentInterface && $c->name === $name;
0 ignored issues
show
Bug introduced by
Accessing name on the interface Amarkal\UI\ValueComponentInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
37
        });
38
        if(count($filtered) < 1)
39
        {
40
            throw new \RuntimeException("No component with the name <b>$name</b> could be found.");
41
        }
42
        return $filtered[0];
43
    }
44
45
    /**
46
     * Get components by type
47
     *
48
     * @param string $type
49
     * @return AbstractComponent[]
50
     */
51
    public function get_by_type( $type )
52
    {
53
        return $this->filter(function($c) use ($type) {
0 ignored issues
show
Documentation introduced by
function ($c) use($type)...onent_type === $type; } is of type object<Closure>, but the function expects a object<Amarkal\UI\function>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
54
            return $c->component_type === $type;
55
        });
56
    }
57
58
    /**
59
     * Get all components.
60
     *
61
     * @return AbstractComponent[]
62
     */
63
    public function get_all()
64
    {
65
        return $this->components;
66
    }
67
68
    /**
69
     * Get all the components that implement the ValueComponentInterface
70
     *
71
     * @return AbstractComponent[]
72
     */
73
    public function get_value_components()
74
    {
75
        return $this->filter(function($c) {
0 ignored issues
show
Documentation introduced by
function ($c) { retu...ueComponentInterface; } is of type object<Closure>, but the function expects a object<Amarkal\UI\function>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
76
            return $c instanceof ValueComponentInterface;
77
        });
78
    }
79
80
    /**
81
     * Get all the components that implement the FilterableComponentInterface
82
     *
83
     * @return AbstractComponent[]
84
     */
85
    public function get_filterable_components()
86
    {
87
        return $this->filter(function($c) {
0 ignored issues
show
Documentation introduced by
function ($c) { retu...leComponentInterface; } is of type object<Closure>, but the function expects a object<Amarkal\UI\function>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
88
            return $c instanceof FilterableComponentInterface;
89
        });
90
    }
91
92
    /**
93
     * Get all the components that implement the ValidatableComponentInterface
94
     *
95
     * @return AbstractComponent[]
96
     */
97
    public function get_validatable_components()
98
    {
99
        return $this->filter(function($c) {
0 ignored issues
show
Documentation introduced by
function ($c) { retu...leComponentInterface; } is of type object<Closure>, but the function expects a object<Amarkal\UI\function>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
100
            return $c instanceof ValidatableComponentInterface;
101
        });
102
    }
103
104
    /**
105
     * Add an array of components to the list
106
     *
107
     * @param AbstractComponent[] $components
108
     * @return void
109
     */
110
    public function add_components( array $components )
111
    {
112
        foreach( $components as $component )
113
        {
114
            $this->add_component($component);
0 ignored issues
show
Documentation introduced by
$component is of type object<Amarkal\UI\AbstractComponent>, but the function expects a array<integer,object<Ama...\UI\AbstractComponent>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
115
        }
116
    }
117
118
    /**
119
     * Add a single component to the list
120
     *
121
     * @param AbstractComponent[] $args
122
     * @return void
123
     */
124
    public function add_component( array $args )
125
    {
126
        if(!array_key_exists('type', $args))
127
        {
128
            throw new \RuntimeException("Component configuration arrays must have a <b>type</b> argument");
129
        }
130
131
        $comp = ComponentFactory::create($args['type'], $args);
0 ignored issues
show
Documentation introduced by
$args['type'] is of type object<Amarkal\UI\AbstractComponent>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
132
133
        $this->verify_name_uniqueness($comp);
134
        $this->components[] = $comp;
135
    }
136
137
    /**
138
     * Verify that the given component name is unique among the list of value components
139
     *
140
     * @param AbstractComponent $comp
141
     * @return void
142
     */
143
    private function verify_name_uniqueness( AbstractComponent $comp )
144
    {
145
        if(!($comp instanceof ValueComponentInterface))
146
        {
147
            return;
148
        }
149
150
        foreach ($this->components as $c) 
151
        {
152
            if($c->name === $comp->name)
153
            {
154
                throw new \RuntimeException("Duplicate component name detected for the name <b>{$c->name}</b>.");
155
            }
156
        }
157
    }
158
159
    /**
160
     * Filter the list of components
161
     *
162
     * @param function $callable
163
     * @return array
164
     */
165
    private function filter( $callable )
166
    {
167
        // array_values is needed in order to reindex the array after filtering it
168
        return array_values(array_filter($this->components, $callable));
169
    }
170
}