Completed
Push — 0.3.x ( e294c0...140210 )
by Marko
04:05
created

Entity   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 293
Duplicated Lines 16.38 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 32
c 0
b 0
f 0
lcom 1
cbo 3
dl 48
loc 293
ccs 87
cts 87
cp 1
rs 9.6

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 15 1
A init() 0 3 1
A defaults() 0 3 1
A attr() 0 4 1
A child() 0 4 1
A position() 0 7 1
A rotation() 0 7 1
A scale() 0 7 1
A animation() 0 4 1
A mixin() 0 5 1
A component() 0 14 3
A __call() 10 11 2
A domElement() 0 19 3
B appendAttributes() 8 8 5
B appendChildren() 16 16 5
A appendAnimations() 14 14 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/** @formatter:off
3
 * ******************************************************************
4
 * Created by   Marko Kungla on Jun 20, 2016 - 9:11:10 PM
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         Entity.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\Core;
25
26
use \AframeVR\Core\Exceptions\BadComponentCallException;
27
use \AframeVR\Interfaces\{
28
    ComponentInterface,
29
    EntityInterface,
30
    AnimationInterface
31
};
32
use \AframeVR\Core\Animation;
33
use \AframeVR\Core\Helpers\EntityChildrenFactory;
34
use \DOMElement;
35
use \Closure;
36
37
class Entity implements EntityInterface
38
{
39
    /**
40
     * Array of used components
41
     *
42
     * @var array
43
     */
44
    protected $components = array();
45
    
46
    /**
47
     * Array of used animations
48
     *
49
     * @var array
50
     */
51
    protected $animations = array();
52
    
53
    /**
54
     * Dom element attributes
55
     *
56
     * @var unknown
57
     */
58
    protected $attrs = array();
59
    
60
    /**
61
     * Children Factory
62
     *
63
     * @var array
64
     */
65
    protected $childrenFactory;
66
    
67
    /**
68
     * Indent used when rendering formated outout
69
     *
70
     * @var unknown
71
     */
72
    private $indentation = 0;
73
74
    /**
75
     * Constructor
76
     *
77
     * @param string $id            
78
     */
79 76
    public function __construct(string $id = 'untitled')
80
    {
81 76
        $this->attr('id', $id);
82
        
83
        /* Components which All entities inherently have */
84 76
        $this->component('Position');
85 76
        $this->component('Rotation');
86 76
        $this->component('Scale');
87
        
88
        /* Extending entity components and init */
89 76
        $this->init();
90
        
91
        /* Extending entity defaults */
92 76
        $this->defaults();
93 76
    }
94
95 45
    public function init()
96
    {
97 45
    }
98
99 45
    public function defaults()
100
    {
101 45
    }
102
103
    /**
104
     * Set DOM attributes
105
     *
106
     * @param string $attr            
107
     * @param string $val            
108
     * @return void
109
     */
110 76
    public function attr(string $attr, string $val)
111
    {
112 76
        $this->attrs[$attr] = $val;
113 76
    }
114
115
    /**
116
     * Child entity / primitive
117
     *
118
     * @return EntityChildrenFactory
119
     */
120 7
    public function child(): EntityChildrenFactory
121
    {
122 7
        return $this->childrenFactory ?? $this->childrenFactory = new EntityChildrenFactory();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \AframeVR\Core\Helpers\EntityChildrenFactory() of type object<AframeVR\Core\Hel...\EntityChildrenFactory> is incompatible with the declared type array of property $childrenFactory.

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...
123
    }
124
125
    /**
126
     * Position component
127
     *
128
     * All entities inherently have the position component.
129
     *
130
     * @param int|float $x_axis            
131
     * @param int|float $y_axis            
132
     * @param int|float $z_axis            
133
     * @return \AframeVR\Core\Entity
134
     */
135 15
    public function position(float $x_axis = 0, float $y_axis = 0, float $z_axis = 0): Entity
136
    {
137 15
        $this->component('Position')->positionX($x_axis);
138 15
        $this->component('Position')->positionY($y_axis);
139 15
        $this->component('Position')->positionZ($z_axis);
140 15
        return $this;
141
    }
142
143
    /**
144
     * Rotation component
145
     *
146
     * All entities inherently have the rotation component.
147
     *
148
     * @param int|float $roll            
149
     * @param int|float $pitch            
150
     * @param int|float $yaw            
151
     * @return \AframeVR\Core\Entity
152
     */
153 14
    public function rotation(float $roll = 0, float $pitch = 0, float $yaw = 0): Entity
154
    {
155 14
        $this->component('Rotation')->roll($roll);
156 14
        $this->component('Rotation')->pitch($pitch);
157 14
        $this->component('Rotation')->yaw($yaw);
158 14
        return $this;
159
    }
160
161
    /**
162
     * Scale component
163
     *
164
     * All entities inherently have the scale component.
165
     *
166
     * @param int|float $scale_x            
167
     * @param int|float $scale_y            
168
     * @param int|float $scale_z            
169
     * @return \AframeVR\Core\Entity
170
     */
171 9
    public function scale(float $scale_x = 1, float $scale_y = 1, float $scale_z = 1): Entity
172
    {
173 9
        $this->component('Scale')->scaleX($scale_x);
174 9
        $this->component('Scale')->scaleY($scale_y);
175 9
        $this->component('Scale')->scaleZ($scale_z);
176 9
        return $this;
177
    }
178
179
    /**
180
     * Animations
181
     *
182
     * @param mixed $name            
183
     * @return \AframeVR\Interfaces\AnimationInterface
184
     */
185 5
    public function animation($name = 'untitled'): AnimationInterface
186
    {
187 5
        return $this->animations[$name] ?? $this->animations[$name] = new Animation();
188
    }
189
190
    /**
191
     * Set mixin attribute
192
     *
193
     * @param string $id            
194
     * @return \AframeVR\Core\Entity
195
     */
196 3
    public function mixin(string $id)
197
    {
198 3
        $this->attr('mixin', $id);
199 3
        return $this;
200
    }
201
202
    /**
203
     * Load component for this entity
204
     *
205
     * @param string $component_name            
206
     * @throws \AframeVR\Core\Exceptions\BadComponentCallException
207
     * @return object|null
208
     */
209 76
    public function component(string $component_name)
210
    {
211 76
        if (! array_key_exists($component_name, $this->components)) {
212 76
            $component = sprintf('\AframeVR\Core\Components\%s\%sComponent', ucfirst($component_name), 
213
                ucfirst($component_name));
214 76
            if (class_exists($component)) {
215 76
                $this->components[$component_name] = new $component();
216
            } else {
217 1
                throw new BadComponentCallException($component_name);
218
            }
219
        }
220
        
221 76
        return $this->components[$component_name] ?? null;
222
    }
223
224
    /**
225
     * Handle entity components
226
     *
227
     * Since we might need to customize these to have
228
     * custom components loaded as $this->methosd aswell therefore
229
     * we have these placeholder magic methods here
230
     *
231
     * @param string $component_name            
232
     * @param array $args            
233
     */
234 21 View Code Duplication
    public function __call(string $component_name, array $args)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
235
    {
236 21
        if (! method_exists($this, $component_name)) {
237 21
            $this->{$component_name} = Closure::bind(
238 21
                function () use ($component_name) {
239 21
                    return $this->component($component_name);
240 21
                }, $this, get_class());
241
        }
242
        
243 21
        return call_user_func($this->{$component_name}, $args);
244
    }
245
246
    /**
247
     * Create and add DOM element of the entity
248
     *
249
     * @param \DOMDocument $aframe_dom            
250
     * @return \DOMElement
251
     */
252 4
    public function domElement(\DOMDocument &$aframe_dom): DOMElement
253
    {
254 4
        $a_entity = $aframe_dom->createElement('a-entity');
255
        
256 4
        $this->appendAttributes($a_entity);
257
        
258 4
        foreach ($this->components as $component) {
259
            /*
260
             * Check does component has any attributes to add to DOM element.
261
             * default attributes most of cases are ommited so we might not have any attributes to add
262
             */
263 4
            if ($component->hasDOMAttributes())
264 4
                $a_entity->setAttributeNode($component->getDOMAttr());
265
        }
266
        
267 4
        $this->appendChildren($aframe_dom, $a_entity);
268 4
        $this->appendAnimations($aframe_dom, $a_entity);
269 4
        return $a_entity;
270
    }
271
272
    /**
273
     * Append DOM attributes no set by components
274
     *
275
     * @param \DOMElement $a_entity            
276
     */
277 4 View Code Duplication
    private function appendAttributes(\DOMElement &$a_entity)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
278
    {
279 4
        foreach ($this->attrs as $attr => $val) {
280 4
            if ($attr === 'id' && ($val === 'untitled' || is_numeric($val)))
281 4
                continue;
282 2
            $a_entity->setAttribute($attr, $val);
283
        }
284 4
    }
285
286
    /**
287
     * Append childern to entities DOM element
288
     *
289
     * @param \DOMDocument $aframe_dom            
290
     * @param \DOMElement $a_entity            
291
     */
292 4 View Code Duplication
    private function appendChildren(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
293
    {
294 4
        if ($this->childrenFactory instanceof EntityChildrenFactory) {
295 2
            foreach ($this->childrenFactory->getChildern() as $child) {
296 2
                if ($aframe_dom->formatOutput) {
297 2
                    $com = $aframe_dom->createComment("\n\t");
298 2
                    $a_entity->appendChild($com);
299
                }
300 2
                $a_entity->appendChild($child->domElement($aframe_dom));
301 2
                if ($aframe_dom->formatOutput) {
302 2
                    $com = $aframe_dom->createComment("");
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
303 2
                    $a_entity->appendChild($com);
304
                }
305
            }
306
        }
307 4
    }
308
309
    /**
310
     * Append childern to entities DOM element
311
     *
312
     * @param \DOMDocument $aframe_dom            
313
     * @param \DOMElement $a_entity            
314
     */
315 4 View Code Duplication
    private function appendAnimations(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
316
    {
317 4
        foreach ($this->animations as $animations) {
318 2
            if ($aframe_dom->formatOutput) {
319 2
                $com = $aframe_dom->createComment("\n\t");
320 2
                $a_entity->appendChild($com);
321
            }
322 2
            $a_entity->appendChild($animations->domElement($aframe_dom));
323 2
            if ($aframe_dom->formatOutput) {
324 2
                $com = $aframe_dom->createComment("");
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
325 2
                $a_entity->appendChild($com);
326
            }
327
        }
328 4
    }
329
}
330