LaravelH5pRepository   F
last analyzed

Complexity

Total Complexity 136

Size/Duplication

Total Lines 1006
Duplicated Lines 0 %

Importance

Changes 6
Bugs 2 Features 0
Metric Value
eloc 352
c 6
b 2
f 0
dl 0
loc 1006
rs 2
wmc 136

59 Methods

Rating   Name   Duplication   Size   Complexity  
A loadContentDependencies() 0 29 3
A updateContent() 0 35 5
A currentUserCanEdit() 0 7 2
A loadLibraries() 0 21 2
B replaceContentTypeCache() 0 50 7
A getLibraryFileUrl() 0 3 1
A getUploadedH5pPath() 0 9 2
A getNumAuthors() 0 3 1
A mayUpdateLibraries() 0 3 1
A insertContent() 0 3 1
A loadContent() 0 22 1
A setInfoMessage() 0 4 2
A t() 0 16 4
A resetContentUserData() 0 10 1
A getLibraryStats() 0 10 2
A setLibraryTutorialUrl() 0 3 1
A saveLibraryUsage() 0 16 5
A lockDependencyStorage() 0 2 1
A libraryHasUpgrade() 0 2 1
A getH5pPath() 0 3 1
A deleteLibraryUsage() 0 3 1
A pathsToCsv() 0 12 3
A afterExportCreated() 0 3 1
A getMessages() 0 3 2
A getLibraryConfig() 0 2 1
A alterLibrarySemantics() 0 2 1
A isPatchedLibrary() 0 15 4
A hasPermission() 0 17 6
A setErrorMessage() 0 4 2
A updateContentFields() 0 7 2
A getWhitelist() 0 9 2
A unlockDependencyStorage() 0 2 1
A clearFilteredParameters() 0 3 1
A getOption() 0 7 2
A getLibraryUsage() 0 12 2
A copyLibraryUsage() 0 9 1
A getPlatformInfo() 0 8 1
A getAdminUrl() 0 3 1
A getLibraryId() 0 17 4
A loadLibrary() 0 31 4
B fetchExternalData() 0 36 8
A getUploadedH5pFolderPath() 0 9 2
A setOption() 0 6 2
A saveLibraryDependencies() 0 9 2
A loadLibrarySemantics() 0 13 3
A deleteCachedAssets() 0 13 2
A isContentSlugAvailable() 0 3 1
A camelToString() 0 5 1
F saveLibraryData() 0 77 14
A getSemanticsFromFile() 0 13 3
A isInDevMode() 0 3 1
A deleteLibraryDependencies() 0 3 1
A deleteContentData() 0 6 1
A saveCachedAssets() 0 8 3
A deleteLibrary() 0 11 1
A getLibraryContentCount() 0 13 2
A getNumNotFiltered() 0 3 1
A getNumContent() 0 3 1
A loadAddons() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like LaravelH5pRepository often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use LaravelH5pRepository, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 *
5
 * @Project        Laravel framework integration class
6
 * @Copyright      Djoudi
7
 * @Created        2018-2-20
8
 * @Filename       H5PLaravel.php
9
 * @Description
10
 *
11
 */
12
13
namespace Djoudi\LaravelH5p\Repositories;
14
15
use Carbon\Carbon;
16
use DB;
17
use Djoudi\LaravelH5p\Eloquents\H5pContent;
18
use Djoudi\LaravelH5p\Eloquents\H5pContentsLibrary;
19
use Djoudi\LaravelH5p\Eloquents\H5pContentsUserData;
20
use Djoudi\LaravelH5p\Eloquents\H5pLibrariesLibrary;
21
use Djoudi\LaravelH5p\Eloquents\H5pLibrary;
22
use Djoudi\LaravelH5p\Eloquents\H5pResult;
23
use Djoudi\LaravelH5p\Events\H5pEvent;
24
use Djoudi\LaravelH5p\Helpers\H5pHelper;
25
use GuzzleHttp\Client;
26
use H5PFrameworkInterface;
27
use Illuminate\Support\Facades\App;
28
29
class LaravelH5pRepository implements H5PFrameworkInterface
30
{
31
    public $_download_file = '';
32
33
    /**
34
     * Kesps track of messages for the user.
35
     *
36
     * @since 1.0.0
37
     *
38
     * @var array
39
     */
40
    protected $messages = ['error' => [], 'updated' => []];
41
42
    public function loadAddons()
43
    {
44
    }
45
46
    public function getLibraryConfig($libraries = null)
47
    {
48
    }
49
50
    public function libraryHasUpgrade($library)
51
    {
52
    }
53
54
    /**
55
     * Implements setErrorMessage.
56
     */
57
    public function setErrorMessage($message, $code = null)
58
    {
59
        if (H5pHelper::current_user_can('edit_h5p_contents')) {
60
            $this->messages['error'][] = $message;
61
        }
62
    }
63
64
    /**
65
     * Implements setInfoMessage.
66
     */
67
    public function setInfoMessage($message)
68
    {
69
        if (H5pHelper::current_user_can('edit_h5p_contents')) {
70
            $this->messages['updated'][] = $message;
71
        }
72
    }
73
74
    /**
75
     * Return the selected messages.
76
     *
77
     * @since 1.0.0
78
     *
79
     * @param string $type
80
     *
81
     * @return array
82
     */
83
    public function getMessages($type)
84
    {
85
        return isset($this->messages[$type]) ? $this->messages[$type] : null;
86
    }
87
88
    /**
89
     * Implements t.
90
     */
91
    public function t($message, $replacements = [])
92
    {
93
        // Insert !var as is, escape @var and emphasis %var.
94
        foreach ($replacements as $key => $replacement) {
95
            if ($key[0] === '@') {
96
//                $replacements[$key] = esc_html($replacement);
97
                $replacements[$key] = $replacement;
98
            } elseif ($key[0] === '%') {
99
//                $replacements[$key] = '<em>' . esc_html($replacement) . '</em>';
100
                $replacements[$key] = '<em>'.$replacement.'</em>';
101
            }
102
        }
103
        $message = preg_replace('/(!|@|%)[a-z0-9]+/i', '%s', $message);
104
105
        // Assumes that replacement vars are in the correct order.
106
        return vsprintf(trans($message), $replacements);
0 ignored issues
show
Bug introduced by
trans($message) of type Illuminate\Translation\Translator is incompatible with the type string expected by parameter $format of vsprintf(). ( Ignorable by Annotation )

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

106
        return vsprintf(/** @scrutinizer ignore-type */ trans($message), $replacements);
Loading history...
107
    }
108
109
    /**
110
     * Helper.
111
     */
112
    private function getH5pPath()
113
    {
114
        return url('vendor/h5p/h5p-core/');
115
    }
116
117
    /**
118
     * Get the URL to a library file.
119
     */
120
    public function getLibraryFileUrl($libraryFolderName, $fileName)
121
    {
122
        return url('vendor/h5p/h5p-core/'.$libraryFolderName.'/'.$fileName);
123
    }
124
125
    /**
126
     * Implements getUploadedH5PFolderPath.
127
     */
128
    public function getUploadedH5pFolderPath()
129
    {
130
        static $dir;
131
        if (is_null($dir)) {
132
            $plugin = App::make('LaravelH5p');
133
            $dir = $plugin::$core->fs->getTmpPath();
134
        }
135
136
        return $dir;
137
    }
138
139
    /**
140
     * Implements getUploadedH5PPath.
141
     */
142
    public function getUploadedH5pPath()
143
    {
144
        static $path;
145
        if (is_null($path)) {
146
            $plugin = App::make('LaravelH5p');
147
            $path = $plugin::$core->fs->getTmpPath().'.h5p';
148
        }
149
150
        return $path;
151
    }
152
153
    /**
154
     * Implements getLibraryId.
155
     */
156
    public function getLibraryId($name, $majorVersion = null, $minorVersion = null)
157
    {
158
        $where = H5pLibrary::select()->where('name', $name);
159
160
        if ($majorVersion !== null) {
161
            $where->where('major_version', $majorVersion);
162
            if ($minorVersion !== null) {
163
                $where->where('minor_version', $minorVersion);
164
            }
165
        }
166
167
        $return = $where->orderBy('major_version', 'DESC')
168
            ->orderBy('minor_version', 'DESC')
169
            ->orderBy('patch_version', 'DESC')
170
            ->first();
171
172
        return $return === null ? false : $return->id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $return === null ? false : $return->id also could return the type false which is incompatible with the return type mandated by H5PFrameworkInterface::getLibraryId() of integer.
Loading history...
173
    }
174
175
    /**
176
     * Implements isPatchedLibrary.
177
     */
178
    public function isPatchedLibrary($library)
179
    {
180
        if (defined('H5P_DEV') && H5P_DEV) {
0 ignored issues
show
Bug introduced by
The constant Djoudi\LaravelH5p\Repositories\H5P_DEV was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
181
            return true;
182
        }
183
        $operator = $this->isInDevMode() ? '<=' : '<';
184
185
        $return = DB::table('h5p_libraries')
186
            ->where('name', $library['machineName'])
187
            ->where('major_version', $library['majorVersion'])
188
            ->where('minor_version', $library['minorVersion'])
189
            ->where('patch_version', $operator, $library['patchVersion'])
190
            ->first();
191
192
        return $return !== null;
193
    }
194
195
    /**
196
     * Implements isInDevMode.
197
     */
198
    public function isInDevMode()
199
    {
200
        return config('laravel-h5p.H5P_DEV');
201
    }
202
203
    /**
204
     * Implements mayUpdateLibraries.
205
     */
206
    public function mayUpdateLibraries()
207
    {
208
        return H5pHelper::current_user_can('manage_h5p_libraries');
209
    }
210
211
    /**
212
     * Implements getLibraryUsage.
213
     */
214
    public function getLibraryUsage($id, $skipContent = false)
215
    {
216
        if ($skipContent) {
217
            $cotent = -1;
0 ignored issues
show
Unused Code introduced by
The assignment to $cotent is dead and can be removed.
Loading history...
218
        } else {
219
            $result = DB::select('SELECT COUNT(distinct c.id) AS cnt FROM h5p_libraries l JOIN h5p_contents_libraries cl ON l.id = cl.library_id JOIN h5p_contents c ON cl.content_id = c.id WHERE l.id = ?', [$id]);
220
            $content = intval($result[0]->cnt);
221
        }
222
223
        return [
224
            'content'   => $content,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $content does not seem to be defined for all execution paths leading up to this point.
Loading history...
225
            'libraries' => intval(H5pLibrariesLibrary::where('required_library_id', $id)->count()),
226
        ];
227
    }
228
229
    /**
230
     * Implements saveLibraryData.
231
     */
232
    public function saveLibraryData(&$library, $new = true)
233
    {
234
        $preloadedJs = $this->pathsToCsv($library, 'preloadedJs');
235
        $preloadedCss = $this->pathsToCsv($library, 'preloadedCss');
236
        $dropLibraryCss = '';
237
        if (isset($library['dropLibraryCss'])) {
238
            $libs = [];
239
            foreach ($library['dropLibraryCss'] as $lib) {
240
                $libs[] = $lib['machineName'];
241
            }
242
            $dropLibraryCss = implode(', ', $libs);
243
        }
244
        $embedTypes = '';
245
        if (isset($library['embedTypes'])) {
246
            $embedTypes = implode(', ', $library['embedTypes']);
247
        }
248
        if (!isset($library['semantics'])) {
249
            $library['semantics'] = '';
250
        }
251
        if (!isset($library['fullscreen'])) {
252
            $library['fullscreen'] = 0;
253
        }
254
        if (!isset($library['tutorial_url'])) {
255
            $library['tutorial_url'] = '';
256
        }
257
        if (!isset($library['hasIcon'])) {
258
            $library['hasIcon'] = 0;
259
        }
260
261
        if ($new) {
262
            $library['libraryId'] = DB::table('h5p_libraries')->insertGetId([
263
                'name'             => $library['machineName'],
264
                'title'            => $library['title'],
265
                'major_version'    => $library['majorVersion'],
266
                'minor_version'    => $library['minorVersion'],
267
                'patch_version'    => $library['patchVersion'],
268
                'runnable'         => $library['runnable'],
269
                'fullscreen'       => $library['fullscreen'],
270
                'embed_types'      => $embedTypes,
271
                'preloaded_js'     => $preloadedJs,
272
                'preloaded_css'    => $preloadedCss,
273
                'drop_library_css' => $dropLibraryCss,
274
                'semantics'        => $library['semantics'],
275
                'tutorial_url'     => $library['tutorial_url'],
276
                'has_icon'         => $library['hasIcon'] ? 1 : 0,
277
            ]);
278
        } else {
279
            $library['libraryId'] = DB::table('h5p_libraries')
280
                ->where('id', $library['libraryId'])->update([
281
                    'title'            => $library['title'],
282
                    'patch_version'    => $library['patchVersion'],
283
                    'runnable'         => $library['runnable'],
284
                    'fullscreen'       => $library['fullscreen'],
285
                    'embed_types'      => $embedTypes,
286
                    'preloaded_js'     => $preloadedJs,
287
                    'preloaded_css'    => $preloadedCss,
288
                    'drop_library_css' => $dropLibraryCss,
289
                    'semantics'        => $library['semantics'],
290
                    'has_icon'         => $library['hasIcon'] ? 1 : 0,
291
                ]);
292
            $this->deleteLibraryDependencies($library['libraryId']);
293
        }
294
295
        // Log library successfully installed/upgraded
296
        event(new H5pEvent('library', ($new ? 'create' : 'update'), null, null, $library['machineName'], $library['majorVersion'].'.'.$library['minorVersion']));
297
298
        // Update languages
299
        DB::table('h5p_libraries_languages')
300
            ->where('library_id', $library['libraryId'])
301
            ->delete();
302
303
        if (isset($library['language'])) {
304
            foreach ($library['language'] as $languageCode => $translation) {
305
                DB::table('h5p_libraries_languages')->insert([
306
                    'library_id'    => $library['libraryId'],
307
                    'language_code' => $languageCode,
308
                    'translation'   => $translation,
309
                ]
310
                );
311
            }
312
        }
313
    }
314
315
    /**
316
     * Convert list of file paths to csv.
317
     *
318
     * @param array  $library
319
     *                        Library data as found in library.json files
320
     * @param string $key
321
     *                        Key that should be found in $libraryData
322
     *
323
     * @return string
324
     *                file paths separated by ', '
325
     */
326
    private function pathsToCsv($library, $key)
327
    {
328
        if (isset($library[$key])) {
329
            $paths = [];
330
            foreach ($library[$key] as $file) {
331
                $paths[] = $file['path'];
332
            }
333
334
            return implode(', ', $paths);
335
        }
336
337
        return '';
338
    }
339
340
    /**
341
     * Implements deleteLibraryDependencies.
342
     */
343
    public function deleteLibraryDependencies($id)
344
    {
345
        DB::table('h5p_libraries_libraries')->where('library_id', $id)->delete();
346
    }
347
348
    /**
349
     * Implements deleteLibrary.
350
     */
351
    public function deleteLibrary($library)
352
    {
353
        $plugin = App::make('LaravelH5p');
354
355
        // Delete library files
356
        $plugin::$core->deleteFileTree($this->getH5pPath().'/libraries/'.$library->name.'-'.$library->major_version.'.'.$library->minor_version);
357
358
        // Remove library data from database
359
        DB::table('h5p_libraries_libraries')->where('library_id', $library->id)->delete();
360
        DB::table('h5p_libraries_languages')->where('library_id', $library->id)->delete();
361
        DB::table('h5p_libraries')->where('id', $library->id)->delete();
362
    }
363
364
    /**
365
     * Implements saveLibraryDependencies.
366
     */
367
    public function saveLibraryDependencies($id, $dependencies, $dependencyType)
368
    {
369
        foreach ($dependencies as $dependency) {
370
            DB::insert('INSERT INTO h5p_libraries_libraries (library_id, required_library_id, dependency_type)
371
            SELECT ?, hl.id, ? FROM h5p_libraries hl WHERE
372
            name = ?
373
            AND major_version = ?
374
            AND minor_version = ?
375
            ON DUPLICATE KEY UPDATE dependency_type = ?', [$id, $dependencyType, $dependency['machineName'], $dependency['majorVersion'], $dependency['minorVersion'], $dependencyType]);
376
        }
377
378
//        DB::table('h5p_libraries_libraries')->insert($datas);
379
    }
380
381
    /**
382
     * Implements updateContent.
383
     */
384
    public function updateContent($entry, $contentMainId = null)
385
    {
386
        $content = [];
387
        $content['title'] = $entry['title'];
388
        $content['embed_type'] = $entry['embed_type'];
389
        $content['user_id'] = $entry['user_id'];
390
        $content['filtered'] = $entry['filtered'];
391
        $content['disable'] = $entry['disable'];
392
        $content['slug'] = $entry['slug'];
393
        $content['library_id'] = $entry['library']['libraryId'];
394
        $content['parameters'] = $entry['params'];
395
396
        if (!isset($entry['id'])) {
397
            $content['created_at'] = isset($entry['created_at']) ? $entry['created_at'] : Carbon::now();
398
399
            // Insert new content
400
            $return = H5pContent::create($content);
401
            $content['id'] = $return->id;
402
            $event_type = 'create';
403
        } else {
404
            $content['id'] = $entry['id'];
405
            $content['updated_at'] = isset($entry['updated_at']) ? $entry['updated_at'] : Carbon::now();
406
407
            H5pContent::where('id', $content['id'])->update($content);
408
            $event_type = 'update';
409
        }
410
411
        // Log content create/update/upload
412
        if (!empty($content['uploaded'])) {
413
            $event_type .= ' upload';
414
        }
415
416
        event(new H5pEvent('content', $event_type, $content['id'], $content['title'], $entry['library']['machineName'], $entry['library']['majorVersion'].'.'.$entry['library']['minorVersion']));
417
418
        return $content['id'];
419
    }
420
421
    /**
422
     * Implements insertContent.
423
     */
424
    public function insertContent($content, $contentMainId = null)
425
    {
426
        return $this->updateContent($content);
427
    }
428
429
    /**
430
     * Implement getWhitelist.
431
     */
432
    public function getWhitelist($isLibrary, $defaultContentWhitelist, $defaultLibraryWhitelist)
433
    {
434
        // TODO: Get this value from a settings page.
435
        $whitelist = $defaultContentWhitelist;
436
        if ($isLibrary) {
437
            $whitelist .= ' '.$defaultLibraryWhitelist;
438
        }
439
440
        return $whitelist;
441
    }
442
443
    /**
444
     * Implements copyLibraryUsage.
445
     */
446
    public function copyLibraryUsage($contentId, $copyFromId, $contentMainId = null)
447
    {
448
        DB::insert('INSERT INTO h5p_contents_libraries (content_id, library_id, dependency_type, weight, drop_css)
449
        SELECT ?,
450
        hcl.library_id,
451
        hcl.dependency_type,
452
        hcl.weight,
453
        hcl.drop_css
454
        FROM h5p_contents_libraries hcl WHERE hcl.content_id = ?', [$contentId, $copyFromId]);
455
    }
456
457
    /**
458
     * Implements deleteContentData.
459
     */
460
    public function deleteContentData($id)
461
    {
462
        H5pContent::where('id', $id)->delete();
463
        $this->deleteLibraryUsage($id);
464
        H5pResult::where('content_id', $id)->delete();
465
        H5pContentsUserData::where('content_id', $id)->delete();
466
    }
467
468
    /**
469
     * Implements deleteLibraryUsage.
470
     */
471
    public function deleteLibraryUsage($contentId)
472
    {
473
        H5pContentsLibrary::where('content_id', $contentId)->delete();
474
    }
475
476
    /**
477
     * Implements saveLibraryUsage.
478
     */
479
    public function saveLibraryUsage($contentId, $librariesInUse)
480
    {
481
        $dropLibraryCssList = [];
482
        foreach ($librariesInUse as $dependency) {
483
            if (!empty($dependency['library']['dropLibraryCss'])) {
484
                $dropLibraryCssList = array_merge($dropLibraryCssList, explode(', ', $dependency['library']['dropLibraryCss']));
485
            }
486
        }
487
        foreach ($librariesInUse as $dependency) {
488
            $dropCss = in_array($dependency['library']['machineName'], $dropLibraryCssList) ? 1 : 0;
489
            DB::table('h5p_contents_libraries')->insert([
490
                'content_id'      => strval($contentId),
491
                'library_id'      => $dependency['library']['libraryId'],
492
                'dependency_type' => $dependency['type'],
493
                'drop_css'        => $dropCss,
494
                'weight'          => $dependency['weight'],
495
            ]);
496
        }
497
    }
498
499
    /**
500
     * Implements loadLibrary.
501
     */
502
    public function loadLibrary($name, $majorVersion, $minorVersion)
503
    {
504
        $library = DB::table('h5p_libraries')
505
            ->select(['id as libraryId', 'name as machineName', 'title', 'major_version as majorVersion', 'minor_version as minorVersion', 'patch_version as patchVersion', 'embed_types as embedTypes', 'preloaded_js as preloadedJs', 'preloaded_css as preloadedCss', 'drop_library_css as dropLibraryCss', 'fullscreen', 'runnable', 'semantics', 'has_icon as hasIcon'])
506
            ->where('name', $name)
507
            ->where('major_version', $majorVersion)
508
            ->where('minor_version', $minorVersion)
509
            ->first();
510
511
        $return = json_decode(json_encode($library), true);
512
513
        $dependencies = DB::select('SELECT hl.name as machineName, hl.major_version as majorVersion, hl.minor_version as minorVersion, hll.dependency_type as dependencyType
514
        FROM h5p_libraries_libraries hll
515
        JOIN h5p_libraries hl ON hll.required_library_id = hl.id
516
        WHERE hll.library_id = ?', [$library->libraryId]);
517
518
        foreach ($dependencies as $dependency) {
519
            $return[$dependency->dependencyType.'Dependencies'][] = [
520
                'machineName'  => $dependency->machineName,
521
                'majorVersion' => $dependency->majorVersion,
522
                'minorVersion' => $dependency->minorVersion,
523
            ];
524
        }
525
        if ($this->isInDevMode()) {
526
            $semantics = $this->getSemanticsFromFile($return['machineName'], $return['majorVersion'], $return['minorVersion']);
527
            if ($semantics) {
528
                $return['semantics'] = $semantics;
529
            }
530
        }
531
532
        return $return;
533
    }
534
535
    private function getSemanticsFromFile($name, $majorVersion, $minorVersion)
536
    {
537
        $semanticsPath = $this->getH5pPath().'/libraries/'.$name.'-'.$majorVersion.'.'.$minorVersion.'/semantics.json';
538
        if (file_exists($semanticsPath)) {
539
            $semantics = file_get_contents($semanticsPath);
540
            if (!json_decode($semantics, true)) {
541
                $this->setErrorMessage($this->t('Invalid json in semantics for %library', ['%library' => $name]));
542
            }
543
544
            return $semantics;
545
        }
546
547
        return false;
548
    }
549
550
    /**
551
     * Implements loadLibrarySemantics.
552
     */
553
    public function loadLibrarySemantics($name, $majorVersion, $minorVersion)
554
    {
555
        if ($this->isInDevMode()) {
556
            $semantics = $this->getSemanticsFromFile($name, $majorVersion, $minorVersion);
557
        } else {
558
            $semantics = H5pLibrary::where('name', $name)
559
                ->where('major_version', $majorVersion)
560
                ->where('minor_version', $minorVersion)
561
                ->first();
562
//                    DB::select("SELECT semantics FROM h5p_libraries WHERE name = ? AND major_version = ? AND minor_version = ?", [$name, $majorVersion, $minorVersion]);
563
        }
564
565
        return $semantics === false ? null : $semantics->semantics;
566
    }
567
568
    /**
569
     * Implements alterLibrarySemantics.
570
     */
571
    public function alterLibrarySemantics(&$semantics, $name, $majorVersion, $minorVersion)
572
    {
573
        /*
574
         * Allows you to alter the H5P library semantics, i.e. changing how the
575
         * editor looks and how content parameters are filtered.
576
         *
577
         * @since 1.5.3
578
         *
579
         * @param object &$semantics
580
         * @param string $libraryName
581
         * @param int $libraryMajorVersion
582
         * @param int $libraryMinorVersion
583
         */
584
//        $this->alterLibrarySemantics($semantics, $name, $majorVersion, $minorVersion);
585
        //        do_action_ref_array('h5p_alter_library_semantics', array(&$semantics, $name, $majorVersion, $minorVersion));
586
    }
587
588
    /**
589
     * Implements loadContent.
590
     */
591
    public function loadContent($id)
592
    {
593
        $return = DB::select('SELECT
594
                hc.id
595
              , hc.title
596
              , hc.parameters AS params
597
              , hc.filtered
598
              , hc.slug AS slug
599
              , hc.user_id
600
              , hc.embed_type AS embedType
601
              , hc.disable
602
              , hl.id AS libraryId
603
              , hl.name AS libraryName
604
              , hl.major_version AS libraryMajorVersion
605
              , hl.minor_version AS libraryMinorVersion
606
              , hl.embed_types AS libraryEmbedTypes
607
              , hl.fullscreen AS libraryFullscreen
608
        FROM h5p_contents hc
609
        JOIN h5p_libraries hl ON hl.id = hc.library_id
610
        WHERE hc.id = ?', [$id]);
611
612
        return (array) array_shift($return);
613
    }
614
615
    /**
616
     * Implements loadContentDependencies.
617
     */
618
    public function loadContentDependencies($id, $type = null)
619
    {
620
        $query = 'SELECT hl.id
621
              , hl.name AS machineName
622
              , hl.major_version AS majorVersion
623
              , hl.minor_version AS minorVersion
624
              , hl.patch_version AS patchVersion
625
              , hl.preloaded_css AS preloadedCss
626
              , hl.preloaded_js AS preloadedJs
627
              , hcl.drop_css AS dropCss
628
              , hcl.dependency_type AS dependencyType
629
        FROM h5p_contents_libraries hcl
630
        JOIN h5p_libraries hl ON hcl.library_id = hl.id
631
        WHERE hcl.content_id = ?';
632
633
        $queryArgs = [$id];
634
        if ($type !== null) {
635
            $query .= ' AND hcl.dependency_type = ?';
636
            $queryArgs[] = $type;
637
        }
638
        $query .= ' ORDER BY hcl.weight';
639
640
        $entrys = DB::select($query, $queryArgs);
641
        $return = [];
642
        foreach ($entrys as $entry) {
643
            $return[] = (array) $entry;
644
        }
645
646
        return $return;
647
    }
648
649
    /**
650
     * Implements getOption().
651
     */
652
    public function getOption($name, $default = false)
653
    {
654
        if ($name === 'site_uuid') {
655
            $name = 'h5p_site_uuid'; // Make up for old core bug
656
        }
657
658
        return config('laravel-h5p.h5p_'.$name, $default);
659
    }
660
661
    /**
662
     * Implements setOption().
663
     */
664
    public function setOption($name, $value)
665
    {
666
        if ($name === 'site_uuid') {
667
            $name = 'h5p_site_uuid'; // Make up for old core bug
668
        }
669
        config(['laravel-h5p.h5p_'.$name => $value]);
670
    }
671
672
    /**
673
     * Convert variables to fit our DB.
674
     */
675
    private static function camelToString($input)
676
    {
677
        $input = preg_replace('/[a-z0-9]([A-Z])[a-z0-9]/', '_$1', $input);
678
679
        return strtolower($input);
680
    }
681
682
    /**
683
     * Implements setFilteredParameters().
684
     */
685
    public function updateContentFields($id, $fields)
686
    {
687
        $processedFields = [];
688
        foreach ($fields as $name => $value) {
689
            $processedFields[self::camelToString($name)] = $value;
690
        }
691
        DB::table('h5p_contents')->where('id', $id)->update($processedFields);
692
    }
693
694
    /**
695
     * Implements clearFilteredParameters().
696
     */
697
    public function clearFilteredParameters($library_id)
698
    {
699
        H5pContent::where('library_id', $library_id)->update(['filtered' => null]);
700
    }
701
702
    /**
703
     * Implements getNumNotFiltered().
704
     */
705
    public function getNumNotFiltered()
706
    {
707
        return H5pContent::where('filtered', '')->count();
0 ignored issues
show
Bug Best Practice introduced by
The expression return Djoudi\LaravelH5p...filtered', '')->count() also could return the type Illuminate\Database\Eloquent\Builder which is incompatible with the return type mandated by H5PFrameworkInterface::getNumNotFiltered() of integer.
Loading history...
708
    }
709
710
    /**
711
     * Implements getNumContent().
712
     */
713
    public function getNumContent($library_id, $skip = null)
714
    {
715
        return H5pContent::where('library_id', $library_id)->count();
0 ignored issues
show
Bug Best Practice introduced by
The expression return Djoudi\LaravelH5p..., $library_id)->count() also could return the type Illuminate\Database\Eloquent\Builder which is incompatible with the return type mandated by H5PFrameworkInterface::getNumContent() of integer.
Loading history...
716
    }
717
718
    /**
719
     * Library list to load from library menu
720
     * Implements loadLibraries.
721
     */
722
    public function loadLibraries()
723
    {
724
        $results = H5pLibrary::select([
725
            'id',
726
            'name',
727
            'title',
728
            'major_version',
729
            'minor_version',
730
            'patch_version',
731
            'runnable',
732
            'restricted', ])
733
            ->orderBy('title', 'ASC')
734
            ->orderBy('major_version', 'ASC')
735
            ->orderBy('minor_version', 'ASC')
736
            ->get();
737
        $libraries = [];
738
        foreach ($results as $library) {
739
            $libraries[$library->name][] = $library;
740
        }
741
742
        return $libraries;
743
    }
744
745
    /**
746
     * Implements getAdminUrl.
747
     */
748
    public function getAdminUrl()
749
    {
750
        return route('laravel-h5p.library');
751
    }
752
753
    /**
754
     * Implements getPlatformInfo.
755
     */
756
    public function getPlatformInfo()
757
    {
758
        $laravel = app();
759
760
        return [
761
            'name'       => 'laravel',
762
            'version'    => $laravel::VERSION,
0 ignored issues
show
Bug introduced by
The constant Illuminate\Container\Container::VERSION was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
763
            'h5pVersion' => config('laravel-h5p.h5p_version'),
764
        ];
765
    }
766
767
    /**
768
     * Implements fetchExternalData.
769
     */
770
    public function fetchExternalData($url, $data = null, $blocking = true, $stream = null)
771
    {
772
        @set_time_limit(0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for set_time_limit(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

772
        /** @scrutinizer ignore-unhandled */ @set_time_limit(0);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
773
        $options = [
774
            'timeout'  => !empty($blocking) ? 30 : 0.01,
775
            'stream'   => !empty($stream),
776
            'filename' => !empty($stream) ? $stream : false,
777
        ];
778
779
        $client = new Client();
780
781
        try {
782
            if ($data !== null) {
783
                // Post
784
                $options['body'] = $data;
785
                $response = $client->request('POST', $url, ['form_params' => $options]);
786
            } else {
787
                // Get
788
                if (empty($options['filename'])) {
789
                    // Support redirects
790
                    //                $response = wp_remote_get($url);
791
                    $response = $client->request('GET', $url);
792
                } else {
793
                    // Use safe when downloading files
794
                    //                $response = wp_safe_remote_get($url, $options);
795
                    $response = $client->request('GET', $url, $options);
796
                }
797
            }
798
799
            if ($response->getStatusCode() === 200) {
800
                return empty($response->getBody()) ? true : $response->getBody();
0 ignored issues
show
Bug Best Practice introduced by
The expression return empty($response->... : $response->getBody() also could return the type true which is incompatible with the return type mandated by H5PFrameworkInterface::fetchExternalData() of string.
Loading history...
801
            } else {
802
                return;
803
            }
804
        } catch (RequestException $e) {
0 ignored issues
show
Bug introduced by
The type Djoudi\LaravelH5p\Repositories\RequestException 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...
805
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the return type mandated by H5PFrameworkInterface::fetchExternalData() of string.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
806
        }
807
    }
808
809
    /**
810
     * Implements setLibraryTutorialUrl.
811
     */
812
    public function setLibraryTutorialUrl($library_name, $url)
813
    {
814
        DB::table('h5p_libraries')->where('name', $library_name)->update(['tutorial_url' => $url]);
815
    }
816
817
    /**
818
     * Implements resetContentUserData.
819
     */
820
    public function resetContentUserData($contentId)
821
    {
822
823
        // Reset user datas for this content
824
        DB::table('h5p_contents_user_data')
825
            ->where('content_id', $contentId)
826
            ->where('invalidate', 1)
827
            ->update([
828
                'updated_at' => Carbon::now(),
829
                'data'       => 'RESET',
830
            ]);
831
    }
832
833
    /**
834
     * Implements isContentSlugAvailable.
835
     */
836
    public function isContentSlugAvailable($slug)
837
    {
838
        return DB::select("SELECT slug FROM h5p_contents WHERE slug = ':slug'", ['slub' => $slug]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return DB::select('SELEC...array('slub' => $slug)) returns the type array which is incompatible with the return type mandated by H5PFrameworkInterface::isContentSlugAvailable() of boolean.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
839
    }
840
841
    /**
842
     * Implements getLibraryContentCount.
843
     */
844
    public function getLibraryContentCount()
845
    {
846
        $count = [];
847
        // Find number of content per library
848
        $results = DB::select('SELECT l.name, l.major_version, l.minor_version, COUNT(*) AS count
849
        FROM h5p_contents c, h5p_libraries l
850
        WHERE c.library_id = l.id GROUP BY l.name, l.major_version, l.minor_version');
851
        // Extract results
852
        foreach ($results as $library) {
853
            $count[$library->name.' '.$library->major_version.'.'.$library->minor_version] = $library->count;
854
        }
855
856
        return $count;
857
    }
858
859
    /**
860
     * Implements getLibraryStats.
861
     */
862
    public function getLibraryStats($type)
863
    {
864
        $count = [];
865
        $results = DB::select('SELECT library_name AS name, library_version AS version, num FROM h5p_counters WHERE type = ?', [$type]);
866
        // Extract results
867
        foreach ($results as $library) {
868
            $count[$library->name.' '.$library->version] = $library->num;
869
        }
870
871
        return $count;
872
    }
873
874
    /**
875
     * Implements getNumAuthors.
876
     */
877
    public function getNumAuthors()
878
    {
879
        return DB::select('SELECT COUNT(DISTINCT user_id) FROM h5p_contents');
0 ignored issues
show
Bug Best Practice introduced by
The expression return DB::select('SELEC...id) FROM h5p_contents') returns the type array which is incompatible with the return type mandated by H5PFrameworkInterface::getNumAuthors() of integer.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
880
    }
881
882
    // Magic stuff not used, we do not support library development mode.
883
    public function lockDependencyStorage()
884
    {
885
    }
886
887
    public function unlockDependencyStorage()
888
    {
889
    }
890
891
    /**
892
     * Implements saveCachedAssets.
893
     */
894
    public function saveCachedAssets($key, $libraries)
895
    {
896
        foreach ($libraries as $library) {
897
            // TODO: Avoid errors if they already exists...
898
            DB::table('h5p_libraries_cachedassets')->insert(
899
                [
900
                    'library_id' => isset($library['id']) ? $library['id'] : $library['libraryId'],
901
                    'hash'       => $key,
902
                ]);
903
        }
904
    }
905
906
    /**
907
     * Implements deleteCachedAssets.
908
     */
909
    public function deleteCachedAssets($library_id)
910
    {
911
912
        // Get all the keys so we can remove the files
913
        $results = DB::select('SELECT hash FROM h5p_libraries_cachedassets WHERE library_id = ?', [$library_id]);
914
        // Remove all invalid keys
915
        $hashes = [];
916
        foreach ($results as $key) {
917
            $hashes[] = $key->hash;
918
            DB::table('h5p_libraries_cachedassets')->where('hash', $key->hash)->delete();
919
        }
920
921
        return $hashes;
922
    }
923
924
    /**
925
     * Implements afterExportCreated.
926
     */
927
    public function afterExportCreated($content, $filename)
928
    {
929
        $this->_download_file = storage_path('h5p/exports/'.$filename);
930
    }
931
932
    /**
933
     * Check if current user can edit H5P.
934
     *
935
     * @method currentUserCanEdit
936
     *
937
     * @param int $contentUserId
938
     *
939
     * @return bool
940
     */
941
    private static function currentUserCanEdit($contentUserId)
0 ignored issues
show
Unused Code introduced by
The method currentUserCanEdit() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
942
    {
943
        if (H5pHelper::current_user_can('edit_others_h5p_contents')) {
944
            return true;
945
        }
946
947
        return get_current_user_id() == $contentUserId;
0 ignored issues
show
Bug introduced by
The function get_current_user_id was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

947
        return /** @scrutinizer ignore-call */ get_current_user_id() == $contentUserId;
Loading history...
948
    }
949
950
    /**
951
     * Implements hasPermission.
952
     *
953
     * @method hasPermission
954
     *
955
     * @param H5PPermission $permission
956
     * @param int           $contentUserId
957
     *
958
     * @return bool
959
     */
960
    public function hasPermission($permission, $contentUserId = null)
961
    {
962
        switch ($permission) {
963
        case H5PPermission::DOWNLOAD_H5P:
0 ignored issues
show
Bug introduced by
The type Djoudi\LaravelH5p\Repositories\H5PPermission was not found. Did you mean H5PPermission? If so, make sure to prefix the type with \.
Loading history...
964
        case H5PPermission::EMBED_H5P:
965
//                return self::currentUserCanEdit($contentUserId);
966
            return true;
967
        case H5PPermission::CREATE_RESTRICTED:
968
        case H5PPermission::UPDATE_LIBRARIES:
969
//                return H5pHelper::current_user_can('manage_h5p_libraries');
970
            return true;
971
        case H5PPermission::INSTALL_RECOMMENDED:
972
//                H5pHelper::current_user_can('install_recommended_h5p_libraries');
973
            return true;
974
        }
975
976
        return false;
977
    }
978
979
    /**
980
     * Replaces existing content type cache with the one passed in.
981
     *
982
     * @param object $contentTypeCache Json with an array called 'libraries'
983
     *                                 containing the new content type cache that should replace the old one.
984
     */
985
    public function replaceContentTypeCache($contentTypeCache)
986
    {
987
        // Replace existing content type cache
988
        DB::table('h5p_libraries_hub_cache')->truncate();
989
990
        foreach ($contentTypeCache->contentTypes as $ct) {
991
            // Insert into db
992
            DB::insert('INSERT INTO h5p_libraries_hub_cache (
993
                machine_name,
994
                major_version,
995
                minor_version,
996
                patch_version,
997
                h5p_major_version,
998
                h5p_minor_version,
999
                title,
1000
                summary,
1001
                description,
1002
                icon,
1003
                created_at,
1004
                updated_at,
1005
                is_recommended,
1006
                popularity,
1007
                screenshots,
1008
                license,
1009
                example,
1010
                tutorial,
1011
                keywords,
1012
                categories,
1013
                owner) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [
1014
                $ct->id,
1015
                $ct->version->major,
1016
                $ct->version->minor,
1017
                $ct->version->patch,
1018
                $ct->coreApiVersionNeeded->major,
1019
                $ct->coreApiVersionNeeded->minor,
1020
                $ct->title,
1021
                $ct->summary,
1022
                $ct->description,
1023
                $ct->icon,
1024
                (new DateTime($ct->createdAt))->getTimestamp(),
0 ignored issues
show
Bug introduced by
The type Djoudi\LaravelH5p\Repositories\DateTime was not found. Did you mean DateTime? If so, make sure to prefix the type with \.
Loading history...
1025
                (new DateTime($ct->updatedAt))->getTimestamp(),
1026
                $ct->isRecommended === true ? 1 : 0,
1027
                $ct->popularity,
1028
                json_encode($ct->screenshots),
1029
                json_encode(isset($ct->license) ? $ct->license : []),
1030
                $ct->example,
1031
                isset($ct->tutorial) ? $ct->tutorial : '',
1032
                json_encode(isset($ct->keywords) ? $ct->keywords : []),
1033
                json_encode(isset($ct->categories) ? $ct->categories : []),
1034
                $ct->owner, ]
1035
            );
1036
        }
1037
    }
1038
}
1039