Completed
Push — master ( 5c9909...94f348 )
by Marko
02:17
created

Material::removeDefaultDOMAttributes()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 0
cts 7
cp 0
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 3
nop 0
crap 30
1
<?php
2
/** @formatter:off
3
 * ******************************************************************
4
 * Created by   Marko Kungla on Jun 21, 2016 - 1:43:40 AM
5
 * Contact      [email protected]
6
 * @copyright   2016 Marko Kungla - https://github.com/mkungla
7
 * @license     The MIT License (MIT)
8
 * 
9
 * @category       AframeVR
10
 * @package        aframe-php
11
 * 
12
 * Lang         PHP (php version >= 7)
13
 * Encoding     UTF-8
14
 * File         Material.php
15
 * Code format  PSR-2 and 12
16
 * @link        https://github.com/mkungla/aframe-php
17
 ^ @issues      https://github.com/mkungla/aframe-php/issues
18
 * ********************************************************************
19
 * Contributors:
20
 * @author Marko Kungla <[email protected]>
21
 * ********************************************************************
22
 * Comments:
23
 * @formatter:on */
24
namespace AframeVR\Components;
25
26
use \AframeVR\Interfaces\ComponentInterface;
27
use \AframeVR\Interfaces\ShaderInterface;
28
use \AframeVR\Core\Exceptions\BadShaderCallException;
29
30
class Material implements ComponentInterface
31
{
32
33
    private $shaderObj;
34
35
    /**
36
     * Whether depth testing is enabled when rendering the material.
37
     *
38
     * @var bool true
39
     */
40
    protected $depthTest = 'true';
41
42
    /**
43
     * Extent of transparency.
44
     * If the transparent property is not true,
45
     * then the material will remain opaque and opacity will only affect color.
46
     *
47
     * @var string 1.0
48
     */
49
    protected $opacity = 1.0;
50
51
    /**
52
     * Whether material is transparent.
53
     * Transparent entities are rendered after non-transparent entities.
54
     *
55
     * @var bool false
56
     */
57
    protected $transparent = 'false';
58
59
    /**
60
     * Which sides of the mesh to render.
61
     * Can be one of front, back, or double.
62
     *
63
     * @var unknown
64
     */
65
    protected $side = 'front';
66
67
    /**
68
     * To set a texture using one of the built-in shading models, specify the src property.
69
     *
70
     * src can be a selector to either an <img> or <video> element:
71
     */
72
    protected $src = false;
73
74
    /**
75
     * Get Component scripts
76
     *
77
     * {@inheritdoc}
78
     *
79
     * @return array
80
     */
81
    public function getScripts(): array
82
    {
83
        return array();
84
    }
85
86
    /**
87
     * Does component have DOM Atributes
88
     *
89
     * {@inheritdoc}
90
     *
91
     * @return bool
92
     */
93
    public function hasDOMAttributes(): bool
94
    {
95
        return ! empty(get_object_vars($this)) || ! empty(get_object_vars($this->shaderObj));
96
    }
97
98
    /**
99
     * Remove default DOMElement Attributes which are not required
100
     *
101
     * @return void
102
     */
103
    public function removeDefaultDOMAttributes()
104
    {
105
        $defaults = array(
106
            'depthTest' => 'true',
107
            'opacity' => 1.0,
108
            'transparent' => 'false',
109
            'side' => 'front'
110
        );
111
        foreach (get_object_vars($this) as $name => $value) {
112
            if (empty($value) || (array_key_exists($name, $defaults) && $value === $defaults[$name]))
113
                unset($this->$name);
114
        }
115
        
116
        /* Remove defaults from current shader */
117
        $this->shaderObj->removeDefaultDOMAttributes();
118
    }
119
120
    /**
121
     * Get DOMAttr for the entity
122
     *
123
     * @return DOMAttr
0 ignored issues
show
Documentation introduced by
Should the return type not be \DOMAttr?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
124
     */
125
    public function getDOMAttributes(): \DOMAttr
126
    {
127
        $material = array(
128
            'depthTest' => $this->depthTest ?? null,
129
            'opacity' => $this->opacity ?? null,
130
            'transparent' => $this->transparent ?? null,
131
            'side' => $this->side ?? null
132
        );
133
        foreach ($material as $key => $val) {
134
            if (empty($val) || ! property_exists($key, $this))
135
                unset($material[$key]);
136
        }
137
        if (! empty($material)) {
138
            $material_format = implode(': %s; ', array_keys($material)) . ': %s;';
139
            $attributes[] = vsprintf($material_format, array_values($material));
0 ignored issues
show
Coding Style Comprehensibility introduced by
$attributes was never initialized. Although not strictly required by PHP, it is generally a good practice to add $attributes = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
140
        }
141
        
142
        $shader_format = implode(': %s; ', array_keys(get_object_vars($this->shaderObj))) . ': %s;';
143
        $attributes[] = vsprintf($shader_format, array_values(get_object_vars($this->shaderObj)));
0 ignored issues
show
Bug introduced by
The variable $attributes does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
144
        
145
        $format = count($attributes) === 1 ? '%s' : '%s %s';
146
        return new \DOMAttr('material', vsprintf($format, $attributes));
147
    }
148
149
    /**
150
     * Which shader or shading model to use.
151
     * Defaults to the built-in standard shading model.
152
     * Can be set to the built-in flat shading model or to a registered custom shader
153
     *
154
     * @var string standard
155
     */
156
    public function shader(string $shader = 'standard')
157
    {
158
        if ($this->shaderObj instanceof ShaderInterface)
159
            return $this->shaderObj;
160
        
161
        try {
162
            $shader = sprintf('\AframeVR\Core\Shaders\%s', ucfirst($shader));
163
            if (class_exists($shader)) {
164
                $this->shaderObj = new $shader();
165
            } else {
166
                throw new BadShaderCallException($shader);
167
            }
168
        } catch (BadShaderCallException $e) {
169
            die($e->getMessage());
170
        }
171
        return $this->shaderObj;
172
    }
173
174
    /**
175
     * opacity
176
     *
177
     * Extent of transparency. If the transparent property is not true,
178
     * then the material will remain opaque and opacity will only affect color.
179
     *
180
     * @param float $opacity            
181
     * @return Entity
0 ignored issues
show
Documentation introduced by
Should the return type not be Entity|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
182
     */
183
    public function opacity(float $opacity = 1.0)
184
    {
185
        $this->opacity = $opacity;
0 ignored issues
show
Documentation Bug introduced by
The property $opacity was declared of type string, but $opacity is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
186
    }
187
188
    /**
189
     * transparent
190
     *
191
     * Whether material is transparent. Transparent entities are rendered after non-transparent entities.
192
     *
193
     * @param string $transparent            
194
     */
195
    public function transparent(string $transparent = 'false')
196
    {
197
        $this->transparent = $transparent;
0 ignored issues
show
Documentation Bug introduced by
The property $transparent was declared of type boolean, but $transparent is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
198
    }
199
200
    /**
201
     * side
202
     *
203
     * Which sides of the mesh to render. Can be one of front, back, or double
204
     *
205
     * @param string $side            
206
     * @return EntityInterface
207
     */
208
    public function side(string $side = 'front'): EntityInterface
209
    {
210
        $this->side = $side;
0 ignored issues
show
Documentation Bug introduced by
It seems like $side of type string is incompatible with the declared type object<AframeVR\Components\unknown> of property $side.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
211
    }
212
}
213