Issues (119)

src/LaravelH5p/LaravelH5p.php (21 issues)

1
<?php
2
3
/*
4
 *
5
 * @Project        djoudi/laravel-h5p
6
 * @Copyright      Djoudi
7
 * @Created        2017-02-21
8
 * @Filename       LaravelH5p.php
9
 * @Description
10
 *
11
 */
12
13
namespace Djoudi\LaravelH5p;
14
15
use Djoudi\LaravelH5p\Repositories\EditorAjaxRepository;
16
use Djoudi\LaravelH5p\Repositories\LaravelH5pRepository;
17
use Djoudi\LaravelH5p\Storages\EditorStorage;
18
use Djoudi\LaravelH5p\Storages\LaravelH5pStorage;
19
use H5PContentValidator;
20
use H5PCore;
21
//use H5PDevelopment;
22
//use H5PDefaultStorage;
23
//use H5PEditorEndpoints;
24
//use H5PEditorAjax;
25
//use H5PEditorAjaxInterface;
26
//use H5peditorFile;
27
//use H5peditorStorage;
28
use H5peditor;
29
use H5PExport;
30
use H5PStorage;
31
use H5PValidator;
32
use Illuminate\Support\Facades\Auth;
33
34
//H5P_Plugin
35
class LaravelH5p
36
{
37
    /**
38
     * Instance of H5P WordPress Framework Interface.
39
     *
40
     * @since 1.0.0
41
     *
42
     * @var \LaravelH5pFramwork
0 ignored issues
show
The type LaravelH5pFramwork was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
43
     */
44
    public static $core = null;
45
    public static $h5peditor = null;
46
    public static $interface = null;
47
    public static $validator = null;
48
    public static $storage = null;
49
    public static $contentvalidator = null;
50
    public static $export = null;
51
    public static $settings = null;
52
53
    public function __construct()
54
    {
55
        self::$interface = new LaravelH5pRepository();
56
        self::$core = new H5PCore(self::$interface, self::get_h5p_storage('', true), self::get_h5p_url(), config('laravel-h5p.language'), config('laravel-h5p.h5p_export'));
0 ignored issues
show
Documentation Bug introduced by
It seems like new H5PCore(self::interf...ravel-h5p.h5p_export')) of type H5PCore is incompatible with the declared type LaravelH5pFramwork of property $core.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
57
        self::$core->aggregateAssets = config('laravel-h5p.H5P_DISABLE_AGGREGATION');
0 ignored issues
show
Bug Best Practice introduced by
The property aggregateAssets does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
58
        self::$validator = new H5PValidator(self::$interface, self::$core);
59
        self::$storage = new H5PStorage(self::$interface, self::$core);
60
        self::$contentvalidator = new H5PContentValidator(self::$interface, self::$core);
61
        self::$export = new H5PExport(self::$interface, self::$core);
62
        self::$h5peditor = new H5peditor(self::$core, new EditorStorage(), new EditorAjaxRepository());
63
        // self::$h5peditor = new H5peditor(self::$core, new EditorStorage(), new EditorAjaxRepository());
64
    }
65
66
    /**
67
     * Parse version string into smaller components.
68
     *
69
     * @since 1.7.9
70
     *
71
     * @param string $version
72
     *
73
     * @return stdClass|bool False on failure to parse
0 ignored issues
show
The type Djoudi\LaravelH5p\stdClass was not found. Did you mean stdClass? If so, make sure to prefix the type with \.
Loading history...
74
     */
75
    public static function split_version($version)
76
    {
77
        $version_parts = explode('.', $version);
78
        if (count($version_parts) !== 3) {
79
            return false;
80
        }
81
82
        return (object) [
83
            'major' => (int) $version_parts[0],
84
            'minor' => (int) $version_parts[1],
85
            'patch' => (int) $version_parts[2],
86
        ];
87
    }
88
89
    public static function get_url($path = '')
90
    {
91
        return url('/assets/vendor'.$path);
92
    }
93
94
    public static function get_h5p_storage($path = '', $absolute = false)
95
    {
96
        if ($absolute) {
97
            return new LaravelH5pStorage(storage_path('h5p'.$path));
98
//            return storage_path('h5p' . $path);
99
        } else {
100
            return self::get_url('/h5p'.$path);
101
        }
102
    }
103
104
    public static function get_laravelh5p_url($path = '')
105
    {
106
        return self::get_url('/laravel-h5p'.$path);
107
    }
108
109
    public static function get_h5p_url($path = '')
110
    {
111
        return self::get_url('/h5p'.$path);
112
    }
113
114
    public static function get_h5pcore_url($path = '')
115
    {
116
        return self::get_h5p_url('/h5p-core'.$path);
117
    }
118
119
    public static function get_h5peditor_url($path = '')
120
    {
121
        return self::get_h5p_url('/h5p-editor'.$path);
122
    }
123
124
    public static function get_h5plibrary_url($path = '', $absolute = false)
125
    {
126
        $return = self::get_url('/h5p'.$path);
127
128
        if ($absolute) {
129
            return storage_path('h5p/'.realpath($return));
130
//            return storage('/h5p/libraries' . $path);
131
        } else {
132
            return $return;
133
        }
134
    }
135
136
    public static function get_service_url($path = '')
0 ignored issues
show
The parameter $path is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

136
    public static function get_service_url(/** @scrutinizer ignore-unused */ $path = '')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
137
    {
138
        return route('h5p.index', [], false);
139
    }
140
141
    public static function get_core($settings = [])
142
    {
143
        $settings = self::get_core_settings($settings);
0 ignored issues
show
The call to Djoudi\LaravelH5p\LaravelH5p::get_core_settings() has too many arguments starting with $settings. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

143
        /** @scrutinizer ignore-call */ 
144
        $settings = self::get_core_settings($settings);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
144
        $settings = self::get_core_files($settings);
145
146
        return $settings;
147
    }
148
149
    public static function get_editor($content = null)
150
    {
151
        $settings = self::get_editor_settings($content);
152
        $settings = self::get_editor_assets($settings, $content);
153
154
        return $settings;
155
    }
156
157
    /**
158
     * Include settings and assets for the given content.
159
     *
160
     * @since 1.0.0
161
     *
162
     * @param array $content
163
     * @param bool  $no_cache
164
     *
165
     * @return string Embed code
166
     */
167
    public function get_embed($content, $settings, $no_cache = false)
0 ignored issues
show
The parameter $no_cache is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

167
    public function get_embed($content, $settings, /** @scrutinizer ignore-unused */ $no_cache = false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
168
    {
169
        // Detemine embed type
170
        $embed = H5PCore::determineEmbedType($content['embedType'], $content['library']['embedTypes']);
171
        // Make sure content isn't added twice
172
        $cid = 'cid-'.$content['id'];
173
        if (!isset($settings['contents'][$cid])) {
174
            $settings['contents'][$cid] = self::get_content_settings($content);
0 ignored issues
show
$content of type array is incompatible with the type Djoudi\LaravelH5p\type expected by parameter $content of Djoudi\LaravelH5p\Larave...:get_content_settings(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

174
            $settings['contents'][$cid] = self::get_content_settings(/** @scrutinizer ignore-type */ $content);
Loading history...
175
            $core = self::$core;
176
            // Get assets for this content
177
            $preloaded_dependencies = $core->loadContentDependencies($content['id'], 'preloaded');
178
            $files = $core->getDependenciesFiles($preloaded_dependencies);
179
            self::alter_assets($files, $preloaded_dependencies, $embed);
180
            if ($embed === 'div') {
181
                foreach ($files['scripts'] as $script) {
182
                    $url = $script->path.$script->version;
183
                    if (!in_array($url, $settings['loadedJs'])) {
184
                        $settings['loadedJs'][] = self::get_h5plibrary_url($url);
185
                    }
186
                }
187
                foreach ($files['styles'] as $style) {
188
                    $url = $style->path.$style->version;
189
                    if (!in_array($url, $settings['loadedCss'])) {
190
                        $settings['loadedCss'][] = self::get_h5plibrary_url($url);
191
                    }
192
                }
193
            } elseif ($embed === 'iframe') {
194
                $settings['contents'][$cid]['scripts'] = $core->getAssetsUrls($files['scripts']);
195
                $settings['contents'][$cid]['styles'] = $core->getAssetsUrls($files['styles']);
196
            }
197
        }
198
199
        if ($embed === 'div') {
200
            return [
0 ignored issues
show
Bug Best Practice introduced by
The expression return array('settings' ...ent['id'] . '"></div>') returns the type array<string,mixed|string> which is incompatible with the documented return type string.
Loading history...
201
                'settings' => $settings,
202
                'embed'    => '<div class="h5p-content" data-content-id="'.$content['id'].'"></div>',
203
            ];
204
        } else {
205
            return [
0 ignored issues
show
Bug Best Practice introduced by
The expression return array('settings' ...="no"></iframe></div>') returns the type array<string,mixed|string> which is incompatible with the documented return type string.
Loading history...
206
                'settings' => $settings,
207
                'embed'    => '<div class="h5p-iframe-wrapper"><iframe id="h5p-iframe-'.$content['id'].'" class="h5p-iframe" data-content-id="'.$content['id'].'" style="height:1px" src="about:blank" frameBorder="0" scrolling="no"></iframe></div>',
208
            ];
209
        }
210
    }
211
212
    /**
213
     * The most basic settings.
214
     *
215
     * @param type $content
0 ignored issues
show
The type Djoudi\LaravelH5p\type was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
216
     *
217
     * @return type
218
     */
219
    private static function get_core_settings()
220
    {
221
        $settings = [
222
            'baseUrl'            => config('laravel-h5p.domain'),
223
            'url'                => self::get_h5p_storage(), // for uploaded
224
            'postUserStatistics' => (config('laravel-h5p.h5p_track_user', true) === '1') && Auth::check(),
225
            'ajax'               => [
226
                'setFinished'     => route('h5p.ajax.finish'),
227
                'contentUserData' => route('h5p.ajax.content-user-data'),
228
                // 'contentUserData' => route('h5p.ajax.content-user-data', ['content_id' => ':contentId', 'data_type' => ':dataType', 'sub_content_id' => ':subContentId']),
229
            ],
230
            'saveFreq' => config('laravel-h5p.h5p_save_content_state', false) ? config('laravel-h5p.h5p_save_content_frequency', 30) : false,
231
            'siteUrl'  => config('laravel-h5p.domain'),
232
            'l10n'     => [
233
                'H5P' => trans('laravel-h5p.h5p'),
234
            ],
235
            'hubIsEnabled' => config('laravel-h5p.h5p_hub_is_enabled'),
236
        ];
237
238
        if (Auth::check()) {
239
            $settings['user'] = [
240
                'name' => Auth::user()->name,
0 ignored issues
show
Accessing name on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
241
                'mail' => Auth::user()->email,
0 ignored issues
show
Accessing email on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
242
            ];
243
        }
244
245
        return $settings;
246
    }
247
248
    private static function get_core_files($settings = [])
249
    {
250
        $settings['loadedJs'] = [];
251
        $settings['loadedCss'] = [];
252
253
        $settings['core'] = [
254
            'styles'  => [],
255
            'scripts' => [],
256
        ];
257
258
        $settings['core']['styles'][] = self::get_laravelh5p_url('/css/laravel-h5p.css');
259
260
        foreach (H5PCore::$styles as $style) {
261
            $settings['core']['styles'][] = self::get_h5pcore_url('/'.$style);
262
        }
263
        foreach (H5PCore::$scripts as $script) {
264
            $settings['core']['scripts'][] = self::get_h5pcore_url('/'.$script);
265
        }
266
267
        $settings['core']['scripts'][] = self::get_h5peditor_url('/scripts/h5peditor-editor.js');
268
269
        $settings['core']['scripts'][] = self::get_laravelh5p_url('/js/laravel-h5p.js');
270
271
        return $settings;
272
    }
273
274
    private static function get_editor_settings($content = null)
275
    {
276
        $settings = self::get_core_settings();
277
278
        $settings['editor'] = [
279
            'filesPath' => self::get_h5p_storage('/editor'),
280
            'fileIcon'  => [
281
                'path'   => self::get_h5peditor_url('/images/binary-file.png'),
282
                'width'  => 50,
283
                'height' => 50,
284
            ],
285
            'ajaxPath' => route('h5p.ajax').'/',
286
            // for checkeditor,
287
            'libraryUrl'         => self::get_h5peditor_url(),
288
            'copyrightSemantics' => self::$contentvalidator->getCopyrightSemantics(),
289
            'metadataSemantics'  => self::$contentvalidator->getMetadataSemantics(),
290
            'assets'             => [],
291
            'deleteMessage'      => trans('laravel-h5p.content.destoryed'),
292
            'apiVersion'         => H5PCore::$coreApi,
293
        ];
294
295
        // contents
296
        if ($content !== null) {
297
            $settings['editor']['nodeVersionId'] = $content['id'];
298
        }
299
300
        return $settings;
301
    }
302
303
    private static function get_editor_assets($settings = [], $content = null)
304
    {
305
        $settings = self::get_core_files($settings);
306
307
        // load core assets
308
        $settings['editor']['assets']['css'] = $settings['core']['styles'];
309
        $settings['editor']['assets']['js'] = $settings['core']['scripts'];
310
311
        $settings['editor']['assets']['js'][] = self::get_laravelh5p_url('/js/laravel-h5p-editor.js');
312
313
        // add editor styles
314
        foreach (H5peditor::$styles as $style) {
315
            $settings['editor']['assets']['css'][] = self::get_h5peditor_url('/'.$style);
316
        }
317
        // Add editor JavaScript
318
        foreach (H5peditor::$scripts as $script) {
319
            // We do not want the creator of the iframe inside the iframe
320
            if ($script !== 'scripts/h5peditor-editor.js') {
321
                $settings['editor']['assets']['js'][] = self::get_h5peditor_url('/'.$script);
322
            }
323
        }
324
325
        $language_script = '/language/'.self::get_language().'.js';
326
        $settings['editor']['assets']['js'][] = self::get_h5peditor_url($language_script);
327
328
        if ($content) {
329
            $settings = self::get_content_files($settings, $content);
330
        }
331
332
        return $settings;
333
    }
334
335
    /**
336
     * @param type $content
337
     *
338
     * @return type
339
     */
340
    public static function get_content_settings($content)
341
    {
342
        $safe_parameters = self::$core->filterParameters($content);
343
//        if (has_action('h5p_alter_filtered_parameters')) {
344
        //            // Parse the JSON parameters
345
        //            $decoded_parameters = json_decode($safe_parameters);
346
        //            /**
347
        //             * Allows you to alter the H5P content parameters after they have been
348
        //             * filtered. This hook only fires before view.
349
        //             *
350
        //             * @since 1.5.3
351
        //             *
352
        //             * @param object &$parameters
353
        //             * @param string $libraryName
354
        //             * @param int $libraryMajorVersion
355
        //             * @param int $libraryMinorVersion
356
        //             */
357
        //            // Stringify the JSON parameters
358
        //            $safe_parameters = json_encode($decoded_parameters);
359
        //        }
360
        // Getting author's user id
361
        $author_id = (int) (is_array($content) ? $content['user_id'] : $content->user_id);
0 ignored issues
show
The condition is_array($content) is always false.
Loading history...
362
        // Add JavaScript settings for this content
363
        $settings = [
364
            'library'         => H5PCore::libraryToString($content['library']),
365
            'jsonContent'     => $safe_parameters,
366
            'fullScreen'      => $content['library']['fullscreen'],
367
            'exportUrl'       => config('laravel-h5p.h5p_export') ? route('h5p.export', [$content['id']]) : '',
368
            'embedCode'       => '<iframe src="'.route('h5p.embed', ['id' => $content['id']]).'" width=":w" height=":h" frameborder="0" allowfullscreen="allowfullscreen"></iframe>',
369
            'resizeCode'      => '<script src="'.self::get_h5pcore_url('/js/h5p-resizer.js').'" charset="UTF-8"></script>',
370
            'url'             => route('h5p.embed', ['id' => $content['id']]),
371
            'title'           => $content['title'],
372
            'displayOptions'  => self::$core->getDisplayOptionsForView($content['disable'], $author_id),
373
            'contentUserData' => [
374
                0 => [
375
                    'state' => '{}',
376
                ],
377
            ],
378
        ];
379
380
        // Get preloaded user data for the current user
381
        if (config('laravel-h5p.h5p_save_content_state') && Auth::check()) {
382
            $results = DB::select('
0 ignored issues
show
The type Djoudi\LaravelH5p\DB was not found. Did you mean DB? If so, make sure to prefix the type with \.
Loading history...
383
                SELECT
384
                hcud.sub_content_id,
385
                hcud.data_id,
386
                hcud.data
387
                FROM h5p_contents_user_data hcud
388
                WHERE user_id = ?
389
                AND content_id = ?
390
                AND preload = 1', [Auth::user()->id, $content['id']]
0 ignored issues
show
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
391
            );
392
393
            if ($results) {
394
                foreach ($results as $result) {
395
                    $settings['contentUserData'][$result->sub_content_id][$result->data_id] = $result->data;
396
                }
397
            }
398
        }
399
400
        return $settings;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $settings returns the type array<string,array<integ...,string>>|mixed|string> which is incompatible with the documented return type Djoudi\LaravelH5p\type.
Loading history...
401
    }
402
403
    /**
404
     * @param type $settings
405
     * @param type $content
406
     *
407
     * @return type
408
     */
409
    public static function get_content_files($settings, $content)
410
    {
411
        $embed = H5PCore::determineEmbedType($content['embedType'], $content['library']['embedTypes']);
412
413
        // Make sure content isn't added twice
414
        $cid = 'cid-'.$content['id'];
415
        if (!isset($settings['contents'][$cid])) {
416
417
            // Load File
418
            $settings['contents'][$cid] = self::get_content_settings($content);
419
420
            $core = self::$core;
421
422
            // Get assets for this content
423
            $preloaded_dependencies = $core->loadContentDependencies($content['id'], 'preloaded');
424
425
            $files = $core->getDependenciesFiles($preloaded_dependencies);
426
427
            self::alter_assets($files, $preloaded_dependencies, $embed);
428
429
            if ($embed === 'div') {
430
//                $this->enqueue_assets($files);
431
                foreach ($files['scripts'] as $script) {
432
                    $url = $script->path.$script->version;
433
                    if (!in_array($url, $settings['loadedJs'])) {
434
                        $settings['loadedJs'][] = self::get_h5plibrary_url($url);
435
                    }
436
                }
437
                foreach ($files['styles'] as $style) {
438
                    $url = $style->path.$style->version;
439
                    if (!in_array($url, $settings['loadedCss'])) {
440
                        $settings['loadedCss'][] = self::get_h5plibrary_url($url);
441
                    }
442
                }
443
            } elseif ($embed === 'iframe') {
444
                $settings['contents'][$cid]['scripts'] = $core->getAssetsUrls($files['scripts']);
445
                $settings['contents'][$cid]['styles'] = $core->getAssetsUrls($files['styles']);
446
            }
447
        }
448
449
        return $settings;
450
    }
451
452
    public static function alter_assets(&$files, &$dependencies, $embed)
0 ignored issues
show
The parameter $embed is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

452
    public static function alter_assets(&$files, &$dependencies, /** @scrutinizer ignore-unused */ $embed)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $files is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

452
    public static function alter_assets(/** @scrutinizer ignore-unused */ &$files, &$dependencies, $embed)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
453
    {
454
        $libraries = [];
455
        foreach ($dependencies as $dependency) {
456
            $libraries[$dependency['machineName']] = [
457
                'majorVersion' => $dependency['majorVersion'],
458
                'minorVersion' => $dependency['minorVersion'],
459
            ];
460
        }
461
462
        return $libraries;
463
    }
464
465
    /**
466
     * Get content with given id.
467
     *
468
     * @since 1.0.0
469
     *
470
     * @param int $id
471
     *
472
     * @throws Exception
473
     *
474
     * @return array
475
     */
476
    public static function get_content($id = null)
477
    {
478
        if ($id === false || $id === null) {
0 ignored issues
show
The condition $id === null is always false.
Loading history...
479
            return trans('h5p.content.missing_h5p_identifier');
480
        }
481
482
        // Try to find content with $id.
483
        $content = self::$core->loadContent($id);
484
485
        if (!$content) {
486
            return trans('h5p.content.can_not_find_content', ['id' => $id]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return trans('h5p.conten...t', array('id' => $id)) also could return the type string which is incompatible with the documented return type array.
Loading history...
487
        }
488
        $content['language'] = self::get_language();
489
490
        return $content;
491
    }
492
493
    public static function get_language()
494
    {
495
        return config('laravel-h5p.language');
496
    }
497
}
498