summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordevianl2 <devianleong@gmail.com>2022-02-11 12:05:11 +0800
committerGitHub <noreply@github.com>2022-02-11 12:05:11 +0800
commit359e2588a4962f51c0d5cbdd2823530a15defee0 (patch)
treeb9bc389a9734ccc9d496353205a7d859bfa7bb48
parent9a3d5c62ac377bfcb9e31f98275636548c4d65ea (diff)
Revert "Improve SCORM disk storage handler"
-rw-r--r--README.md34
-rw-r--r--config/scorm.php18
-rw-r--r--database/migrations/create_scorm_tables.php.stub14
-rw-r--r--src/Entity/Scorm.php35
-rw-r--r--src/Library/ScormLib.php30
-rw-r--r--src/Manager/ScormDisk.php74
-rw-r--r--src/Manager/ScormManager.php246
-rw-r--r--src/Model/ScormScoModel.php11
8 files changed, 166 insertions, 296 deletions
diff --git a/README.md b/README.md
index b0dd5a2..4aaec66 100644
--- a/README.md
+++ b/README.md
@@ -32,42 +32,8 @@ php artisan vendor:publish --provider="Peopleaps\Scorm\ScormServiceProvider"
```
## Step 3:
-Run config cache for update cached configuration
-```sh
-php artisan config:cache
-```
-
-## Step 4:
Migrate file to database
```sh
php artisan migrate
```
-## Step 5 (Optional):
-update SCORM config under config/scorm
-- update scorm table names.
-- update SCORM disk and configure disk @see config/filesystems.php
-```
- 'disk' => 'scorm-local',
- 'disk' => 'scorm-s3',
-
- // @see config/filesystems.php
- 'disks' => [
- .....
- 'scorm-local' => [
- 'driver' => 'local',
- 'root' => env('SCORM_ROOT_DIR'), // set root dir
- 'visibility' => 'public',
- ],
-
- 's3-scorm' => [
- 'driver' => 's3',
- 'root' => env('SCORM_ROOT_DIR'), // set root dir
- 'key' => env('AWS_ACCESS_KEY_ID'),
- 'secret' => env('AWS_SECRET_ACCESS_KEY'),
- 'region' => env('AWS_DEFAULT_REGION'),
- 'bucket' => env('AWS_SCORM_BUCKET'),
- ],
- .....
- ]
-```
diff --git a/config/scorm.php b/config/scorm.php
index 0330bc5..e5efb3f 100644
--- a/config/scorm.php
+++ b/config/scorm.php
@@ -3,25 +3,11 @@
return [
'table_names' => [
- 'user_table' => 'users', // user table name on main LMS app.
+ 'user_table' => 'users',
'scorm_table' => 'scorm',
'scorm_sco_table' => 'scorm_sco',
'scorm_sco_tracking_table' => 'scorm_sco_tracking',
],
- /**
- * Scorm directory. You may create a custom path in file system
- * Define Scorm disk under @see config/filesystems.php
- * 'disk' => 'local',
- * 'disk' => 's3-scorm',
- * ex.
- * 's3-scorm' => [
- * 'driver' => 's3',
- * 'root' => env('SCORM_ROOT_DIR'), // define root dir
- * 'key' => env('AWS_ACCESS_KEY_ID'),
- * 'secret' => env('AWS_SECRET_ACCESS_KEY'),
- * 'region' => env('AWS_DEFAULT_REGION'),
- * 'bucket' => env('AWS_SCORM_BUCKET'),
- * ],
- */
+ // Scorm directory. You may create a custom path in file system
'disk' => 'local',
];
diff --git a/database/migrations/create_scorm_tables.php.stub b/database/migrations/create_scorm_tables.php.stub
index 6a136b3..506e9cb 100644
--- a/database/migrations/create_scorm_tables.php.stub
+++ b/database/migrations/create_scorm_tables.php.stub
@@ -97,7 +97,19 @@ class CreateScormTables extends Migration
*/
public function down()
{
- $tableNames = config('scorm.table_names');
+ $tableNames = config('scorm_sco_tracking_table');
+
+ if (empty($tableNames)) {
+ throw new \Exception('Error: Table not found.');
+ }
+
+ $tableNames = config('scorm_sco_table');
+
+ if (empty($tableNames)) {
+ throw new \Exception('Error: Table not found.');
+ }
+
+ $tableNames = config('scorm_table');
if (empty($tableNames)) {
throw new \Exception('Error: Table not found.');
diff --git a/src/Entity/Scorm.php b/src/Entity/Scorm.php
index 48fd711..4095986 100644
--- a/src/Entity/Scorm.php
+++ b/src/Entity/Scorm.php
@@ -3,6 +3,9 @@
namespace Peopleaps\Scorm\Entity;
+
+use Doctrine\Common\Collections\ArrayCollection;
+
class Scorm
{
const SCORM_12 = 'scorm_12';
@@ -10,9 +13,8 @@ class Scorm
public $uuid;
public $id;
- public $title;
public $version;
- public $entryUrl;
+ public $hashName;
public $ratio = 56.25;
public $scos;
public $scoSerializer;
@@ -68,33 +70,17 @@ class Scorm
/**
* @return string
*/
- public function getTitle()
- {
- return $this->title;
- }
-
- /**
- * @param string $title
- */
- public function setTitle($title)
- {
- $this->title = $title;
- }
-
- /**
- * @return string
- */
- public function getEntryUrl()
+ public function getHashName()
{
- return $this->entryUrl;
+ return $this->hashName;
}
/**
- * @param string $title
+ * @param string $hashName
*/
- public function setEntryUrl($entryUrl)
+ public function setHashName($hashName)
{
- $this->entryUrl = $entryUrl;
+ $this->hashName = $hashName;
}
/**
@@ -145,8 +131,7 @@ class Scorm
return [
'id' => $scorm->getUuid(),
'version' => $scorm->getVersion(),
- 'title' => $scorm->getTitle(),
- 'entryUrl' => $scorm->getEntryUrl(),
+ 'hashName' => $scorm->getHashName(),
'ratio' => $scorm->getRatio(),
'scos' => $this->serializeScos($scorm),
];
diff --git a/src/Library/ScormLib.php b/src/Library/ScormLib.php
index 731601a..0ca8a6b 100644
--- a/src/Library/ScormLib.php
+++ b/src/Library/ScormLib.php
@@ -7,7 +7,7 @@ namespace Peopleaps\Scorm\Library;
use DOMDocument;
use Peopleaps\Scorm\Entity\Sco;
use Peopleaps\Scorm\Exception\InvalidScormArchiveException;
-use Illuminate\Support\Str;
+use Ramsey\Uuid\Uuid;
class ScormLib
{
@@ -28,20 +28,16 @@ class ScormLib
$organizations = $organizationsList->item(0);
$organization = $organizations->firstChild;
- if (
- !is_null($organizations->attributes)
- && !is_null($organizations->attributes->getNamedItem('default'))
- ) {
+ if (!is_null($organizations->attributes)
+ && !is_null($organizations->attributes->getNamedItem('default'))) {
$defaultOrganization = $organizations->attributes->getNamedItem('default')->nodeValue;
} else {
$defaultOrganization = null;
}
// No default organization is defined
if (is_null($defaultOrganization)) {
- while (
- !is_null($organization)
- && 'organization' !== $organization->nodeName
- ) {
+ while (!is_null($organization)
+ && 'organization' !== $organization->nodeName) {
$organization = $organization->nextSibling;
}
@@ -52,12 +48,10 @@ class ScormLib
// A default organization is defined
// Look for it
else {
- while (
- !is_null($organization)
+ while (!is_null($organization)
&& ('organization' !== $organization->nodeName
|| is_null($organization->attributes->getNamedItem('identifier'))
- || $organization->attributes->getNamedItem('identifier')->nodeValue !== $defaultOrganization)
- ) {
+ || $organization->attributes->getNamedItem('identifier')->nodeValue !== $defaultOrganization)) {
$organization = $organization->nextSibling;
}
@@ -88,7 +82,7 @@ class ScormLib
if ('item' === $item->nodeName) {
$sco = new Sco();
$scos[] = $sco;
- $sco->setUuid(Str::uuid());
+ $sco->setUuid(Uuid::uuid4());
$sco->setScoParent($parentSco);
$this->findAttrParams($sco, $item, $resources);
$this->findNodeParams($sco, $item->firstChild);
@@ -125,7 +119,7 @@ class ScormLib
throw new InvalidScormArchiveException('sco_resource_without_href_message');
}
$sco = new Sco();
- $sco->setUuid(Str::uuid());
+ $sco->setUuid(Uuid::uuid4());
$sco->setBlock(false);
$sco->setVisible(true);
$sco->setIdentifier($identifier->nodeValue);
@@ -201,12 +195,10 @@ class ScormLib
case 'adlcp:timeLimitAction':
$action = strtolower($item->nodeValue);
- if (
- 'exit,message' === $action
+ if ('exit,message' === $action
|| 'exit,no message' === $action
|| 'continue,message' === $action
- || 'continue,no message' === $action
- ) {
+ || 'continue,no message' === $action) {
$sco->setTimeLimitAction($action);
}
break;
diff --git a/src/Manager/ScormDisk.php b/src/Manager/ScormDisk.php
deleted file mode 100644
index 249f027..0000000
--- a/src/Manager/ScormDisk.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-namespace Peopleaps\Scorm\Manager;
-
-use Illuminate\Filesystem\FilesystemAdapter;
-use Illuminate\Support\Facades\Storage;
-use Peopleaps\Scorm\Exception\StorageNotFoundException;
-use ZipArchive;
-
-class ScormDisk
-{
- /**
- * Extract zip file into destination directory.
- *
- * @param string $path Destination directory
- * @param string $zipFilePath The path to the zip file.
- *
- * @return bool True on success, false on failure.
- */
- public function unzip($file, $path)
- {
- $path = $this->cleanPath($path);
-
- $zipArchive = new ZipArchive();
- if ($zipArchive->open($file) !== true) {
- return false;
- }
-
- /** @var FilesystemAdapter $disk */
- $disk = $this->getDisk();
-
- for ($i = 0; $i < $zipArchive->numFiles; ++$i) {
- $zipEntryName = $zipArchive->getNameIndex($i);
- $destination = $path . DIRECTORY_SEPARATOR . $this->cleanPath($zipEntryName);
- if ($this->isDirectory($zipEntryName)) {
- $disk->createDir($destination);
- continue;
- }
- $disk->putStream($destination, $zipArchive->getStream($zipEntryName));
- }
-
- return true;
- }
-
- /**
- * @param string $directory
- * @return bool
- */
- public function deleteScormFolder($folderHashedName)
- {
- return $this->getDisk()->deleteDirectory($folderHashedName);
- }
-
- private function isDirectory($zipEntryName)
- {
- return substr($zipEntryName, -1) === '/';
- }
-
- private function cleanPath($path)
- {
- return str_replace('/', DIRECTORY_SEPARATOR, $path);
- }
-
- /**
- * @return FilesystemAdapter $disk
- */
- private function getDisk()
- {
- if (!config()->has('filesystems.disks.' . config('scorm.disk'))) {
- throw new StorageNotFoundException('scorm_disk_not_define');
- }
- return Storage::disk(config('scorm.disk'));
- }
-}
diff --git a/src/Manager/ScormManager.php b/src/Manager/ScormManager.php
index 56c723c..2a54706 100644
--- a/src/Manager/ScormManager.php
+++ b/src/Manager/ScormManager.php
@@ -3,28 +3,31 @@
namespace Peopleaps\Scorm\Manager;
+use App\Models\User;
use Carbon\Carbon;
use DOMDocument;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\UploadedFile;
+use Illuminate\Support\Facades\File;
+use Illuminate\Support\Facades\Storage;
+use League\Flysystem\FileNotFoundException;
+use Peopleaps\Scorm\Entity\Sco;
use Peopleaps\Scorm\Entity\Scorm;
use Peopleaps\Scorm\Entity\ScoTracking;
use Peopleaps\Scorm\Exception\InvalidScormArchiveException;
+use Peopleaps\Scorm\Exception\StorageNotFoundException;
use Peopleaps\Scorm\Library\ScormLib;
use Peopleaps\Scorm\Model\ScormModel;
use Peopleaps\Scorm\Model\ScormScoModel;
use Peopleaps\Scorm\Model\ScormScoTrackingModel;
-use Illuminate\Support\Str;
-use Peopleaps\Scorm\Entity\Sco;
+use Ramsey\Uuid\Uuid;
use ZipArchive;
class ScormManager
{
/** @var ScormLib */
private $scormLib;
- /** @var ScormDisk */
- private $scormDisk;
/**
* Constructor.
@@ -32,18 +35,18 @@ class ScormManager
* @param string $filesDir
* @param string $uploadDir
*/
- public function __construct()
- {
+ public function __construct(
+ ) {
$this->scormLib = new ScormLib();
- $this->scormDisk = new ScormDisk();
}
- public function uploadScormArchive(UploadedFile $file)
+ public function uploadScormArchive(UploadedFile $file, Model $model)
{
// Checks if it is a valid scorm archive
$scormData = null;
$zip = new ZipArchive();
$openValue = $zip->open($file);
+ $oldModel = null;
$isScormArchive = (true === $openValue) && $zip->getStream('imsmanifest.xml');
@@ -55,71 +58,57 @@ class ScormManager
$scormData = $this->generateScorm($file);
}
+ $oldModel = $model->scorm()->first(); // get old scorm data for deletion (If success to store new)
+
// save to db
- if (is_null($scormData) || !is_array($scormData)) {
- throw new InvalidScormArchiveException('invalid_scorm_data');
- }
+ if ($scormData && is_array($scormData)) {
- $scorm = ScormModel::whereOriginFile($scormData['identifier']);
- // Check if scom package already exists to drop old one.
- if (!$scorm->exists()) {
- $scorm = new ScormModel();
- } else {
- $scorm = $scorm->first();
- $this->deleteScormData($scorm);
- }
+ $scorm = new ScormModel();
+ $scorm->version = $scormData['version'];
+ $scorm->hash_name = $scormData['hashName'];
+ $scorm->origin_file = $scormData['name'];
+ $scorm->origin_file_mime = $scormData['type'];
+ $scorm->uuid = $scormData['hashName'];
+
+ $scorm = $model->scorm()->save($scorm);
- $scorm->uuid = $scormData['uuid'];
- $scorm->title = $scormData['title'];
- $scorm->version = $scormData['version'];
- $scorm->entry_url = $scormData['entryUrl'];
- $scorm->origin_file = $scormData['identifier'];
- $scorm->save();
-
- if (!empty($scormData['scos']) && is_array($scormData['scos'])) {
- /** @var Sco $scoData */
- foreach ($scormData['scos'] as $scoData) {
- $sco = $this->saveScormScos($scorm->id, $scoData);
- if ($scoData->scoChildren) {
- foreach ($scoData->scoChildren as $scoChild) {
- $this->saveScormScos($scorm->id, $scoChild, $sco->id);
+ if (!empty($scormData['scos']) && is_array($scormData['scos'])) {
+ foreach ($scormData['scos'] as $scoData) {
+
+ $scoParent = null;
+ if (!empty($scoData->scoParent)) {
+ $scoParent = ScormScoModel::where('uuid', $scoData->scoParent->uuid)->first();
}
+
+ $sco = new ScormScoModel();
+ $sco->scorm_id = $scorm->id;
+ $sco->uuid = $scoData->uuid;
+ $sco->sco_parent_id = $scoParent ? $scoParent->id : null;
+ $sco->entry_url = $scoData->entryUrl;
+ $sco->identifier = $scoData->identifier;
+ $sco->title = $scoData->title;
+ $sco->visible = $scoData->visible;
+ $sco->sco_parameters = $scoData->parameters;
+ $sco->launch_data = $scoData->launchData;
+ $sco->max_time_allowed = $scoData->maxTimeAllowed;
+ $sco->time_limit_action = $scoData->timeLimitAction;
+ $sco->block = $scoData->block;
+ $sco->score_int = $scoData->scoreToPassInt;
+ $sco->score_decimal = $scoData->scoreToPassDecimal;
+ $sco->completion_threshold = $scoData->completionThreshold;
+ $sco->prerequisites = $scoData->prerequisites;
+ $sco->save();
}
}
+
+ if ($oldModel != null) {
+ $this->deleteScormData($oldModel);
+ }
}
return $scormData;
}
- /**
- * Save Scorm sco and it's nested children
- * @param int $scorm_id scorm id.
- * @param Sco $scoData Sco data to be store.
- * @param int $sco_parent_id sco parent id for children
- */
- private function saveScormScos($scorm_id, $scoData, $sco_parent_id = null)
- {
- $sco = new ScormScoModel();
- $sco->scorm_id = $scorm_id;
- $sco->uuid = $scoData->uuid;
- $sco->sco_parent_id = $sco_parent_id;
- $sco->entry_url = $scoData->entryUrl;
- $sco->identifier = $scoData->identifier;
- $sco->title = $scoData->title;
- $sco->visible = $scoData->visible;
- $sco->sco_parameters = $scoData->parameters;
- $sco->launch_data = $scoData->launchData;
- $sco->max_time_allowed = $scoData->maxTimeAllowed;
- $sco->time_limit_action = $scoData->timeLimitAction;
- $sco->block = $scoData->block;
- $sco->score_int = $scoData->scoreToPassInt;
- $sco->score_decimal = $scoData->scoreToPassDecimal;
- $sco->completion_threshold = $scoData->completionThreshold;
- $sco->prerequisites = $scoData->prerequisites;
- $sco->save();
- return $sco;
- }
-
private function parseScormArchive(UploadedFile $file)
{
$data = [];
@@ -140,18 +129,8 @@ class ScormManager
throw new InvalidScormArchiveException('cannot_load_imsmanifest_message');
}
- $manifest = $dom->getElementsByTagName('manifest')->item(0);
- if (!is_null($manifest->attributes->getNamedItem('identifier'))) {
- $data['identifier'] = $manifest->attributes->getNamedItem('identifier')->nodeValue;
- } else {
- throw new InvalidScormArchiveException('invalid_scorm_manifest_identifier');
- }
- $titles = $dom->getElementsByTagName('title');
- if ($titles->length > 0) {
- $data['title'] = Str::of($titles->item(0)->textContent)->trim('/n')->trim();
- }
-
$scormVersionElements = $dom->getElementsByTagName('schemaversion');
+
if ($scormVersionElements->length > 0) {
switch ($scormVersionElements->item(0)->textContent) {
case '1.2':
@@ -173,43 +152,69 @@ class ScormManager
if (0 >= count($scos)) {
throw new InvalidScormArchiveException('no_sco_in_scorm_archive_message');
}
-
- $data['entryUrl'] = $scos[0]->entryUrl ?? $scos[0]->scoChildren[0]->entryUrl;
$data['scos'] = $scos;
return $data;
}
- public function deleteScorm($model)
- {
+ public function deleteScormData($model) {
// Delete after the previous item is stored
if ($model) {
- $this->deleteScormData($model);
+
+ $oldScos = $model->scos()->get();
+
+ // Delete all tracking associate with sco
+ foreach ($oldScos as $oldSco) {
+ $oldSco->scoTrackings()->delete();
+ }
+
+ $model->scos()->delete(); // delete scos
$model->delete(); // delete scorm
+
+ // Delete folder from server
+ $this->deleteScormFolder($model->hash_name);
}
}
+ /**
+ * @param $folderHashedName
+ * @return bool
+ */
+ protected function deleteScormFolder($folderHashedName) {
- private function deleteScormData($model)
- {
- // Delete after the previous item is stored
- $oldScos = $model->scos()->get();
+ $response = Storage::disk('scorm')->deleteDirectory($folderHashedName);
- // Delete all tracking associate with sco
- foreach ($oldScos as $oldSco) {
- $oldSco->scoTrackings()->delete();
- }
- $model->scos()->delete(); // delete scos
- // Delete folder from server
- $this->deleteScormFolder($model->uuid);
+ return $response;
}
/**
- * @param $folderHashedName
- * @return bool
+ * Unzip a given ZIP file into the web resources directory.
+ *
+ * @param string $hashName name of the destination directory
*/
- protected function deleteScormFolder($folderHashedName)
+ private function unzipScormArchive(UploadedFile $file, $hashName)
{
- return $this->scormDisk->deleteScormFolder($folderHashedName);
+ $zip = new \ZipArchive();
+ $zip->open($file);
+
+ if (!config()->has('filesystems.disks.'.config('scorm.disk').'.root')) {
+ throw new StorageNotFoundException();
+ }
+
+ $rootFolder = config('filesystems.disks.'.config('scorm.disk').'.root');
+
+ if (substr($rootFolder, -1) != '/') {
+ // If end with xxx/
+ $rootFolder = config('filesystems.disks.'.config('scorm.disk').'.root').'/';
+ }
+
+ $destinationDir = $rootFolder.$hashName; // file path
+
+ if (!File::isDirectory($destinationDir)) {
+ File::makeDirectory($destinationDir, 0755, true, true);
+ }
+
+ $zip->extractTo($destinationDir);
+ $zip->close();
}
/**
@@ -219,21 +224,32 @@ class ScormManager
*/
private function generateScorm(UploadedFile $file)
{
- $uuid = Str::uuid();
+ $hashName = Uuid::uuid4();
+ $hashFileName = $hashName.'.zip';
$scormData = $this->parseScormArchive($file);
- /**
- * Unzip a given ZIP file into the web resources directory.
- *
- * @param string $hashName name of the destination directory
- */
- $this->scormDisk->unzip($file, $uuid);
+ $this->unzipScormArchive($file, $hashName);
+
+ if (!config()->has('filesystems.disks.'.config('scorm.disk').'.root')) {
+ throw new StorageNotFoundException();
+ }
+
+ $rootFolder = config('filesystems.disks.'.config('scorm.disk').'.root');
+
+ if (substr($rootFolder, -1) != '/') {
+ // If end with xxx/
+ $rootFolder = config('filesystems.disks.'.config('scorm.disk').'.root').'/';
+ }
+
+ $destinationDir = $rootFolder.$hashName; // file path
+
+ // Move Scorm archive in the files directory
+ $finalFile = $file->move($destinationDir, $hashName.'.zip');
return [
- 'identifier' => $scormData['identifier'],
- 'uuid' => $uuid,
- 'title' => $scormData['title'], // to follow standard file data format
+ 'name' => $hashFileName, // to follow standard file data format
+ 'hashName' => $hashName,
+ 'type' => $finalFile->getMimeType(),
'version' => $scormData['version'],
- 'entryUrl' => $scormData['entryUrl'],
'scos' => $scormData['scos'],
];
}
@@ -243,8 +259,7 @@ class ScormManager
* @param $scormId
* @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
*/
- public function getScos($scormId)
- {
+ public function getScos($scormId) {
$scos = ScormScoModel::with([
'scorm'
])->where('scorm_id', $scormId)
@@ -258,8 +273,7 @@ class ScormManager
* @param $scoUuid
* @return null|\Illuminate\Database\Eloquent\Builder|Model
*/
- public function getScoByUuid($scoUuid)
- {
+ public function getScoByUuid($scoUuid) {
$sco = ScormScoModel::with([
'scorm'
])->where('uuid', $scoUuid)
@@ -268,8 +282,7 @@ class ScormManager
return $sco;
}
- public function getUserResult($scoId, $userId)
- {
+ public function getUserResult($scoId, $userId) {
return ScormScoTrackingModel::where('sco_id', $scoId)->where('user_id', $userId)->first();
}
@@ -314,7 +327,7 @@ class ScormManager
'user_id' => $userId,
'sco_id' => $sco->id
], [
- 'uuid' => Str::uuid(),
+ 'uuid' => Uuid::uuid4(),
'progression' => $scoTracking->getProgression(),
'score_raw' => $scoTracking->getScoreRaw(),
'score_min' => $scoTracking->getScoreMin(),
@@ -362,8 +375,7 @@ class ScormManager
return $scoTracking;
}
- public function findScoTrackingId($scoUuid, $scoTrackingUuid)
- {
+ public function findScoTrackingId($scoUuid, $scoTrackingUuid) {
return ScormScoTrackingModel::with([
'sco'
])->whereHas('sco', function (Builder $query) use ($scoUuid) {
@@ -372,8 +384,7 @@ class ScormManager
->firstOrFail();
}
- public function checkUserIsCompletedScorm($scormId, $userId)
- {
+ public function checkUserIsCompletedScorm($scormId, $userId) {
$completedSco = [];
$scos = ScormScoModel::where('scorm_id', $scormId)->get();
@@ -527,8 +538,7 @@ class ScormManager
$bestStatus = $lessonStatus;
}
- if (
- empty($tracking->getCompletionStatus())
+ if (empty($tracking->getCompletionStatus())
|| ($completionStatus !== $tracking->getCompletionStatus() && $statusPriority[$completionStatus] > $statusPriority[$tracking->getCompletionStatus()])
) {
// This is no longer needed as completionStatus and successStatus are merged together
@@ -620,7 +630,7 @@ class ScormManager
$remainingTime %= 3600;
$nbMinutes = (int) ($remainingTime / 60);
$nbSeconds = $remainingTime % 60;
- $result .= 'P' . $nbDays . 'DT' . $nbHours . 'H' . $nbMinutes . 'M' . $nbSeconds . 'S';
+ $result .= 'P'.$nbDays.'DT'.$nbHours.'H'.$nbMinutes.'M'.$nbSeconds.'S';
}
return $result;
diff --git a/src/Model/ScormScoModel.php b/src/Model/ScormScoModel.php
index d606d32..de50741 100644
--- a/src/Model/ScormScoModel.php
+++ b/src/Model/ScormScoModel.php
@@ -13,18 +13,11 @@ class ScormScoModel extends Model
return config('scorm.table_names.scorm_sco_table', parent::getTable());
}
- public function scorm()
- {
+ public function scorm() {
return $this->belongsTo(ScormModel::class, 'scorm_id', 'id');
}
- public function scoTrackings()
- {
+ public function scoTrackings() {
return $this->hasMany(ScormScoTrackingModel::class, 'sco_id', 'id');
}
-
- public function children()
- {
- return $this->hasMany(ScormScoModel::class, 'sco_parent_id', 'id');
- }
}