Completed
Pull Request — master (#65)
by Marko
02:39
created

Scene::__call()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 2
nop 2
crap 3
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 \Closure;
31
use \AframeVR\Core\Exceptions\BadComponentCallException;
32
use \AframeVR\Core\Helpers\EntityChildrenFactory;
33
34
final class Scene
35
{
36
    /* All scenes can use primitives */
37
    use Primitives;
38
    
39
    /**
40
     * Name with what you can retrieve this scene while working with multiple scenes
41
     *
42
     * @var string $name
43
     */
44
    private $keyword;
45
    
46
    /**
47
     * Is scene prepared for rendering
48
     *
49
     * @var bool
50
     */
51
    private $prepared;
52
    
53
    /**
54
     * Assets
55
     *
56
     * @var \AframeVR\Core\Assets
57
     */
58
    protected $assets;
59
    
60
    /**
61
     * Aframe Document Object Model
62
     *
63
     * @var \AframeVR\Core\DOM\AframeDOMDocument
64
     */
65
    protected $aframeDomObj;
66
    
67
    /**
68
     * Scene components
69
     *
70
     * @var array $components
71
     */
72
    protected $components = array();
73
74
    /**
75
     * Children Factory
76
     *
77
     * @var \AframeVR\Core\Helpers\EntityChildrenFactory
78
     */
79
    protected $childrenFactory;
80
    
81
    /**
82
     * Scene constructor
83
     *
84
     * @param string $keyword            
85
     * @param Config $config            
86
     */
87 98
    public function __construct(string $keyword, Config $config)
88
    {
89 98
        $this->keyword         = $keyword;
90 98
        $this->aframeDomObj    = new AframeDOMDocument($config);
91 98
        $this->childrenFactory = new EntityChildrenFactory();
92
        /* Initialize assests manager */
93 98
        $this->asset($config);
94 98
    }
95
96
    /**
97
     * Aframe Document Object Model
98
     *
99
     * @api
100
     *
101
     * @return \AframeVR\Core\DOM\AframeDOMDocument
102
     */
103 2
    public function dom()
104
    {
105 2
        return $this->aframeDomObj;
106
    }
107
    
108
    /**
109
     * Assets
110
     *
111
     * @api
112
     *
113
     * @param null|Config $config
114
     * @return \AframeVR\Core\Assets
115
     */
116 98
    public function asset(Config $config = null): Assets
117
    {
118 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 116 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...
119
    }
120
121
    /**
122
     * Child entity / primitive
123
     *
124
     * @return \AframeVR\Core\Helpers\EntityChildrenFactory
125
     */
126 77
    public function child(): EntityChildrenFactory
127
    {
128 77
        return $this->childrenFactory;
129
    }
130
    
131
    /**
132
     * Render the A-Frame scene and return the HTML
133
     *
134
     * @api
135
     *
136
     * @param bool $only_scene            
137
     * @return string
138
     */
139 19
    public function save($only_scene = false, string $file = null): string
140
    {
141 19
        $this->prepare();
142 19
        $html = ! $only_scene ? $this->aframeDomObj->render() : $this->aframeDomObj->renderSceneOnly();
143 19
        if (! empty($file) && is_writable(dirname($file))) {
144 1
            file_put_contents($file, $html);
145
        }
146
        
147 19
        return $html;
148
    }
149
150
    /**
151
     * Render the A-Frame scene and passthru HTML
152
     *
153
     * @api
154
     *
155
     * @param bool $only_scene            
156
     * @return void
157
     */
158 1
    public function render($only_scene = false)
159
    {
160 1
        print $this->save($only_scene);
161 1
    }
162
163
    /**
164
     * Alias of AframeDOMDocument::setTitle(string)
165
     *
166
     * Set <title> tag
167
     * $this->dom()->setTitle(string);
168
     *
169
     * @api
170
     *
171
     * @param string $title            
172
     */
173 1
    public function title(string $title)
174
    {
175 1
        $this->dom()->setTitle($title);
176 1
    }
177
178
    /**
179
     * Alias of AframeDOMDocument::setDescription(string)
180
     *
181
     * Set <meta name="description"> tag
182
     * $this->dom()->setDescription(string);
183
     *
184
     * @api
185
     *
186
     * @param string $description            
187
     */
188 1
    public function description(string $description)
189
    {
190 1
        $this->dom()->setDescription($description);
191 1
    }
192
193
    /**
194
     * Get scenes keyword
195
     *
196
     * @return string
197
     */
198 1
    public function getKeyword()
199
    {
200 1
        return $this->keyword;
201
    }
202
203
    /**
204
     * Load component for this scene or set it's attr
205
     *
206
     * @param string $component_name
207
     * @param null|string $attr_data
208
     * @throws \AframeVR\Core\Exceptions\BadComponentCallException
209
     * @return object|null
210
     */
211 2
    public function attr(string $component_name, string $attr_data = null)
212
    {
213 2
        if(!is_null($attr_data)) {
214 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...
215 1
            return $this;
216
        }
217 2
        if (! array_key_exists($component_name, $this->components)) {
218 2
            $component = sprintf('\AframeVR\Core\Components\ascene\%s\%sComponent', ucfirst($component_name), 
219
                ucfirst($component_name));
220 2
            if (class_exists($component)) {
221 1
                $this->components[$component_name] = new $component();
222
            } else {
223 1
                throw new BadComponentCallException($component_name);
224
            }
225
        }
226
        
227 1
        return $this->components[$component_name] ?? null;
228
    }
229
230
    /**
231
     * Map calls to scene entities and components
232
     *
233
     * Since we might need to customize these to have
234
     * custom components loaded as $this->methosd aswell therefore
235
     * we have these placeholder magic methods here
236
     *
237
     * @param string $method            
238
     * @param array $args            
239
     * @throws BadShaderCallException
240
     * @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...
241
     */
242 79
    public function __call(string $method, array $args)
243
    {
244 79
        $id        = $args[0] ?? 0;
245 79
        $primitive = sprintf('\AframeVR\Extras\Primitives\%s', ucfirst($method));
246
        
247 79
        if ($method === 'entity' || class_exists($primitive)) {
248 77
            return $this->child()->getEntity($method, $id);
249
        } else {
250 2
            return $this->attr($method);
251
        }
252
    }
253
254
    /**
255
     * Add everyting to DOM
256
     *
257
     * @return void
258
     */
259 19
    protected function prepare()
260
    {
261 19
        if ($this->prepared)
262 1
            return;
263
            
264
            /* Append all assets */
265 19
        $assets = $this->assets->getAssets();
266 19
        (! $assets) ?: $this->aframeDomObj->appendAssets($assets);
267
        /* Append all primitives */
268 19
        $this->preparePrimitives();
269
        
270
        /* Append all entities */
271 19
        $this->aframeDomObj->appendEntities($this->childrenFactory->getChildren());
272 19
        $this->aframeDomObj->appendSceneComponents($this->components);
273 19
        $this->prepared = true;
274 19
    }
275
}
276