Completed
Pull Request — master (#66)
by Marko
02:37
created

Scene   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 289
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 95.38%

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 5
dl 0
loc 289
ccs 62
cts 65
cp 0.9538
rs 10
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A dom() 0 4 1
A asset() 0 4 1
A child() 0 4 1
A save() 0 10 4
A render() 0 4 1
A title() 0 4 1
A description() 0 4 1
A getKeyword() 0 4 1
A attr() 0 18 4
A addScript() 0 4 1
A __call() 0 11 3
A prepare() 0 20 2
A prepareAssets() 0 5 2
A prepareScripts() 0 4 2
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
     * Scene constructor
91
     *
92
     * @param string $keyword
93
     * @param Config $config
94
     */
95 98
    public function __construct(string $keyword, Config $config)
96
    {
97 98
        $this->keyword         = $keyword;
98 98
        $this->aframeDomObj    = new AframeDOMDocument($config);
99 98
        $this->childrenFactory = new EntityChildrenFactory();
100
        /* Initialize assests manager */
101 98
        $this->asset($config);
102 98
    }
103
104
    /**
105
     * Aframe Document Object Model
106
     *
107
     * @api
108
     *
109
     * @return \AframeVR\Core\DOM\AframeDOMDocument
110
     */
111 2
    public function dom()
112
    {
113 2
        return $this->aframeDomObj;
114
    }
115
116
    /**
117
     * Assets
118
     *
119
     * @api
120
     *
121
     * @param null|Config $config
122
     * @return \AframeVR\Core\Assets
123
     */
124 98
    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
129
    /**
130
     * Child entity / primitive
131
     *
132
     * @return \AframeVR\Core\Helpers\EntityChildrenFactory
133
     */
134 77
    public function child(): EntityChildrenFactory
135
    {
136 77
        return $this->childrenFactory;
137
    }
138
139
    /**
140
     * Render the A-Frame scene and return the HTML
141
     *
142
     * @api
143
     *
144
     * @param bool $only_scene
145
     * @return string
146
     */
147 19
    public function save($only_scene = false, string $file = null): string
148
    {
149 19
        $this->prepare();
150 19
        $html = ! $only_scene ? $this->aframeDomObj->render() : $this->aframeDomObj->renderSceneOnly();
151 19
        if (! empty($file) && is_writable(dirname($file))) {
152 1
            file_put_contents($file, $html);
153
        }
154
155 19
        return $html;
156
    }
157
158
    /**
159
     * Render the A-Frame scene and passthru HTML
160
     *
161
     * @api
162
     *
163
     * @param bool $only_scene
164
     * @return void
165
     */
166 1
    public function render($only_scene = false)
167
    {
168 1
        print $this->save($only_scene);
169 1
    }
170
171
    /**
172
     * Alias of AframeDOMDocument::setTitle(string)
173
     *
174
     * Set <title> tag
175
     * $this->dom()->setTitle(string);
176
     *
177
     * @api
178
     *
179
     * @param string $title
180
     */
181 1
    public function title(string $title)
182
    {
183 1
        $this->dom()->setTitle($title);
184 1
    }
185
186
    /**
187
     * Alias of AframeDOMDocument::setDescription(string)
188
     *
189
     * Set <meta name="description"> tag
190
     * $this->dom()->setDescription(string);
191
     *
192
     * @api
193
     *
194
     * @param string $description
195
     */
196 1
    public function description(string $description)
197
    {
198 1
        $this->dom()->setDescription($description);
199 1
    }
200
201
    /**
202
     * Get scenes keyword
203
     *
204
     * @return string
205
     */
206 1
    public function getKeyword()
207
    {
208 1
        return $this->keyword;
209
    }
210
211
    /**
212
     * Load component for this scene or set it's attr
213
     *
214
     * @param string $component_name
215
     * @param null|string $attr_data
216
     * @throws \AframeVR\Core\Exceptions\BadComponentCallException
217
     * @return object|null
218
     */
219 2
    public function attr(string $component_name, string $attr_data = null)
220
    {
221 2
        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 1
            return $this;
224
        }
225 2
        if (! array_key_exists($component_name, $this->components)) {
226 2
            $component = sprintf('\AframeVR\Core\Components\ascene\%s\%sComponent', ucfirst($component_name),
227
                ucfirst($component_name));
228 2
            if (class_exists($component)) {
229 1
                $this->components[$component_name] = new $component();
230
            } else {
231 1
                throw new BadComponentCallException($component_name);
232
            }
233
        }
234
235 1
        return $this->components[$component_name] ?? null;
236
    }
237
238
    /**
239
     * Add scripts like components and shaders
240
     *
241
     * @param string $path
242
     * @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
     * @param string $method
257
     * @param array $args
258
     * @throws BadShaderCallException
259
     * @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
     */
261 79
    public function __call(string $method, array $args)
262
    {
263 79
        $id        = $args[0] ?? 0;
264 79
        $primitive = sprintf('\AframeVR\Extras\Primitives\%s', ucfirst($method));
265
266 79
        if ($method === 'entity' || class_exists($primitive)) {
267 77
            return $this->child()->getEntity($method, $id);
268
        } else {
269 2
            return $this->attr($method);
270
        }
271
    }
272
273
    /**
274
     * Add everyting to DOM
275
     *
276
     * @return void
277
     */
278 19
    protected function prepare()
279
    {
280 19
        if ($this->prepared)
281 1
            return;
282
283
        /* Append all assets */
284 19
        $this->prepareAssets();
285
286
        /* Append all primitives */
287 19
        $this->preparePrimitives();
288
289
        /* Append all entities */
290 19
        $this->aframeDomObj->appendEntities($this->childrenFactory->getChildren());
291 19
        $this->aframeDomObj->appendSceneComponents($this->components);
292
293
        /* Append extra scripts */
294 19
        $this->prepareScripts();
295
296 19
        $this->prepared = true;
297 19
    }
298
299
    /**
300
     * Append all assets
301
     *
302
     * @return void
303
     */
304 19
    protected function prepareAssets()
305
    {
306 19
        $assets = $this->assets->getAssets();
307 19
        (!$assets) ?: $this->aframeDomObj->appendAssets($assets);
308 19
    }
309
310
    /**
311
     * Append extra scripts
312
     *
313
     * like extra components and shaders used in scene
314
     *
315
     * @return void
316
     */
317 19
    protected function prepareScripts()
318
    {
319 19
        (empty($this->scripts)) ?: $this->aframeDomObj->registerScripts($this->scripts);
320 19
    }
321
}
322