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

AframeDOMDocument::appendScript()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 6
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
crap 2
1
<?php
2
/** @formatter:off
3
 * ******************************************************************
4
 * Created by   Marko Kungla on Jun 27, 2016 - 9:55:09 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         AframeDOMDocument.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\DOM;
25
26
use \AframeVR\Core\Config;
27
use \DOMImplementation;
28
use \DOMDocumentType;
29
use \DOMDocument;
30
use \AframeVR\Core\Entity;
31
use \AframeVR\Interfaces\AssetsInterface;
32
33
final class AframeDOMDocument extends DOMImplementation
34
{
35
    use AframeDOMProcessor;
36
37
    /**
38
     * A-Frame DOM Document type
39
     *
40
     * @var \DOMDocumentType
41
     */
42
    protected $doctypeObj;
43
44
    /**
45
     * A-Frame DOM Document
46
     *
47
     * @var \DOMDocument
48
     */
49
    protected $docObj;
50
51
    /**
52
     * Scene meta tile
53
     *
54
     * @var string $scene_title
55
     */
56
    protected $scene_title = 'Untitled';
57
58
    /**
59
     * Scene meta description
60
     *
61
     * @var string $scene_description
62
     */
63
    protected $scene_description = '';
64
65
    /**
66
     * <head>
67
     *
68
     * @var \DOMElement
69
     */
70
    protected $head;
71
72
    /**
73
     * <body>
74
     *
75
     * @var \DOMElement
76
     */
77
    protected $body;
78
79
    /**
80
     * <a-scene>
81
     *
82
     * @var \DOMElement
83
     */
84
    protected $scene;
85
86
    /**
87
     * <a-assets>
88
     *
89
     * @var \DOMElement
90
     */
91
    protected $assets;
92
93
    /************
94
     * CONFIG
95
     ***********/
96
97
    /**
98
     * Nicely formats output with indentation and extra space.
99
     *
100
     * @var bool
101
     */
102
    protected $format_output = false;
103
104
    /**
105
     * CDN Of aframe.js
106
     *
107
     * @var string
108
     */
109
    protected $cdn_url;
110
111
    /**
112
     * Whether to use CDN
113
     *
114
     * @var bool $use_cdn
115
     */
116
    protected $use_cdn = false;
117
118
    /**
119
     * aframe assets URI relative to App's base URL / domain
120
     *
121
     * @var string assets_uri
122
     */
123
    protected $assets_uri;
124
125
    /**
126
     * Extra scrits to add into head
127
     *
128
     * Like components and shaders
129
     *
130
     * @var array $scripts
131
     */
132
    protected $scripts = array();
133
134
    /**
135
     * A-Frame DOM
136
     *
137
     * @param Config $config
138
     */
139 98
    public function __construct(Config $config)
140
    {
141
        /* Config */
142 98
        $this->configOptions($config);
143
144
        /* Create HTML5 Document type */
145 98
        $this->createDocType('html');
146
147
        /* Create A-Frame DOM Document */
148 98
        $this->createAframeDocument();
149
150
        /* Create boostrap elements */
151 98
        $this->documentBootstrap();
152 98
    }
153
154
    /**
155
     * Render scene this DOM Object is attached to
156
     *
157
     * @return string
158
     */
159 8
    public function render(): string
160
    {
161 8
        $html = $this->docObj->getElementsByTagName('html')->item(0);
162
        /* Make sure we do not add duplicates when render is called multiple times */
163 8
        if (! $html->hasChildNodes()) {
164 8
            $this->renderHead();
165
166 8
            $html->appendChild($this->head);
167
168 8
            $this->renderBody();
169
170 8
            $html->appendChild($this->body);
171
        }
172 8
        return $this->format_output ? $this->correctOutputFormat($this->docObj->saveHTML()) : $this->docObj->saveHTML();
173
    }
174
175
    /**
176
     * Set Scene meta title
177
     *
178
     * @param string $title
179
     */
180 1
    public function setTitle(string $title)
181
    {
182 1
        $this->scene_title = $title;
183 1
    }
184
185
    /**
186
     * Set Scene meta description
187
     *
188
     * @param string $description
189
     */
190 1
    public function setDescription(string $description)
191
    {
192 1
        $this->scene_description = $description;
193 1
    }
194
195
    /**
196
     * Append entities
197
     *
198
     * @param array $entities
199
     * @return void
200
     */
201 19
    public function appendEntities(array $entities)
202
    {
203 19
        if (! empty($entities)) {
204 11
            foreach ($entities as $entity) {
205 11
                $this->appendEntity($entity);
206
            }
207
        }
208 19
    }
209
210
    /**
211
     * Append assets
212
     *
213
     * @param array $assets
214
     * @return void
215
     */
216 2
    public function appendAssets(array $assets)
217
    {
218 2
        if (! empty($assets)) {
219 2
            if ($this->format_output) {
220 2
                $com = $this->docObj->createComment('');
221 2
                $this->scene->appendChild($com);
222
            }
223 2
            foreach ($assets as $asset) {
224 2
                $this->appendAsset($asset);
225
            }
226 2
            $this->scene->appendChild($this->assets);
227
        }
228 2
    }
229
230
    /**
231
     * Register scripts to be added to DOM
232
     *
233
     * @param array $scripts
234
     * @return void
235
     */
236
    public function registerScripts(array $scripts)
237
    {
238
        $this->scripts = array_merge($this->scripts, $scripts);
239
    }
240
    /**
241
     * Append scripts
242
     *
243
     * @param array $scripts
244
     * @return void
245
     */
246 8
    public function appendScripts(array $scripts)
247
    {
248 8
        foreach($scripts as $url => $use) {
249
            (!$use)?:$this->appendScript($url);
250
        }
251 8
    }
252
253
    /**
254
     * Append script
255
     *
256
     * @param string $script_uri
257
     * @return void
258
     */
259
    public function appendScript(string $script_uri)
260
    {
261
        $extra_script_url = sprintf('%s%s',$this->assets_uri, $script_uri);
262
        $extra_script     = $this->docObj->createElement('script');
263
        $extra_script->setAttribute('src', $extra_script_url);
264
        $this->head->appendChild($extra_script);
265
    }
266
    /**
267
     * Append asset
268
     *
269
     * Create asset DOMElement
270
     *
271
     * @param AssetsInterface $asset
272
     */
273 2
    public function appendAsset(AssetsInterface $asset)
274
    {
275 2
        $this->appendFormatComment('assets', "\n\t");
276 2
        $this->assets->appendChild($asset->domElement($this->docObj));
277 2
    }
278
279
    /**
280
     * Create entity DOMElement
281
     *
282
     * Created entity and append it to scene
283
     *
284
     * @param Entity $entity
285
     * @return void
286
     */
287 13
    public function appendEntity(Entity $entity)
288
    {
289 13
        $this->appendFormatComment('scene', "\n");
290 13
        $this->scene->appendChild($entity->domElement($this->docObj));
291 13
    }
292
293
    /**
294
     * Get HTML of Scene only
295
     *
296
     * @return string
297
     */
298 12
    public function renderSceneOnly()
299
    {
300 12
        $html               = new DOMDocument();
301 12
        $html->formatOutput = $this->format_output;
302
303 12
        $html_scene = $html->importNode($this->scene, true);
304 12
        $html->appendChild($html_scene);
305 12
        return $this->format_output ? $this->correctOutputFormat($html->saveHTML()) : $html->saveHTML();
306
    }
307
308
    /**
309
     * Add scene components
310
     *
311
     * @param array $components
312
     * @return void
313
     */
314 19
    public function appendSceneComponents(array $components)
315
    {
316 19
        foreach ($components as $component) {
317
            /*
318
             * Check does component has any attributes to add to scene DOM element.
319
             * default attributes most of cases are ommited so we might not have any attributes to add
320
             */
321 1
            if ($component->hasDOMAttributes())
322 1
                $this->scene->setAttributeNode($component->getDOMAttr());
323
        }
324 19
    }
325
326
    /**
327
     * Set configuration option related to DOM
328
     *
329
     * @param Config $config
330
     * @return void
331
     */
332 98
    protected function configOptions(Config $config)
333
    {
334 98
        $this->setConfigurationOption($config, 'format_output', false);
335 98
        $this->setConfigurationOption($config, 'cdn_url', null);
336 98
        $this->setConfigurationOption($config, 'use_cdn', false);
337 98
        $this->setConfigurationOption($config, 'assets_uri', '/aframe');
338 98
    }
339
340
    /**
341
     * Set individual option
342
     *
343
     * @param Config $config
344
     * @param string $opt
345
     * @param mixed $default
346
     * @return void
347
     */
348 98
    protected function setConfigurationOption(Config $config, string $opt, $default)
349
    {
350 98
        $this->{$opt} = $config->get($opt) ?? $default;
351 98
    }
352
}
353