Completed
Pull Request — master (#63)
by Marko
06:31
created

Entity::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 1
cts 1
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 0
crap 1
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\Helpers\{
33
    EntityChildrenFactory,
34
    MeshAttributes,
35
    Helper
36
};
37
use \AframeVR\Core\Animation;
38
use \DOMElement;
39
use \Closure;
40
41
class Entity implements EntityInterface
42
{
43
    use MeshAttributes;
44
    
45
    /**
46
     * Array of used components
47
     *
48
     * @var array
49
     */
50
    protected $components = array();
51
    
52
    /**
53
     * Array of used animations
54
     *
55
     * @var array
56
     */
57
    protected $animations = array();
58
    
59
    /**
60
     * Dom element attributes
61
     *
62
     * @var unknown
63
     */
64
    protected $attrs = array();
65
    
66
    /**
67
     * Children Factory
68
     *
69
     * @var EntityChildrenFactory
70
     */
71
    protected $childrenFactory;
72
    
73
    /**
74
     * Indent used when rendering formated outout
75
     *
76
     * @var unknown
77
     */
78
    private $indentation = 0;
79 110
80
    /**
81 110
     * Constructor
82
     *
83
     * @param string $id            
84 110
     */
85 110
    public function __construct(string $id = 'untitled')
86 110
    {
87
        $this->attr('id', $id);
88
        
89 110
        /* Extending entity reset | initial setup */
90
        $this->reset();
91
    }
92 110
93 110
    /**
94
     * Reset primitive default attributtes
95 60
     *
96
     * {@inheritdoc}
97 60
     *
98
     * @return void
99 73
     */
100
    public function reset()
101 73
    {
102
        /* Components which All entities inherently have */
103
        $this->component('Position');
104
        $this->component('Rotation');
105
        $this->component('Scale');
106
    }
107
108
    /**
109
     * Set DOM attributes
110 110
     *
111
     * @param string $attr            
112 110
     * @param string $val            
113 110
     * @return void
114
     */
115
    public function attr(string $attr, string $val)
116
    {
117
        $this->attrs[$attr] = $val;
118
    }
119
120 7
    /**
121
     * Child entity / primitive
122 7
     *
123
     * @return EntityChildrenFactory
0 ignored issues
show
Documentation introduced by
Should the return type not be Helpers\EntityChildrenFactory?

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 child(): EntityChildrenFactory
126
    {
127
        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 object<EntityChildrenFactory> 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...
128
    }
129
130
    /**
131
     * Position component
132
     *
133
     * All entities inherently have the position component.
134
     *
135 21
     * @param int|float $x_axis            
136
     * @param int|float $y_axis            
137 21
     * @param int|float $z_axis            
138 21
     * @return EntityInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be \AframeVR\Interfaces\EntityInterface?

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...
139 21
     */
140 21
    public function position(float $x_axis = 0, float $y_axis = 0, float $z_axis = 0): EntityInterface
141
    {
142
        $this->component('Position')->positionX($x_axis);
143
        $this->component('Position')->positionY($y_axis);
144
        $this->component('Position')->positionZ($z_axis);
145
        return $this;
146
    }
147
148
    /**
149
     * Rotation component
150
     *
151
     * All entities inherently have the rotation component.
152
     *
153 20
     * @param int|float $roll            
154
     * @param int|float $pitch            
155 20
     * @param int|float $yaw            
156 20
     * @return EntityInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be \AframeVR\Interfaces\EntityInterface?

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...
157 20
     */
158 20
    public function rotation(float $roll = 0, float $pitch = 0, float $yaw = 0): EntityInterface
159
    {
160
        $this->component('Rotation')->roll($roll);
161
        $this->component('Rotation')->pitch($pitch);
162
        $this->component('Rotation')->yaw($yaw);
163
        return $this;
164
    }
165
166
    /**
167
     * Scale component
168
     *
169
     * All entities inherently have the scale component.
170
     *
171 17
     * @param int|float $scale_x            
172
     * @param int|float $scale_y            
173 17
     * @param int|float $scale_z            
174 17
     * @return EntityInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be \AframeVR\Interfaces\EntityInterface?

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...
175 17
     */
176 17
    public function scale(float $scale_x = 1, float $scale_y = 1, float $scale_z = 1): EntityInterface
177
    {
178
        $this->component('Scale')->scaleX($scale_x);
179
        $this->component('Scale')->scaleY($scale_y);
180
        $this->component('Scale')->scaleZ($scale_z);
181
        return $this;
182
    }
183
184
    /**
185 5
     * Animations
186
     *
187 5
     * @param mixed $name            
188
     * @return \AframeVR\Interfaces\AnimationInterface
189
     */
190
    public function animation($name = 'untitled'): AnimationInterface
191
    {
192
        return $this->animations[$name] ?? $this->animations[$name] = new Animation();
193
    }
194
195
    /**
196 3
     * Set mixin attribute
197
     *
198 3
     * @param string $id            
199 3
     * @return \AframeVR\Core\Entity
200
     */
201
    public function mixin(string $id)
202
    {
203
        $this->attr('mixin', $id);
204
        return $this;
205
    }
206
207
    /**
208
     * Load component for this entity
209 110
     *
210
     * @param string $component_name            
211 110
     * @throws \AframeVR\Core\Exceptions\BadComponentCallException
212 110
     * @return object|null
213
     */
214 110 View Code Duplication
    public function component(string $component_name)
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...
215 110
    {
216
        if (! array_key_exists($component_name, $this->components)) {
217 1
            $component = sprintf('\AframeVR\Core\Components\%s\%sComponent', ucfirst($component_name), 
218
                ucfirst($component_name));
219
            if (class_exists($component)) {
220
                $this->components[$component_name] = new $component();
221 110
            } else {
222
                throw new BadComponentCallException($component_name);
223
            }
224
        }
225
        
226
        return $this->components[$component_name] ?? null;
227
    }
228
229
    /**
230
     * Handle entity components
231
     *
232
     * Since we might need to customize these to have
233
     * custom components loaded as $this->methosd aswell therefore
234 32
     * we have these placeholder magic methods here
235
     *
236 32
     * @param string $component_name            
237 32
     * @param array $args            
238 32
     */
239 32 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...
240 32
    {
241
        if (! method_exists($this, $component_name)) {
242
            $this->{$component_name} = Closure::bind(
243 32
                function () use ($component_name) {
244
                    return $this->component($component_name);
245
                }, $this, get_class());
246
        }
247
        
248
        return call_user_func($this->{$component_name}, $args);
249
    }
250
251
    /**
252 5
     * Create and add DOM element of the entity
253
     *
254 5
     * @param \DOMDocument $aframe_dom            
255
     * @return \DOMElement
256 5
     */
257
    public function domElement(\DOMDocument &$aframe_dom): DOMElement
258 5
    {
259
        $a_entity = $aframe_dom->createElement('a-entity');
260
        
261
        $this->appendAttributes($a_entity);
262
 
263 5
        foreach ($this->components as $component) {
264 5
            /*
265
             * Check does component has any attributes to add to DOM element.
266
             * default attributes most of cases are ommited so we might not have any attributes to add
267 5
             */
268 5
            if ($component->hasDOMAttributes())
269 5
                $a_entity->setAttributeNode($component->getDOMAttr());
270
        }
271
        
272
        $this->appendChildren($aframe_dom, $a_entity);
273
        $this->appendAnimations($aframe_dom, $a_entity);
274
        return $a_entity;
275
    }
276
277 5
    /**
278
     * Append DOM attributes no set by components
279 5
     *
280 5
     * @param \DOMElement $a_entity            
281
     */
282 5
    private function appendAttributes(\DOMElement &$a_entity)
283
    {
284 5
        foreach ($this->attrs as $attr => $val) {
285
            $this->setAttribute($a_entity, $attr, $val);
286 5
        }
287 5
    }
288
289 2 View Code Duplication
    private function setAttribute(&$a_entity, $attr, $val)
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...
290 2
    {
291
        if ($attr === 'id' && ($val === 'untitled' || is_numeric($val)))
292
            return;
293
        
294
        $a_entity->setAttribute($attr, $val);
295
    }
296
297
    /**
298 5
     * Append childern to entities DOM element
299
     *
300 5
     * @param \DOMDocument $aframe_dom            
301 2
     * @param \DOMElement $a_entity            
302 2
     */
303 2
    private function appendChildren(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
304 2
    {
305
        if ($this->childrenFactory instanceof EntityChildrenFactory) {
306
            foreach ($this->childrenFactory->getChildern() as $child) {
307 5
                $this->addFormatComment($aframe_dom, $a_entity, "\n\t");
308
                $a_entity->appendChild($child->domElement($aframe_dom));
309
                $this->addFormatComment($aframe_dom, $a_entity, '');
310
            }
311
        }
312
    }
313
314
    /**
315 5
     * Append childern to entities DOM element
316
     *
317 5
     * @param \DOMDocument $aframe_dom            
318 2
     * @param \DOMElement $a_entity            
319 2
     */
320 2
    private function appendAnimations(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
321
    {
322 5
        foreach ($this->animations as $animations) {
323
            $this->addFormatComment($aframe_dom, $a_entity, "\n\t");
324
            $a_entity->appendChild($animations->domElement($aframe_dom));
325
            $this->addFormatComment($aframe_dom, $a_entity, '');
326
        }
327
    }
328
329
    /**
330
     * Add format comment
331 2
     * 
332
     * @param \DOMDocument $aframe_dom            
333 2
     * @param \DOMElement $a_entity            
334 2
     * @param string $content            
335 2
     */
336
    private function addFormatComment(\DOMDocument &$aframe_dom, \DOMElement &$a_entity, string $content)
337 2
    {
338
        if ($aframe_dom->formatOutput) {
339
            $com = $aframe_dom->createComment($content);
340
            $a_entity->appendChild($com);
341
        }
342
    }
343
}
344