Scene::attr()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 18
ccs 10
cts 10
cp 1
rs 9.2
cc 4
eloc 12
nc 4
nop 2
crap 4
1
<?php
2
/** @formatter:off
3
 * ******************************************************************
4
 * Created by   Marko Kungla on Jun 20, 2016 - 9:01:22 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         Scene.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\Extras\Primitives;
27
use \AframeVR\Core\Entity;
28
use \AframeVR\Core\DOM\AframeDOMDocument;
29
use \AframeVR\Core\Assets;
30
use \AframeVR\Core\Exceptions\BadComponentCallException;
31
use \AframeVR\Core\Helpers\EntityChildrenFactory;
32
33
final class Scene
34
{
35
    /* All scenes can use primitives */
36
    use Primitives;
37
38
    /**
39
     * Name with what you can retrieve this scene while working with multiple scenes
40
     *
41
     * @var string $name
42
     */
43
    private $keyword;
44
45
    /**
46
     * Is scene prepared for rendering
47
     *
48
     * @var bool
49
     */
50
    private $prepared;
51
52
    /**
53
     * Assets
54
     *
55
     * @var \AframeVR\Core\Assets
56
     */
57
    protected $assets;
58
59
    /**
60
     * Aframe Document Object Model
61
     *
62
     * @var \AframeVR\Core\DOM\AframeDOMDocument
63
     */
64
    protected $aframeDomObj;
65
66
    /**
67
     * Scene components
68
     *
69
     * @var array $components
70
     */
71
    protected $components = array();
72
73
    /**
74
     * Children Factory
75
     *
76
     * @var \AframeVR\Core\Helpers\EntityChildrenFactory
77
     */
78
    protected $childrenFactory;
79
80
    /**
81
     * Extra scrits to add into head
82
     *
83
     * Like components and shaders
84
     *
85
     * @var array $scripts
86
     */
87
    protected $scripts = array();
88
89
    /**
90
     * Dom element attributes
91
     *
92
     * @var unknown
93
     */
94
    protected $attrs = array();
95
96
    /**
97
     * Scene constructor
98
     *
99
     * @param string $keyword
100
     * @param Config $config
101
     */
102 103
    public function __construct(string $keyword, Config $config)
103
    {
104 103
        $this->keyword         = $keyword;
105 103
        $this->aframeDomObj    = new AframeDOMDocument($config);
106 103
        $this->childrenFactory = new EntityChildrenFactory();
107
        /* Initialize assests manager */
108 103
        $this->asset($config);
109 103
    }
110
111
    /**
112
     * Aframe Document Object Model
113
     *
114
     * @api
115
     *
116
     * @return \AframeVR\Core\DOM\AframeDOMDocument
117
     */
118 2
    public function dom()
119
    {
120 2
        return $this->aframeDomObj;
121
    }
122
123
    /**
124
     * Assets
125
     *
126
     * @api
127
     *
128
     * @param null|Config $config
129
     * @return \AframeVR\Core\Assets
130
     */
131 103
    public function asset(Config $config = null): Assets
132
    {
133 103
        return $this->assets ?? $this->assets = new Assets($config);
0 ignored issues
show
Bug introduced by
It seems like $config defined by parameter $config on line 131 can be null; however, AframeVR\Core\Assets::__construct() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
134
    }
135
136
    /**
137
     * Child entity / primitive
138
     *
139
     * @return \AframeVR\Core\Helpers\EntityChildrenFactory
140
     */
141 78
    public function el(): EntityChildrenFactory
142
    {
143 78
        return $this->childrenFactory;
144
    }
145
146
    /**
147
     * Render the A-Frame scene and return the HTML
148
     *
149
     * @api
150
     *
151
     * @param bool $only_scene
152
     * @return string
153
     */
154 24
    public function save($only_scene = false, string $file = null): string
155
    {
156 24
        $this->prepare();
157 24
        $html = ! $only_scene ? $this->aframeDomObj->render() : $this->aframeDomObj->renderSceneOnly();
158 24
        if (! empty($file) && is_writable(dirname($file))) {
159 1
            file_put_contents($file, $html);
160
        }
161
162 24
        return $html;
163
    }
164
165
    /**
166
     * Render the A-Frame scene and passthru HTML
167
     *
168
     * @api
169
     *
170
     * @param bool $only_scene
171
     * @return void
172
     */
173 1
    public function render($only_scene = false)
174
    {
175 1
        print $this->save($only_scene);
176 1
    }
177
178
    /**
179
     * Alias of AframeDOMDocument::setTitle(string)
180
     *
181
     * Set <title> tag
182
     * $this->dom()->setTitle(string);
183
     *
184
     * @api
185
     *
186
     * @param string $title
187
     */
188 1
    public function title(string $title)
189
    {
190 1
        $this->dom()->setTitle($title);
191 1
    }
192
193
    /**
194
     * Alias of AframeDOMDocument::setDescription(string)
195
     *
196
     * Set <meta name="description"> tag
197
     * $this->dom()->setDescription(string);
198
     *
199
     * @api
200
     *
201
     * @param string $description
202
     */
203 1
    public function description(string $description)
204
    {
205 1
        $this->dom()->setDescription($description);
206 1
    }
207
208
    /**
209
     * Get scenes keyword
210
     *
211
     * @return string
212
     */
213 1
    public function getKeyword()
214
    {
215 1
        return $this->keyword;
216
    }
217
218
    /**
219
     * Load component for this scene or set it's attr
220
     *
221
     * @param string $component_name
222
     * @param null|mixed $attr_data
223
     * @throws \AframeVR\Core\Exceptions\BadComponentCallException
224
     * @return object|null
225
     */
226 3
    public function attr(string $component_name, $attr_data = null)
227
    {
228 3
        if(!is_null($attr_data)) {
229 2
            $this->attrs[$component_name] = $attr_data;
230 2
            return $this;
231
        }
232 2
        if (! array_key_exists($component_name, $this->components)) {
233 2
            $component = sprintf('\AframeVR\Core\Components\ascene\%s\%sComponent', ucfirst($component_name),
234
                ucfirst($component_name));
235 2
            if (class_exists($component)) {
236 1
                $this->components[$component_name] = new $component();
237
            } else {
238 1
                throw new BadComponentCallException($component_name);
239
            }
240
        }
241
242 1
        return $this->components[$component_name] ?? null;
243
    }
244
245
    /**
246
     * Add scripts like components and shaders
247
     *
248
     * @param string $path
249
     * @return void
250
     */
251 2
    public function addScript(string $path)
252
    {
253 2
        $this->scripts[$path] = true;
254 2
    }
255
256
    /**
257
     * Map calls to scene entities and components
258
     *
259
     * Since we might need to customize these to have
260
     * custom components loaded as $this->methosd aswell therefore
261
     * we have these placeholder magic methods here
262
     *
263
     * @param string $method
264
     * @param array $args
265
     * @throws BadShaderCallException
266
     * @return Entity|\AframeVR\Interfaces\ComponentInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be object|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...
267
     */
268 80
    public function __call(string $method, array $args)
269
    {
270 80
        $id        = $args[0] ?? 0;
271 80
        $primitive = sprintf('\AframeVR\Extras\Primitives\%s', ucfirst($method));
272
273 80
        if ($method === 'entity' || class_exists($primitive)) {
274 78
            return $this->el()->getEntity($method, $id);
275
        } else {
276 2
            return $this->attr($method);
277
        }
278
    }
279
280
    /**
281
     * Add everyting to DOM
282
     *
283
     * @return void
284
     */
285 24
    protected function prepare()
286
    {
287 24
        if ($this->prepared)
288 1
            return;
289
290
        /* Append all assets */
291 24
        $this->prepareAssets();
292
293
        /* Append all primitives */
294 24
        $this->preparePrimitives();
295
296
        /* Append all entities */
297 24
        $this->aframeDomObj->appendEntities($this->childrenFactory->getChildren());
298 24
        $this->aframeDomObj->appendSceneComponents($this->components);
299
300 24
        $this->aframeDomObj->appendSceneAttributes($this->attrs);
301
302
        /* Append extra scripts */
303 24
        $this->prepareScripts();
304
305 24
        $this->prepared = true;
306 24
    }
307
308
    /**
309
     * Append all assets
310
     *
311
     * @return void
312
     */
313 24
    protected function prepareAssets()
314
    {
315 24
        $assets = $this->assets->getAssets();
316 24
        (!$assets) ?: $this->aframeDomObj->appendAssets($assets);
317 24
    }
318
319
    /**
320
     * Append extra scripts
321
     *
322
     * like extra components and shaders used in scene
323
     *
324
     * @return void
325
     */
326 24
    protected function prepareScripts()
327
    {
328 24
        (empty($this->scripts)) ?: $this->aframeDomObj->registerScripts($this->scripts);
329 24
    }
330
}
331