Completed
Pull Request — master (#66)
by Marko
06:34
created

Scene::prepareAssets()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
ccs 0
cts 0
cp 0
rs 9.4285
cc 2
eloc 3
nc 2
nop 0
crap 6
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 98
     */
87
    protected $scripts = array();
88 98
89 98
    /**
90
     * Scene constructor
91 98
     *
92 98
     * @param string $keyword
93
     * @param Config $config
94
     */
95
    public function __construct(string $keyword, Config $config)
96
    {
97
        $this->keyword         = $keyword;
98
        $this->aframeDomObj    = new AframeDOMDocument($config);
99
        $this->childrenFactory = new EntityChildrenFactory();
100
        /* Initialize assests manager */
101 2
        $this->asset($config);
102
    }
103 2
104
    /**
105
     * Aframe Document Object Model
106
     *
107
     * @api
108
     *
109
     * @return \AframeVR\Core\DOM\AframeDOMDocument
110
     */
111
    public function dom()
112
    {
113
        return $this->aframeDomObj;
114 51
    }
115
116 51
    /**
117
     * Assets
118
     *
119
     * @api
120
     *
121
     * @param null|Config $config
122
     * @return \AframeVR\Core\Assets
123
     */
124
    public function asset(Config $config = null): Assets
125
    {
126 98
        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 124 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...
127
    }
128 98
129
    /**
130
     * Child entity / primitive
131
     *
132
     * @return \AframeVR\Core\Helpers\EntityChildrenFactory
133
     */
134
    public function child(): EntityChildrenFactory
135
    {
136
        return $this->childrenFactory;
137
    }
138
139 19
    /**
140
     * Render the A-Frame scene and return the HTML
141 19
     *
142 19
     * @api
143 19
     *
144 1
     * @param bool $only_scene
145
     * @return string
146
     */
147 19
    public function save($only_scene = false, string $file = null): string
148
    {
149
        $this->prepare();
150
        $html = ! $only_scene ? $this->aframeDomObj->render() : $this->aframeDomObj->renderSceneOnly();
151
        if (! empty($file) && is_writable(dirname($file))) {
152
            file_put_contents($file, $html);
153
        }
154
155
        return $html;
156
    }
157
158 1
    /**
159
     * Render the A-Frame scene and passthru HTML
160 1
     *
161 1
     * @api
162
     *
163
     * @param bool $only_scene
164
     * @return void
165
     */
166
    public function render($only_scene = false)
167
    {
168
        print $this->save($only_scene);
169
    }
170
171
    /**
172
     * Alias of AframeDOMDocument::setTitle(string)
173 1
     *
174
     * Set <title> tag
175 1
     * $this->dom()->setTitle(string);
176 1
     *
177
     * @api
178
     *
179
     * @param string $title
180
     */
181
    public function title(string $title)
182
    {
183
        $this->dom()->setTitle($title);
184
    }
185
186
    /**
187
     * Alias of AframeDOMDocument::setDescription(string)
188 1
     *
189
     * Set <meta name="description"> tag
190 1
     * $this->dom()->setDescription(string);
191 1
     *
192
     * @api
193
     *
194
     * @param string $description
195
     */
196
    public function description(string $description)
197
    {
198 1
        $this->dom()->setDescription($description);
199
    }
200 1
201
    /**
202
     * Get scenes keyword
203
     *
204
     * @return string
205
     */
206
    public function getKeyword()
207
    {
208
        return $this->keyword;
209
    }
210 2
211
    /**
212 2
     * Load component for this scene or set it's attr
213 2
     *
214
     * @param string $component_name
215 2
     * @param null|string $attr_data
216 1
     * @throws \AframeVR\Core\Exceptions\BadComponentCallException
217
     * @return object|null
218 1
     */
219
    public function attr(string $component_name, string $attr_data = null)
220
    {
221
        if(!is_null($attr_data)) {
222 1
            $this->attrs[$component_name] = $attr_data;
0 ignored issues
show
Bug introduced by
The property attrs does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
223
            return $this;
224
        }
225
        if (! array_key_exists($component_name, $this->components)) {
226
            $component = sprintf('\AframeVR\Core\Components\ascene\%s\%sComponent', ucfirst($component_name),
227
                ucfirst($component_name));
228
            if (class_exists($component)) {
229
                $this->components[$component_name] = new $component();
230
            } else {
231
                throw new BadComponentCallException($component_name);
232
            }
233 28
        }
234
235 28
        return $this->components[$component_name] ?? null;
236 28
    }
237
238 28
    /**
239 26
     * Add scripts like components and shaders
240 26
     *
241
     * @param string $path
242 2
     * @return void
243
     */
244
    public function addScript(string $path)
245
    {
246
        $this->scripts[$path] = true;
247
    }
248
249
    /**
250
     * Map calls to scene entities and components
251
     *
252
     * Since we might need to customize these to have
253
     * custom components loaded as $this->methosd aswell therefore
254
     * we have these placeholder magic methods here
255
     *
256 2
     * @param string $method
257
     * @param array $args
258 2
     * @throws BadShaderCallException
259 2
     * @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...
260 2
     */
261 2
    public function __call(string $method, array $args)
262 2
    {
263
        $id        = $args[0] ?? 0;
264
        $primitive = sprintf('\AframeVR\Extras\Primitives\%s', ucfirst($method));
265 2
266
        if ($method === 'entity' || class_exists($primitive)) {
267
            return $this->child()->getEntity($method, $id);
268
        } else {
269
            return $this->attr($method);
270
        }
271
    }
272
273 19
    /**
274
     * Add everyting to DOM
275 19
     *
276 1
     * @return void
277
     */
278
    protected function prepare()
279 19
    {
280 19
        if ($this->prepared)
281
            return;
282 19
283
        /* Append all assets */
284
        $this->prepareAssets();
285 19
286 19
        /* Append all primitives */
287 19
        $this->preparePrimitives();
288 19
289
        /* Append all entities */
290
        $this->aframeDomObj->appendEntities($this->childrenFactory->getChildren());
291
        $this->aframeDomObj->appendSceneComponents($this->components);
292
293
        $this->aframeDomObj->appendSceneAttributes($this->attrs);
294
295
        /* Append extra scripts */
296
        $this->prepareScripts();
297
298
        $this->prepared = true;
299
    }
300
301
    /**
302
     * Append all assets
303
     *
304
     * @return void
305
     */
306
    protected function prepareAssets()
307
    {
308
        $assets = $this->assets->getAssets();
309
        (!$assets) ?: $this->aframeDomObj->appendAssets($assets);
310
    }
311
312
    /**
313
     * Append extra scripts
314
     *
315
     * like extra components and shaders used in scene
316
     *
317
     * @return void
318
     */
319
    protected function prepareScripts()
320
    {
321
        (empty($this->scripts)) ?: $this->aframeDomObj->registerScripts($this->scripts);
322
    }
323
}
324