Skip to content

Commit 88d7940

Browse files
authored
Merge pull request #9 from devianl2/revert-8-revert-7-main
Revert "Revert "Improve SCORM disk storage handler""
2 parents 3da4550 + 8a88eed commit 88d7940

File tree

9 files changed

+303
-167
lines changed

9 files changed

+303
-167
lines changed

README.md

+34
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,42 @@ php artisan vendor:publish --provider="Peopleaps\Scorm\ScormServiceProvider"
3232
```
3333

3434
## Step 3:
35+
Run config cache for update cached configuration
36+
```sh
37+
php artisan config:cache
38+
```
39+
40+
## Step 4:
3541
Migrate file to database
3642
```sh
3743
php artisan migrate
3844
```
3945

46+
## Step 5 (Optional):
47+
update SCORM config under config/scorm
48+
- update scorm table names.
49+
- update SCORM disk and configure disk @see config/filesystems.php
50+
```
51+
'disk' => 'scorm-local',
52+
'disk' => 'scorm-s3',
53+
54+
// @see config/filesystems.php
55+
'disks' => [
56+
.....
57+
'scorm-local' => [
58+
'driver' => 'local',
59+
'root' => env('SCORM_ROOT_DIR'), // set root dir
60+
'visibility' => 'public',
61+
],
62+
63+
's3-scorm' => [
64+
'driver' => 's3',
65+
'root' => env('SCORM_ROOT_DIR'), // set root dir
66+
'key' => env('AWS_ACCESS_KEY_ID'),
67+
'secret' => env('AWS_SECRET_ACCESS_KEY'),
68+
'region' => env('AWS_DEFAULT_REGION'),
69+
'bucket' => env('AWS_SCORM_BUCKET'),
70+
],
71+
.....
72+
]
73+
```

config/scorm.php

+16-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,25 @@
33
return [
44

55
'table_names' => [
6-
'user_table' => 'users',
6+
'user_table' => 'users', // user table name on main LMS app.
77
'scorm_table' => 'scorm',
88
'scorm_sco_table' => 'scorm_sco',
99
'scorm_sco_tracking_table' => 'scorm_sco_tracking',
1010
],
11-
// Scorm directory. You may create a custom path in file system
11+
/**
12+
* Scorm directory. You may create a custom path in file system
13+
* Define Scorm disk under @see config/filesystems.php
14+
* 'disk' => 'local',
15+
* 'disk' => 's3-scorm',
16+
* ex.
17+
* 's3-scorm' => [
18+
* 'driver' => 's3',
19+
* 'root' => env('SCORM_ROOT_DIR'), // define root dir
20+
* 'key' => env('AWS_ACCESS_KEY_ID'),
21+
* 'secret' => env('AWS_SECRET_ACCESS_KEY'),
22+
* 'region' => env('AWS_DEFAULT_REGION'),
23+
* 'bucket' => env('AWS_SCORM_BUCKET'),
24+
* ],
25+
*/
1226
'disk' => 'local',
1327
];

database/migrations/create_scorm_tables.php.stub

+1-13
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,7 @@ class CreateScormTables extends Migration
9797
*/
9898
public function down()
9999
{
100-
$tableNames = config('scorm_sco_tracking_table');
101-
102-
if (empty($tableNames)) {
103-
throw new \Exception('Error: Table not found.');
104-
}
105-
106-
$tableNames = config('scorm_sco_table');
107-
108-
if (empty($tableNames)) {
109-
throw new \Exception('Error: Table not found.');
110-
}
111-
112-
$tableNames = config('scorm_table');
100+
$tableNames = config('scorm.table_names');
113101

114102
if (empty($tableNames)) {
115103
throw new \Exception('Error: Table not found.');

src/Entity/Scorm.php

+25-10
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@
33

44
namespace Peopleaps\Scorm\Entity;
55

6-
7-
use Doctrine\Common\Collections\ArrayCollection;
8-
96
class Scorm
107
{
118
const SCORM_12 = 'scorm_12';
129
const SCORM_2004 = 'scorm_2004';
1310

1411
public $uuid;
1512
public $id;
13+
public $title;
1614
public $version;
17-
public $hashName;
15+
public $entryUrl;
1816
public $ratio = 56.25;
1917
public $scos;
2018
public $scoSerializer;
@@ -70,17 +68,33 @@ public function setVersion($version)
7068
/**
7169
* @return string
7270
*/
73-
public function getHashName()
71+
public function getTitle()
72+
{
73+
return $this->title;
74+
}
75+
76+
/**
77+
* @param string $title
78+
*/
79+
public function setTitle($title)
80+
{
81+
$this->title = $title;
82+
}
83+
84+
/**
85+
* @return string
86+
*/
87+
public function getEntryUrl()
7488
{
75-
return $this->hashName;
89+
return $this->entryUrl;
7690
}
7791

7892
/**
79-
* @param string $hashName
93+
* @param string $title
8094
*/
81-
public function setHashName($hashName)
95+
public function setEntryUrl($entryUrl)
8296
{
83-
$this->hashName = $hashName;
97+
$this->entryUrl = $entryUrl;
8498
}
8599

86100
/**
@@ -131,7 +145,8 @@ public function serialize(Scorm $scorm)
131145
return [
132146
'id' => $scorm->getUuid(),
133147
'version' => $scorm->getVersion(),
134-
'hashName' => $scorm->getHashName(),
148+
'title' => $scorm->getTitle(),
149+
'entryUrl' => $scorm->getEntryUrl(),
135150
'ratio' => $scorm->getRatio(),
136151
'scos' => $this->serializeScos($scorm),
137152
];

src/Library/ScormLib.php

+19-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use DOMDocument;
88
use Peopleaps\Scorm\Entity\Sco;
99
use Peopleaps\Scorm\Exception\InvalidScormArchiveException;
10-
use Ramsey\Uuid\Uuid;
10+
use Illuminate\Support\Str;
1111

1212
class ScormLib
1313
{
@@ -28,16 +28,20 @@ public function parseOrganizationsNode(DOMDocument $dom)
2828
$organizations = $organizationsList->item(0);
2929
$organization = $organizations->firstChild;
3030

31-
if (!is_null($organizations->attributes)
32-
&& !is_null($organizations->attributes->getNamedItem('default'))) {
31+
if (
32+
!is_null($organizations->attributes)
33+
&& !is_null($organizations->attributes->getNamedItem('default'))
34+
) {
3335
$defaultOrganization = $organizations->attributes->getNamedItem('default')->nodeValue;
3436
} else {
3537
$defaultOrganization = null;
3638
}
3739
// No default organization is defined
3840
if (is_null($defaultOrganization)) {
39-
while (!is_null($organization)
40-
&& 'organization' !== $organization->nodeName) {
41+
while (
42+
!is_null($organization)
43+
&& 'organization' !== $organization->nodeName
44+
) {
4145
$organization = $organization->nextSibling;
4246
}
4347

@@ -48,10 +52,12 @@ public function parseOrganizationsNode(DOMDocument $dom)
4852
// A default organization is defined
4953
// Look for it
5054
else {
51-
while (!is_null($organization)
55+
while (
56+
!is_null($organization)
5257
&& ('organization' !== $organization->nodeName
5358
|| is_null($organization->attributes->getNamedItem('identifier'))
54-
|| $organization->attributes->getNamedItem('identifier')->nodeValue !== $defaultOrganization)) {
59+
|| $organization->attributes->getNamedItem('identifier')->nodeValue !== $defaultOrganization)
60+
) {
5561
$organization = $organization->nextSibling;
5662
}
5763

@@ -82,7 +88,7 @@ private function parseItemNodes(\DOMNode $source, \DOMNodeList $resources, Sco $
8288
if ('item' === $item->nodeName) {
8389
$sco = new Sco();
8490
$scos[] = $sco;
85-
$sco->setUuid(Uuid::uuid4());
91+
$sco->setUuid(Str::uuid());
8692
$sco->setScoParent($parentSco);
8793
$this->findAttrParams($sco, $item, $resources);
8894
$this->findNodeParams($sco, $item->firstChild);
@@ -119,7 +125,7 @@ private function parseResourceNodes(\DOMNodeList $resources)
119125
throw new InvalidScormArchiveException('sco_resource_without_href_message');
120126
}
121127
$sco = new Sco();
122-
$sco->setUuid(Uuid::uuid4());
128+
$sco->setUuid(Str::uuid());
123129
$sco->setBlock(false);
124130
$sco->setVisible(true);
125131
$sco->setIdentifier($identifier->nodeValue);
@@ -195,10 +201,12 @@ private function findNodeParams(Sco $sco, \DOMNode $item)
195201
case 'adlcp:timeLimitAction':
196202
$action = strtolower($item->nodeValue);
197203

198-
if ('exit,message' === $action
204+
if (
205+
'exit,message' === $action
199206
|| 'exit,no message' === $action
200207
|| 'continue,message' === $action
201-
|| 'continue,no message' === $action) {
208+
|| 'continue,no message' === $action
209+
) {
202210
$sco->setTimeLimitAction($action);
203211
}
204212
break;

src/Manager/ScormDisk.php

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespace Peopleaps\Scorm\Manager;
4+
5+
use Illuminate\Filesystem\FilesystemAdapter;
6+
use Illuminate\Support\Facades\Storage;
7+
use Peopleaps\Scorm\Exception\StorageNotFoundException;
8+
use ZipArchive;
9+
10+
class ScormDisk
11+
{
12+
/**
13+
* Extract zip file into destination directory.
14+
*
15+
* @param string $path Destination directory
16+
* @param string $zipFilePath The path to the zip file.
17+
*
18+
* @return bool True on success, false on failure.
19+
*/
20+
public function unzip($file, $path)
21+
{
22+
$path = $this->cleanPath($path);
23+
24+
$zipArchive = new ZipArchive();
25+
if ($zipArchive->open($file) !== true) {
26+
return false;
27+
}
28+
29+
/** @var FilesystemAdapter $disk */
30+
$disk = $this->getDisk();
31+
32+
for ($i = 0; $i < $zipArchive->numFiles; ++$i) {
33+
$zipEntryName = $zipArchive->getNameIndex($i);
34+
$destination = $path . DIRECTORY_SEPARATOR . $this->cleanPath($zipEntryName);
35+
if ($this->isDirectory($zipEntryName)) {
36+
$disk->createDir($destination);
37+
continue;
38+
}
39+
$disk->putStream($destination, $zipArchive->getStream($zipEntryName));
40+
}
41+
42+
return true;
43+
}
44+
45+
/**
46+
* @param string $directory
47+
* @return bool
48+
*/
49+
public function deleteScormFolder($folderHashedName)
50+
{
51+
return $this->getDisk()->deleteDirectory($folderHashedName);
52+
}
53+
54+
private function isDirectory($zipEntryName)
55+
{
56+
return substr($zipEntryName, -1) === '/';
57+
}
58+
59+
private function cleanPath($path)
60+
{
61+
return str_replace('/', DIRECTORY_SEPARATOR, $path);
62+
}
63+
64+
/**
65+
* @return FilesystemAdapter $disk
66+
*/
67+
private function getDisk()
68+
{
69+
if (!config()->has('filesystems.disks.' . config('scorm.disk'))) {
70+
throw new StorageNotFoundException('scorm_disk_not_define');
71+
}
72+
return Storage::disk(config('scorm.disk'));
73+
}
74+
}

0 commit comments

Comments
 (0)