Completed
Push — master ( 61d47b...f50d69 )
by Abdelouahab
03:54
created

LaravelH5pRepository::loadAddons()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 1
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 1
rs 10
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
43
44
     public function loadAddons();
45
     public function getLibraryConfig($libraries = NULL);  
46
     public function libraryHasUpgrade($library); 
47
48
    /**
49
     * Implements setErrorMessage.
50
     */
51
    public function setErrorMessage($message, $code = null)
52
    {
53
        if (H5pHelper::current_user_can('edit_h5p_contents')) {
54
            $this->messages['error'][] = $message;
55
        }
56
    }
57
58
    /**
59
     * Implements setInfoMessage.
60
     */
61
    public function setInfoMessage($message)
62
    {
63
        if (H5pHelper::current_user_can('edit_h5p_contents')) {
64
            $this->messages['updated'][] = $message;
65
        }
66
    }
67
68
    /**
69
     * Return the selected messages.
70
     *
71
     * @since 1.0.0
72
     *
73
     * @param string $type
74
     *
75
     * @return array
76
     */
77
    public function getMessages($type)
78
    {
79
        return isset($this->messages[$type]) ? $this->messages[$type] : null;
80
    }
81
82
    /**
83
     * Implements t.
84
     */
85
    public function t($message, $replacements = [])
86
    {
87
        // Insert !var as is, escape @var and emphasis %var.
88
        foreach ($replacements as $key => $replacement) {
89
            if ($key[0] === '@') {
90
//                $replacements[$key] = esc_html($replacement);
91
                $replacements[$key] = $replacement;
92
            } elseif ($key[0] === '%') {
93
//                $replacements[$key] = '<em>' . esc_html($replacement) . '</em>';
94
                $replacements[$key] = '<em>'.$replacement.'</em>';
95
            }
96
        }
97
        $message = preg_replace('/(!|@|%)[a-z0-9]+/i', '%s', $message);
98
99
        // Assumes that replacement vars are in the correct order.
100
        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

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

766
        /** @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...
767
        $options = [
768
            'timeout'  => !empty($blocking) ? 30 : 0.01,
769
            'stream'   => !empty($stream),
770
            'filename' => !empty($stream) ? $stream : false,
771
        ];
772
773
        $client = new Client();
774
775
        try {
776
            if ($data !== null) {
777
                // Post
778
                $options['body'] = $data;
779
                $response = $client->request('POST', $url, ['form_params' => $options]);
780
            } else {
781
                // Get
782
                if (empty($options['filename'])) {
783
                    // Support redirects
784
                    //                $response = wp_remote_get($url);
785
                    $response = $client->request('GET', $url);
786
                } else {
787
                    // Use safe when downloading files
788
                    //                $response = wp_safe_remote_get($url, $options);
789
                    $response = $client->request('GET', $url, $options);
790
                }
791
            }
792
793
            if ($response->getStatusCode() === 200) {
794
                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...
795
            } else {
796
                return;
797
            }
798
        } 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...
799
            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...
800
        }
801
    }
802
803
    /**
804
     * Implements setLibraryTutorialUrl.
805
     */
806
    public function setLibraryTutorialUrl($library_name, $url)
807
    {
808
        DB::table('h5p_libraries')->where('name', $library_name)->update(['tutorial_url' => $url]);
809
    }
810
811
    /**
812
     * Implements resetContentUserData.
813
     */
814
    public function resetContentUserData($contentId)
815
    {
816
817
        // Reset user datas for this content
818
        DB::table('h5p_contents_user_data')
819
            ->where('content_id', $contentId)
820
            ->where('invalidate', 1)
821
            ->update([
822
                'updated_at' => Carbon::now(),
823
                'data'       => 'RESET',
824
            ]);
825
    }
826
827
    /**
828
     * Implements isContentSlugAvailable.
829
     */
830
    public function isContentSlugAvailable($slug)
831
    {
832
        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...
833
    }
834
835
    /**
836
     * Implements getLibraryContentCount.
837
     */
838
    public function getLibraryContentCount()
839
    {
840
        $count = [];
841
        // Find number of content per library
842
        $results = DB::select('SELECT l.name, l.major_version, l.minor_version, COUNT(*) AS count
843
        FROM h5p_contents c, h5p_libraries l
844
        WHERE c.library_id = l.id GROUP BY l.name, l.major_version, l.minor_version');
845
        // Extract results
846
        foreach ($results as $library) {
847
            $count[$library->name.' '.$library->major_version.'.'.$library->minor_version] = $library->count;
848
        }
849
850
        return $count;
851
    }
852
853
    /**
854
     * Implements getLibraryStats.
855
     */
856
    public function getLibraryStats($type)
857
    {
858
        $count = [];
859
        $results = DB::select('SELECT library_name AS name, library_version AS version, num FROM h5p_counters WHERE type = ?', [$type]);
860
        // Extract results
861
        foreach ($results as $library) {
862
            $count[$library->name.' '.$library->version] = $library->num;
863
        }
864
865
        return $count;
866
    }
867
868
    /**
869
     * Implements getNumAuthors.
870
     */
871
    public function getNumAuthors()
872
    {
873
        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...
874
    }
875
876
    // Magic stuff not used, we do not support library development mode.
877
    public function lockDependencyStorage()
878
    {
879
    }
880
881
    public function unlockDependencyStorage()
882
    {
883
    }
884
885
    /**
886
     * Implements saveCachedAssets.
887
     */
888
    public function saveCachedAssets($key, $libraries)
889
    {
890
        foreach ($libraries as $library) {
891
            // TODO: Avoid errors if they already exists...
892
            DB::table('h5p_libraries_cachedassets')->insert(
893
                [
894
                    'library_id' => isset($library['id']) ? $library['id'] : $library['libraryId'],
895
                    'hash'       => $key,
896
                ]);
897
        }
898
    }
899
900
    /**
901
     * Implements deleteCachedAssets.
902
     */
903
    public function deleteCachedAssets($library_id)
904
    {
905
906
        // Get all the keys so we can remove the files
907
        $results = DB::select('SELECT hash FROM h5p_libraries_cachedassets WHERE library_id = ?', [$library_id]);
908
        // Remove all invalid keys
909
        $hashes = [];
910
        foreach ($results as $key) {
911
            $hashes[] = $key->hash;
912
            DB::table('h5p_libraries_cachedassets')->where('hash', $key->hash)->delete();
913
        }
914
915
        return $hashes;
916
    }
917
918
    /**
919
     * Implements afterExportCreated.
920
     */
921
    public function afterExportCreated($content, $filename)
922
    {
923
        $this->_download_file = storage_path('h5p/exports/'.$filename);
924
    }
925
926
    /**
927
     * Check if current user can edit H5P.
928
     *
929
     * @method currentUserCanEdit
930
     *
931
     * @param int $contentUserId
932
     *
933
     * @return bool
934
     */
935
    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...
936
    {
937
        if (H5pHelper::current_user_can('edit_others_h5p_contents')) {
938
            return true;
939
        }
940
941
        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

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