Completed
Pull Request — master (#63)
by Marko
03:19
created

Entity::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 5
cts 5
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
80
    /**
81
     * Constructor
82
     *
83
     * @param string $id            
84
     */
85 55
    public function __construct(string $id = 'untitled')
86
    {
87 55
        $this->attr('id', $id);
88
        
89
        /* Extending entity reset | initial setup */
90 55
        $this->reset();
91 55
    }
92
93
    /**
94
     * Reset primitive default attributtes
95
     *
96
     * {@inheritdoc}
97
     *
98
     * @return void
99
     */
100 55
    public function reset()
101
    {
102
        /* Components which All entities inherently have */
103 55
        $this->component('Position');
104 55
        $this->component('Rotation');
105 55
        $this->component('Scale');
106 55
    }
107
108
    /**
109
     * Set DOM attributes
110
     *
111
     * @param string $attr            
112
     * @param string $val            
113
     * @return void
114
     */
115 55
    public function attr(string $attr, string $val)
116
    {
117 55
        $this->attrs[$attr] = $val;
118 55
    }
119
120
    /**
121
     * Child entity / primitive
122
     *
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 1
    public function child(): EntityChildrenFactory
126
    {
127 1
        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
     * @param int|float $x_axis            
136
     * @param int|float $y_axis            
137
     * @param int|float $z_axis            
138
     * @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
     */
140 2
    public function position(float $x_axis = 0, float $y_axis = 0, float $z_axis = 0): EntityInterface
141
    {
142 2
        $this->component('Position')->positionX($x_axis);
143 2
        $this->component('Position')->positionY($y_axis);
144 2
        $this->component('Position')->positionZ($z_axis);
145 2
        return $this;
146
    }
147
148
    /**
149
     * Rotation component
150
     *
151
     * All entities inherently have the rotation component.
152
     *
153
     * @param int|float $roll            
154
     * @param int|float $pitch            
155
     * @param int|float $yaw            
156
     * @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
     */
158 2
    public function rotation(float $roll = 0, float $pitch = 0, float $yaw = 0): EntityInterface
159
    {
160 2
        $this->component('Rotation')->roll($roll);
161 2
        $this->component('Rotation')->pitch($pitch);
162 2
        $this->component('Rotation')->yaw($yaw);
163 2
        return $this;
164
    }
165
166
    /**
167
     * Scale component
168
     *
169
     * All entities inherently have the scale component.
170
     *
171
     * @param int|float $scale_x            
172
     * @param int|float $scale_y            
173
     * @param int|float $scale_z            
174
     * @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
     */
176 2
    public function scale(float $scale_x = 1, float $scale_y = 1, float $scale_z = 1): EntityInterface
177
    {
178 2
        $this->component('Scale')->scaleX($scale_x);
179 2
        $this->component('Scale')->scaleY($scale_y);
180 2
        $this->component('Scale')->scaleZ($scale_z);
181 2
        return $this;
182
    }
183
184
    /**
185
     * Animations
186
     *
187
     * @param mixed $name            
188
     * @return \AframeVR\Interfaces\AnimationInterface
189
     */
190 2
    public function animation($name = 'untitled'): AnimationInterface
191
    {
192 2
        return $this->animations[$name] ?? $this->animations[$name] = new Animation();
193
    }
194
195
    /**
196
     * Set mixin attribute
197
     *
198
     * @param string $id            
199
     * @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
     *
210
     * @param string $component_name            
211
     * @throws \AframeVR\Core\Exceptions\BadComponentCallException
212
     * @return object|null
213
     */
214 55 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
    {
216 55
        if (! array_key_exists($component_name, $this->components)) {
217 55
            $component = sprintf('\AframeVR\Core\Components\%s\%sComponent', ucfirst($component_name), 
218
                ucfirst($component_name));
219 55
            if (class_exists($component)) {
220 55
                $this->components[$component_name] = new $component();
221
            } else {
222 1
                throw new BadComponentCallException($component_name);
223
            }
224
        }
225
        
226 55
        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
     * we have these placeholder magic methods here
235
     *
236
     * @param string $component_name            
237
     * @param array $args            
238
     */
239 29 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
    {
241 29
        if (! method_exists($this, $component_name)) {
242 29
            $this->{$component_name} = Closure::bind(
243 29
                function () use ($component_name) {
244 29
                    return $this->component($component_name);
245 29
                }, $this, get_class());
246
        }
247
        
248 29
        return call_user_func($this->{$component_name}, $args);
249
    }
250
251
    /**
252
     * Create and add DOM element of the entity
253
     *
254
     * @param \DOMDocument $aframe_dom            
255
     * @return \DOMElement
256
     */
257 1
    public function domElement(\DOMDocument &$aframe_dom): DOMElement
258
    {
259 1
        $a_entity = $aframe_dom->createElement('a-entity');
260
        
261 1
        $this->appendAttributes($a_entity);
262
        
263 1
        foreach ($this->components as $component) {
264
            /*
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
             */
268 1
            if ($component->hasDOMAttributes())
269 1
                $a_entity->setAttributeNode($component->getDOMAttr());
270
        }
271
        
272 1
        $this->appendChildren($aframe_dom, $a_entity);
273 1
        $this->appendAnimations($aframe_dom, $a_entity);
274 1
        return $a_entity;
275
    }
276
277
    
278
279
    /**
280
     * Append DOM attributes no set by components
281
     *
282
     * @param \DOMElement $a_entity            
283
     */
284 1
    private function appendAttributes(\DOMElement &$a_entity)
285
    {
286 1
        foreach ($this->attrs as $attr => $val) {
287 1
            $this->setAttribute($a_entity, $attr, $val);
288
        }
289 1
    }
290
291 1 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...
292
    {
293 1
        if ($attr === 'id' && ($val === 'untitled' || is_numeric($val)))
294 1
            return;
295
        
296
        $a_entity->setAttribute($attr, $val);
297
    }
298
299
    /**
300
     * Append childern to entities DOM element
301
     *
302
     * @param \DOMDocument $aframe_dom            
303
     * @param \DOMElement $a_entity            
304
     */
305 1
    private function appendChildren(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
306
    {
307 1
        if ($this->childrenFactory instanceof EntityChildrenFactory) {
308
            foreach ($this->childrenFactory->getChildern() as $child) {
309
                $this->addFormatComment($aframe_dom, $a_entity, "\n\t");
310
                $a_entity->appendChild($child->domElement($aframe_dom));
311
                $this->addFormatComment($aframe_dom, $a_entity, '');
312
            }
313
        }
314 1
    }
315
316
    /**
317
     * Append childern to entities DOM element
318
     *
319
     * @param \DOMDocument $aframe_dom            
320
     * @param \DOMElement $a_entity            
321
     */
322 1
    private function appendAnimations(\DOMDocument &$aframe_dom, \DOMElement &$a_entity)
323
    {
324 1
        foreach ($this->animations as $animations) {
325
            $this->addFormatComment($aframe_dom, $a_entity, "\n\t");
326
            $a_entity->appendChild($animations->domElement($aframe_dom));
327
            $this->addFormatComment($aframe_dom, $a_entity, '');
328
        }
329 1
    }
330
331
    /**
332
     * Add format comment
333
     *
334
     * @param \DOMDocument $aframe_dom            
335
     * @param \DOMElement $a_entity            
336
     * @param string $content            
337
     */
338
    private function addFormatComment(\DOMDocument &$aframe_dom, \DOMElement &$a_entity, string $content)
339
    {
340
        if ($aframe_dom->formatOutput) {
341
            $com = $aframe_dom->createComment($content);
342
            $a_entity->appendChild($com);
343
        }
344
    }
345
}
346