diff --git a/sourcecode/apis/contentauthor/app/Article.php b/sourcecode/apis/contentauthor/app/Article.php index cd56fb68a2..f3659ac51b 100644 --- a/sourcecode/apis/contentauthor/app/Article.php +++ b/sourcecode/apis/contentauthor/app/Article.php @@ -17,6 +17,8 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Iso639p3; @@ -73,27 +75,36 @@ public function render(): string return self::rewriteUploadUrls($this->content); } - public function collaborators() + /** + * @return HasMany + */ + public function collaborators(): HasMany { return $this->hasMany(ArticleCollaborator::class); } - public function files() + /** + * @return HasMany + */ + public function files(): HasMany { return $this->hasMany(File::class); } - public function rewriteUrls($original, $new) + public function rewriteUrls($original, $new): void { $this->content = str_replace($original, $new, $this->content); } - public function givesScore() + public function givesScore(): int { return 0; } - public function parent() + /** + * @return BelongsTo + */ + public function parent(): BelongsTo { return $this->belongsTo(Article::class, 'parent_id'); } @@ -108,12 +119,12 @@ public function getOriginalIdAttribute($originalId) } // Abstract method implementations - protected function getContentContent() + protected function getContentContent(): string { return $this->content; } - protected function getRequestContent(Request $request) + protected function getRequestContent(Request $request): mixed { return $request->get('content'); } @@ -128,7 +139,7 @@ public function getISO6393Language(): string return Iso639p3::code3letters('eng'); } - public function makeCopy($owner = null) + public function makeCopy($owner = null): self { $newArticle = $this->replicate(); $newArticle->id = Uuid::uuid4()->toString(); @@ -154,21 +165,23 @@ public function getContentType(bool $withSubType = false): string return Content::TYPE_ARTICLE; } - public function scopeOfBulkCalculated($query, $type) + /** + * @param Builder $query + */ + public function scopeOfBulkCalculated(Builder $query, $type): void { $query->where('bulk_calculated', $type); } /** - * @param Builder $query + * @param Builder $query */ - public function scopeNoMaxScore($query) + public function scopeNoMaxScore(Builder $query): void { $query->whereNull('max_score'); } - - public function getMaxScoreHelper($content, $haltIfNotCalculated = false) + public function getMaxScoreHelper($content, $haltIfNotCalculated = false): int { $pattern = '/src=.\/lti\/launch\?url=([^"]+)"?/m'; preg_match_all($pattern, $content, $matches, PREG_SET_ORDER); @@ -203,7 +216,7 @@ public function getMaxScoreHelper($content, $haltIfNotCalculated = false) ->sum(); } - public function getMaxScore() + public function getMaxScore(): int { return $this->getMaxScoreHelper($this->content); } @@ -228,7 +241,7 @@ public function setParentVersionId(string $parentVersionId): bool } } - public function setVersionId(string $versionId) + public function setVersionId(string $versionId): void { $this->version_id = $versionId; } @@ -236,9 +249,8 @@ public function setVersionId(string $versionId) /** * Used by Eloquent to get primary key type. * UUID Identified as a string. - * @return string */ - public function getKeyType() + public function getKeyType(): string { return 'string'; } diff --git a/sourcecode/apis/contentauthor/app/Collaborator.php b/sourcecode/apis/contentauthor/app/Collaborator.php index 38667512a7..55d68d18da 100644 --- a/sourcecode/apis/contentauthor/app/Collaborator.php +++ b/sourcecode/apis/contentauthor/app/Collaborator.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\MorphTo; class Collaborator extends Model { @@ -11,7 +12,7 @@ class Collaborator extends Model protected $fillable = ['email']; - public function collaboratable() + public function collaboratable(): MorphTo { return $this->morphTo(); } diff --git a/sourcecode/apis/contentauthor/app/CollaboratorContext.php b/sourcecode/apis/contentauthor/app/CollaboratorContext.php index a98b180d3c..491eed9165 100644 --- a/sourcecode/apis/contentauthor/app/CollaboratorContext.php +++ b/sourcecode/apis/contentauthor/app/CollaboratorContext.php @@ -15,7 +15,7 @@ class CollaboratorContext extends Model public $incrementing = false; public $timestamps = false; - public static function contextShouldUpdate($systemId, $contextId, $timestamp) + public static function contextShouldUpdate($systemId, $contextId, $timestamp): bool { if (!config('feature.context-collaboration', false)) { return false; @@ -27,7 +27,7 @@ public static function contextShouldUpdate($systemId, $contextId, $timestamp) ->doesntExist(); } - public static function deleteContext($systemId, $contextId) + public static function deleteContext($systemId, $contextId): void { if (!config('feature.context-collaboration', false)) { return; @@ -38,7 +38,7 @@ public static function deleteContext($systemId, $contextId) ->delete(); } - public static function updateContext($systemId, $contextId, $collaborators, $resources, $timestamp) + public static function updateContext($systemId, $contextId, $collaborators, $resources, $timestamp): void { if (!config('feature.context-collaboration', false)) { return; @@ -74,10 +74,9 @@ public static function updateContext($systemId, $contextId, $collaborators, $res } /** - * @return bool * @throws Exception */ - public static function isUserCollaborator($collaboratorId, $resourceId) + public static function isUserCollaborator($collaboratorId, $resourceId): bool { if (!config('feature.context-collaboration', false)) { return false; diff --git a/sourcecode/apis/contentauthor/app/Content.php b/sourcecode/apis/contentauthor/app/Content.php index 1930b9abdc..e67a09069d 100644 --- a/sourcecode/apis/contentauthor/app/Content.php +++ b/sourcecode/apis/contentauthor/app/Content.php @@ -20,6 +20,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Http\Request; use Illuminate\Support\Facades\Session; @@ -99,6 +100,9 @@ public function isOwner($currentUserId): bool abstract public function getContentType(bool $withSubType = false); + /** + * @return HasOne + */ public function ndlaMapper(): HasOne { return $this->hasOne(NdlaIdMapper::class, 'ca_id'); @@ -109,7 +113,10 @@ public function isCopyable(): bool return License::isContentCopyable($this->license); } - public function locks() + /** + * @return HasMany + */ + public function locks(): HasMany { return $this->hasMany(ContentLock::class, 'content_id'); } @@ -151,10 +158,9 @@ public function getOwnerName($ownerId): ?string } /** - * @return bool * @throws Exception */ - public function isExternalCollaborator($currentUserId) + public function isExternalCollaborator($currentUserId): bool { if (CollaboratorContext::isUserCollaborator($currentUserId, $this->id)) { return true; @@ -187,7 +193,7 @@ public function canUpdateOriginalResource(mixed $userId): bool return $this->isOwner($userId) || $this->isCollaborator(); } - public function shouldCreateForkBasedOnSession($username = 'authId') + public function shouldCreateForkBasedOnSession($username = 'authId'): bool { return $this->shouldCreateFork(Session::get($username, false)); } @@ -290,12 +296,11 @@ public function unlock() } /** - * @param Builder $query - * @return Builder + * @param Builder $query */ - public function scopeUnversioned($query) + public function scopeUnversioned(Builder $query): void { - return $query->where('version_id', null); + $query->where('version_id', null); } /** @@ -343,7 +348,7 @@ public function isImported(): bool return $ndlaMapperCollection->isNotEmpty(); } - private function getVersionedIds(VersionData $version) + private function getVersionedIds(VersionData $version): array { $id = [$version->getExternalReference()]; if (!is_null($version->getParent())) { @@ -383,9 +388,9 @@ public static function isUserPublishEnabled(): bool return $adapter->isUserPublishEnabled(); } - public function canList(Request $request) + public function canList(Request $request): bool { - if (self::isUserPublishEnabled() !== true || $this->exists === false) { + if (!self::isUserPublishEnabled() || !$this->exists) { return true; } @@ -393,30 +398,24 @@ public function canList(Request $request) return $this->isOwner($authId) || $this->isCollaborator() || $this->isExternalCollaborator($authId); } - public function canPublish(Request $request) + public function canPublish(Request $request): bool { - if (self::isUserPublishEnabled() !== true || $this->exists === false || $request->importRequest ?? false === true) { + if (self::isUserPublishEnabled() || !$this->exists || ($request->importRequest ?? false)) { return true; } return $this->canList($request) || $this->isCopyable(); } - /** - * @param boolean $preview - * @return boolean - */ - public function canShow($preview = false) + public function canShow(bool $preview = false): bool { - return $preview === true || $this->isActuallyPublished(); + return $preview || $this->isActuallyPublished(); } /** - * @return H5PContent|Article|Game|Link|QuestionSet|null - * * Poor mans morphism... */ - public static function findContentById($contentId) + public static function findContentById($contentId): H5PContent|Article|Game|Link|QuestionSet|null { if ((preg_match('/^\d+$/', $contentId) && ($content = H5PContent::find($contentId))) || ($content = Article::find($contentId)) || @@ -426,6 +425,8 @@ public static function findContentById($contentId) ) { return $content; } + + return null; } public function getEditUrl($latest = false): ?string @@ -447,12 +448,12 @@ public function getEditUrl($latest = false): ?string return $editUrl; } - public function getMaxScore() + public function getMaxScore(): int|null { return null; } - public function getAuthorOverwrite() + public function getAuthorOverwrite(): string|null { return null; } diff --git a/sourcecode/apis/contentauthor/app/ContentAttribution.php b/sourcecode/apis/contentauthor/app/ContentAttribution.php index 553825b849..6785c2d11e 100644 --- a/sourcecode/apis/contentauthor/app/ContentAttribution.php +++ b/sourcecode/apis/contentauthor/app/ContentAttribution.php @@ -37,7 +37,7 @@ public function getAttributionAttribute($value): Attribution /** * @throws \Exception */ - public function setAttributionAttribute(Attribution $attribution) + public function setAttributionAttribute(Attribution $attribution): void { $serializedAttribution = json_encode($attribution); diff --git a/sourcecode/apis/contentauthor/app/ContentLanguage.php b/sourcecode/apis/contentauthor/app/ContentLanguage.php index 2df072fd1a..16c09eff79 100644 --- a/sourcecode/apis/contentauthor/app/ContentLanguage.php +++ b/sourcecode/apis/contentauthor/app/ContentLanguage.php @@ -22,7 +22,7 @@ class ContentLanguage extends Model /** * @throws Exception */ - public function setLanguageCodeAttribute($languageCode) + public function setLanguageCodeAttribute($languageCode): void { $languageCode = mb_strtolower($languageCode); diff --git a/sourcecode/apis/contentauthor/app/ContentLanguageLink.php b/sourcecode/apis/contentauthor/app/ContentLanguageLink.php index e30ab95c94..8c3230ef40 100644 --- a/sourcecode/apis/contentauthor/app/ContentLanguageLink.php +++ b/sourcecode/apis/contentauthor/app/ContentLanguageLink.php @@ -2,14 +2,18 @@ namespace App; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class ContentLanguageLink extends Model { protected $fillable = ['main_content_id', 'link_content_id', "language_code", "content_type"]; - public function scopeOfContentType($query, $contentType) + /** + * @param Builder $query + */ + public function scopeOfContentType(Builder $query, $contentType): void { - return $query->where("content_type", $contentType); + $query->where("content_type", $contentType); } } diff --git a/sourcecode/apis/contentauthor/app/ContentLock.php b/sourcecode/apis/contentauthor/app/ContentLock.php index 824b911d5f..2263dde6d7 100644 --- a/sourcecode/apis/contentauthor/app/ContentLock.php +++ b/sourcecode/apis/contentauthor/app/ContentLock.php @@ -2,6 +2,7 @@ namespace App; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Support\Facades\Session; use Carbon\Carbon; @@ -80,8 +81,11 @@ public function getEditor() return "???"; } - public function scopeActive($query) + /** + * @param Builder $query + */ + public function scopeActive(Builder $query): void { - return $query->where('updated_at', '>', Carbon::now()->subSeconds(self::EXPIRES)); + $query->where('updated_at', '>', Carbon::now()->subSeconds(self::EXPIRES)); } } diff --git a/sourcecode/apis/contentauthor/app/File.php b/sourcecode/apis/contentauthor/app/File.php index 681c74f354..70a9813774 100644 --- a/sourcecode/apis/contentauthor/app/File.php +++ b/sourcecode/apis/contentauthor/app/File.php @@ -4,6 +4,7 @@ use App\Libraries\ContentAuthorStorage; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Facades\Storage; use Ramsey\Uuid\Uuid; use Illuminate\Database\Eloquent\Model; @@ -14,24 +15,27 @@ class File extends Model { use HasFactory; - public function article() + /** + * @return BelongsTo + */ + public function article(): BelongsTo { return $this->belongsTo(Article::class); } - public function generatePath() + public function generatePath(): string { $contentAuthorStorage = app(ContentAuthorStorage::class); return $contentAuthorStorage->getAssetUrl(sprintf(ContentStorageSettings::ARTICLE_FILE, $this->article->id, $this->name), true); } - public function generateTempPath() + public function generateTempPath(): string { $contentAuthorStorage = app(ContentAuthorStorage::class); return $contentAuthorStorage->getAssetUrl(sprintf(ContentStorageSettings::ARTICLE_FILE, 'tmp', $this->name), true); } - public function moveTempToArticle(Article $article) + public function moveTempToArticle(Article $article): bool { $moved = false; $fromFile = sprintf(ContentStorageSettings::ARTICLE_FILE, 'tmp', $this->name); @@ -46,7 +50,7 @@ public function moveTempToArticle(Article $article) return $moved; } - public static function moveUploadedFileToTmp(UploadedFile $uploadedFile) + public static function moveUploadedFileToTmp(UploadedFile $uploadedFile): File { $newFile = self::moveUploadedFileTo($uploadedFile, 'tmp'); $newFile->save(); @@ -54,7 +58,7 @@ public static function moveUploadedFileToTmp(UploadedFile $uploadedFile) return $newFile; } - public static function addUploadedFileToArticle(UploadedFile $uploadedFile, Article $article) + public static function addUploadedFileToArticle(UploadedFile $uploadedFile, Article $article): File { $newFile = self::moveUploadedFileTo($uploadedFile, $article->id); $article->files()->save($newFile); @@ -62,7 +66,7 @@ public static function addUploadedFileToArticle(UploadedFile $uploadedFile, Arti return $newFile; } - private static function moveUploadedFileTo(UploadedFile $file, $path = '') + private static function moveUploadedFileTo(UploadedFile $file, $path = ''): File { $fileExtension = $file->getExtension(); if (empty($fileExtension)) { diff --git a/sourcecode/apis/contentauthor/app/Game.php b/sourcecode/apis/contentauthor/app/Game.php index 9eb090a8d0..410af762fe 100644 --- a/sourcecode/apis/contentauthor/app/Game.php +++ b/sourcecode/apis/contentauthor/app/Game.php @@ -6,7 +6,7 @@ use App\Libraries\Games\GameHandler; use App\Libraries\Versioning\VersionableObject; use App\Traits\Collaboratable; -use App\Traits\UuidForKey; +use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Http\Request; @@ -29,7 +29,7 @@ class Game extends Content implements VersionableObject { use Collaboratable; use HasFactory; - use UuidForKey; + use HasUuids; public string $editRouteName = 'game.edit'; /** @@ -59,6 +59,9 @@ public function getISO6393Language(): string return Iso639p3::code3letters('eng'); } + /** + * @return BelongsTo + */ public function gameType(): BelongsTo { return $this->belongsTo(Gametype::class, 'gametype'); @@ -71,20 +74,17 @@ public function getGameSettingsAttribute(string $gameSettings): Object /** - * @return Libraries\Games\Contracts\GameTypeContract * @throws \Exception */ - public function getGameTypeHandler() + public function getGameTypeHandler(): Libraries\Games\Contracts\GameTypeContract { return GameHandler::makeGameTypeFromId($this->gametype); } /** - * @param null|string $owner - * @return Game * @throws \Exception */ - public function makeCopy($owner = null) + public function makeCopy(string|null $owner = null): Game { $game = $this->replicate(); if (!is_null($owner)) { @@ -118,7 +118,7 @@ public function setParentVersionId(string $parentVersionId): bool return false; } - public function setVersionId(string $versionId) + public function setVersionId(string $versionId): void { $this->version_id = $versionId; } diff --git a/sourcecode/apis/contentauthor/app/Gametype.php b/sourcecode/apis/contentauthor/app/Gametype.php index 1723ef27dd..a64e67818f 100644 --- a/sourcecode/apis/contentauthor/app/Gametype.php +++ b/sourcecode/apis/contentauthor/app/Gametype.php @@ -5,10 +5,11 @@ use App\Libraries\ContentAuthorStorage; use App\Libraries\DataObjects\ContentStorageSettings; use App\Libraries\Games\Contracts\GameTypeModelContract; -use App\Traits\UuidForKey; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; /** * @property string $id @@ -22,7 +23,7 @@ class Gametype extends Model implements GameTypeModelContract { use HasFactory; - use UuidForKey; + use HasUuids; private $scripts = [ 'c2runtime.js', @@ -56,44 +57,56 @@ class Gametype extends Model implements GameTypeModelContract ], ]; - public function games() + /** + * @return HasMany + */ + public function games(): HasMany { return $this->hasMany(Game::class, 'gametype'); } - public function scopeOfName($query, $machineName) + /** + * @param Builder $query + */ + public function scopeOfName(Builder $query, $machineName): void { - return $query->where('name', $machineName); + $query->where('name', $machineName); } - public function scopeOfMajorVersion($query, $version) + /** + * @param Builder $query + */ + public function scopeOfMajorVersion(Builder $query, $version): void { - return $query->where('major_version', $version); + $query->where('major_version', $version); } - public function scopeOfMinorVersion($query, $version) + /** + * @param Builder $query + */ + public function scopeOfMinorVersion(Builder $query, $version): void { - return $query->where('minor_version', $version); + $query->where('minor_version', $version); } - public function scopeOfGameType($query, $machineName, $majorVersion, $minorVersion) + /** + * @param Builder $query + */ + public function scopeOfGameType(Builder $query, $machineName, $majorVersion, $minorVersion): void { - $query = $this->scopeOfName($query, $machineName); - $query = $this->scopeOfMajorVersion($query, $majorVersion); - return $this->scopeOfMinorVersion($query, $minorVersion); + $this->scopeOfName($query, $machineName); + $this->scopeOfMajorVersion($query, $majorVersion); + $this->scopeOfMinorVersion($query, $minorVersion); } - public function getVersion() + public function getVersion(): string { return $this->major_version . '.' . $this->minor_version; } // Return the most updated game by version of a machine - /** - * @param string $machineName - */ - public static function mostRecent($machineName = null): self|null + public static function mostRecent(string $machineName = null): self|null { if (!$machineName) { return null; @@ -106,33 +119,33 @@ public static function mostRecent($machineName = null): self|null ->first(); } - public function getScripts() + public function getScripts(): array { return $this->scripts; } - public function getCss() + public function getCss(): array { return $this->css; } - public function getLinks() + public function getLinks(): array { return $this->links; } - public function getPublicFolder() + public function getPublicFolder(): string { $contentAuthorStorage = app(ContentAuthorStorage::class); return $contentAuthorStorage->getAssetUrl(sprintf(ContentStorageSettings::GAMES_PATH, $this->getMachineFolder()), true) . '/'; } - public function getMachineFolder() + public function getMachineFolder(): string { return 'millionaire/' . $this->getVersion() . '/'; } - public function getAssets($type = null) + public function getAssets($type = null): array { $assets = collect(); $machinePath = $this->getMachineFolder(); diff --git a/sourcecode/apis/contentauthor/app/H5PContent.php b/sourcecode/apis/contentauthor/app/H5PContent.php index f2e995e709..4a213e66d0 100644 --- a/sourcecode/apis/contentauthor/app/H5PContent.php +++ b/sourcecode/apis/contentauthor/app/H5PContent.php @@ -14,6 +14,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Http\Request; @@ -72,32 +73,47 @@ public function getTitleCleanAttribute(): string|null return htmlspecialchars_decode($this->title, ENT_HTML5 | ENT_QUOTES); } + /** + * @return HasMany + */ public function collaborators(): HasMany { return $this->hasMany(H5PCollaborator::class, 'h5p_id'); } - public function library() + /** + * @return BelongsTo + */ + public function library(): BelongsTo { return $this->belongsTo(H5PLibrary::class, 'library_id'); } - public function contentUserData() + /** + * @return HasMany + */ + public function contentUserData(): HasMany { return $this->hasMany(H5PContentsUserData::class, 'content_id'); } - public function contentLibraries() + /** + * @return HasMany + */ + public function contentLibraries(): HasMany { return $this->hasMany(H5PContentLibrary::class, 'content_id'); } + /** + * @return HasOne + */ public function metadata(): HasOne { return $this->hasOne(H5PContentsMetadata::class, 'content_id'); } - public function getMetadataStructure() + public function getMetadataStructure(): array { /** @var H5PContentsMetadata $h5pmetadata */ $h5pmetadata = $this->metadata()->first(); @@ -109,7 +125,7 @@ public function getMetadataStructure() return $this->parseStructure($metadataObject); } - public function parseStructure(H5PMetadataObject $metadataObject) + public function parseStructure(H5PMetadataObject $metadataObject): array { return collect(H5PMetadataObject::H5PMetadataFieldsInOrder) ->flip() @@ -127,13 +143,13 @@ public function parseStructure(H5PMetadataObject $metadataObject) } // Abstract method implementations - protected function getContentContent() + protected function getContentContent(): string { $metadata = $this->getMetadataStructure(); return sprintf('{"params":%s,"metadata":%s}', $this->parameters, json_encode($metadata)); } - protected function getRequestContent(Request $request) + protected function getRequestContent(Request $request): string { $parameters = json_decode($request->get('parameters')); if (!empty($parameters->metadata)) { @@ -153,7 +169,7 @@ protected function getRequestContent(Request $request) ]); } - protected function getRequestLibrary(Request $request) + protected function getRequestLibrary(Request $request): string { return $request->get('library'); } @@ -168,7 +184,7 @@ public function getISO6393Language(): string return Iso639p3::code3letters($this->language_iso_639_3 ?? $this->metadata->default_language ?? 'eng'); } - public function makeCopy($owner = null) + public function makeCopy($owner = null): self { $newH5P = $this->replicate(); $newH5P->version_id = null; @@ -188,7 +204,10 @@ public function makeCopy($owner = null) return $newH5P; } - public function contentVideos() + /** + * @return HasMany + */ + public function contentVideos(): HasMany { return $this->hasMany(H5PContentsVideo::class, 'h5p_content_id'); } @@ -230,19 +249,14 @@ public function getContentType($withSubType = false): string return Str::lower($this->library->name); } - /** - * @param Builder $query - */ - protected function noMaxScoreScope($query) + protected function noMaxScoreScope(Builder $query): void { $query ->whereNull('max_score') - ->orWhere(function ($query) { - /** @var Builder $query */ + ->orWhere(function (Builder $query) { $query->where('bulk_calculated', H5PLibraryAdmin::BULK_UNTOUCHED) ->where('max_score', 0) - ->whereIn('library_id', function ($query) { - /** @var Builder $query */ + ->whereIn('library_id', function (\Illuminate\Database\Query\Builder $query) { $query->select('id') ->from('h5p_libraries') ->where('name', QuestionSet::$machineName); @@ -250,15 +264,18 @@ protected function noMaxScoreScope($query) }); } - public function scopeNoMaxScore($query) + /** + * @param Builder $query + */ + public function scopeNoMaxScore(Builder $query): void { $this->noMaxScoreScope($query); } /** - * @param Builder $query + * @param Builder $query */ - public function scopeOfBulkCalculated($query, $type) + public function scopeOfBulkCalculated(Builder $query, $type): void { $query->where('bulk_calculated', $type); } @@ -274,7 +291,7 @@ public function setParentVersionId(string $parentVersionId): bool return false; } - public function setVersionId(string $versionId) + public function setVersionId(string $versionId): void { $this->version_id = $versionId; } @@ -285,17 +302,17 @@ public function getOwnerId(): string } // Overrides Method from trait - public function getPublicId() + public function getPublicId(): string { return "h5p-".$this->id; } - public function getMaxScore() + public function getMaxScore(): int { return $this->max_score; } - public function getAuthorOverwrite() + public function getAuthorOverwrite(): string|null { $contentMetadata = $this->metadata()->first(); if (is_null($contentMetadata)) { diff --git a/sourcecode/apis/contentauthor/app/H5PContentsMetadata.php b/sourcecode/apis/contentauthor/app/H5PContentsMetadata.php index 4340a6db5f..074955d33a 100644 --- a/sourcecode/apis/contentauthor/app/H5PContentsMetadata.php +++ b/sourcecode/apis/contentauthor/app/H5PContentsMetadata.php @@ -5,6 +5,7 @@ use App\Libraries\H5P\Dataobjects\H5PMetadataObject; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * @method static self make(array $attributes = []) @@ -19,7 +20,10 @@ class H5PContentsMetadata extends Model protected $table = 'h5p_contents_metadata'; - public function content() + /** + * @return BelongsTo + */ + public function content(): BelongsTo { return $this->belongsTo(H5PContent::class, 'content_id'); } diff --git a/sourcecode/apis/contentauthor/app/H5PContentsUserData.php b/sourcecode/apis/contentauthor/app/H5PContentsUserData.php index 195ad376d2..90b86e611c 100644 --- a/sourcecode/apis/contentauthor/app/H5PContentsUserData.php +++ b/sourcecode/apis/contentauthor/app/H5PContentsUserData.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; class H5PContentsUserData extends Model { @@ -13,25 +14,28 @@ class H5PContentsUserData extends Model public $timestamps = false; protected $table = "h5p_contents_user_data"; - public function content() + /** + * @return BelongsTo + */ + public function content(): BelongsTo { return $this->belongsTo(H5PContent::class, 'content_id'); } /** - * @param Builder $query + * @param Builder $query */ - public function scopeOfContext($query, string $context) + public function scopeOfContext(Builder $query, string $context): void { - return $this->scopeOfContexts($query, [$context]); + $this->scopeOfContexts($query, [$context]); } /** - * @param Builder $query + * @param Builder $query */ - public function scopeOfContexts($query, array $contexts) + public function scopeOfContexts(Builder $query, array $contexts): void { - return $query->whereIn('context', array_map(function ($context) { + $query->whereIn('context', array_map(function ($context) { return trim($context); }, $contexts)); } diff --git a/sourcecode/apis/contentauthor/app/H5PContentsVideo.php b/sourcecode/apis/contentauthor/app/H5PContentsVideo.php index 1c37d5febc..59d9dc6438 100644 --- a/sourcecode/apis/contentauthor/app/H5PContentsVideo.php +++ b/sourcecode/apis/contentauthor/app/H5PContentsVideo.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; class H5PContentsVideo extends Model { @@ -17,7 +18,10 @@ class H5PContentsVideo extends Model 'source_file' ]; - public function content() + /** + * @return BelongsTo + */ + public function content(): BelongsTo { return $this->belongsTo(H5PContent::class); } diff --git a/sourcecode/apis/contentauthor/app/H5PFile.php b/sourcecode/apis/contentauthor/app/H5PFile.php index a95c0b4c6f..df517397df 100644 --- a/sourcecode/apis/contentauthor/app/H5PFile.php +++ b/sourcecode/apis/contentauthor/app/H5PFile.php @@ -29,46 +29,22 @@ public function getParamsAttribute($value) } /** - * @param Builder $query - * @param string $requestId + * @param Builder $query */ - protected function getFileUploadStatusFromRequestIdScope($query, $requestId) + public function scopeOfFileUploadFromRequestId(Builder $query, $requestId): void { $query->where('requestId', $requestId); } /** - * @param Builder $query - * @param string $requestId + * @param Builder $query */ - public function scopeOfFileUploadFromRequestId($query, $requestId) - { - return $this->getFileUploadStatusFromRequestIdScope($query, $requestId); - } - - /** - * @param Builder $query - * @param int $contentId - */ - protected function getFileUploadStatusFromContentScope($query, $contentId) + public function scopeOfFileUploadFromContent(Builder $query, int $contentId): void { $query->where('content_id', $contentId); } - /** - * @param Builder $query - * @param int $contentId - */ - public function scopeOfFileUploadFromContent($query, $contentId) - { - return $this->getFileUploadStatusFromContentScope($query, $contentId); - } - - /** - * @param int $contentId - * @param string $filePath - */ - protected function deleteContentPendingUpload($contentId, $filePath) + protected function deleteContentPendingUpload(int $contentId, string $filePath): void { self::ofFileUploadFromContent($contentId) ->get() diff --git a/sourcecode/apis/contentauthor/app/H5PLibrariesHubCache.php b/sourcecode/apis/contentauthor/app/H5PLibrariesHubCache.php index e24b1dd307..895e297860 100644 --- a/sourcecode/apis/contentauthor/app/H5PLibrariesHubCache.php +++ b/sourcecode/apis/contentauthor/app/H5PLibrariesHubCache.php @@ -4,6 +4,7 @@ use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; /** * @property string $title @@ -34,7 +35,10 @@ public function getUpdatedAtAttribute($value) return Carbon::parse($value)->getTimestamp(); } - public function libraries() + /** + * @return HasMany + */ + public function libraries(): HasMany { return $this->hasMany(H5PLibrary::class, 'name', 'name'); } diff --git a/sourcecode/apis/contentauthor/app/H5PLibrary.php b/sourcecode/apis/contentauthor/app/H5PLibrary.php index a5d070008a..b0577e85e7 100644 --- a/sourcecode/apis/contentauthor/app/H5PLibrary.php +++ b/sourcecode/apis/contentauthor/app/H5PLibrary.php @@ -36,7 +36,7 @@ class H5PLibrary extends Model protected $guarded = ['id']; - protected static function boot() + protected static function boot(): void { parent::boot(); @@ -51,17 +51,26 @@ public function getMachineNameAttribute() return $this->name; } - public function capability() + /** + * @return HasOne + */ + public function capability(): HasOne { return $this->hasOne(H5PLibraryCapability::class, 'library_id'); } + /** + * @return HasOne + */ public function description(): HasOne { return $this->hasOne(LibraryDescription::class, 'library_id'); } - public function contents() + /** + * @return HasMany + */ + public function contents(): HasMany { return $this->hasMany(H5PContent::class, 'library_id'); } @@ -71,38 +80,56 @@ public function contentsWithNoScore() return $this->contents()->whereNull('max_score'); } - public function languages() + /** + * @return HasMany + */ + public function languages(): HasMany { return $this->hasMany(H5PLibraryLanguage::class, 'library_id'); } + /** + * @return HasMany + */ public function libraries(): HasMany { return $this->hasMany(H5PLibraryLibrary::class, 'library_id'); } - public function scopeFromMachineName($query, $machineName) + /** + * @param Builder $query + */ + public function scopeFromMachineName(Builder $query, $machineName): void { - return $query->where('name', $machineName); + $query->where('name', $machineName); } - public function scopeLatestVersion($query) + /** + * @param Builder $query + */ + public function scopeLatestVersion(Builder $query): void { - return $query->orderBy('major_version', 'DESC') + $query->orderBy('major_version', 'DESC') ->orderBy('minor_version', 'DESC') ->limit(1); } - public function scopeVersion($query, $majorVersion, $minorVersion) + /** + * @param Builder $query + */ + public function scopeVersion(Builder $query, $majorVersion, $minorVersion): void { - return $query + $query ->where('major_version', $majorVersion) ->where('minor_version', $minorVersion); } - public function scopeRunnable($query) + /** + * @param Builder $query + */ + public function scopeRunnable(Builder $query): void { - return $query->where('runnable', 1); + $query->where('runnable', 1); } public function getVersions($asModels = false) @@ -136,10 +163,13 @@ public function getTitleAndVersionString() return \H5PCore::libraryToString($this->getLibraryH5PFriendly('title')); } - public function scopeFromLibrary($query, $value) + /** + * @param Builder $query + */ + public function scopeFromLibrary(Builder $query, array $value): void { list($machineName, $majorVersion, $minorVersion) = array_values($value); - return $query->where('name', $machineName) + $query->where('name', $machineName) ->where('major_version', $majorVersion) ->where('minor_version', $minorVersion); } @@ -166,17 +196,17 @@ public function getUpgrades($toArray = true) return $toArray === true ? $upgradeVersions->toArray() : $upgradeVersions; } - public function isUpgradable() + public function isUpgradable(): bool { return $this->getUpgrades(false)->isNotEmpty() && $this->contents()->count() > 0; } - public function isLibraryTypeIdentical(H5PLibrary $comparingLibrary) + public function isLibraryTypeIdentical(H5PLibrary $comparingLibrary): bool { return $this->name === $comparingLibrary->name; } - public function isLibraryNewer(H5PLibrary $compareLibrary) + public function isLibraryNewer(H5PLibrary $compareLibrary): bool { return $this->getUpgrades(false) ->filter(function ($library) use ($compareLibrary) { diff --git a/sourcecode/apis/contentauthor/app/H5PLibraryCapability.php b/sourcecode/apis/contentauthor/app/H5PLibraryCapability.php index bd5947c685..baab8608d3 100644 --- a/sourcecode/apis/contentauthor/app/H5PLibraryCapability.php +++ b/sourcecode/apis/contentauthor/app/H5PLibraryCapability.php @@ -2,7 +2,9 @@ namespace App; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Facades\Lang; class H5PLibraryCapability extends Model @@ -11,17 +13,23 @@ class H5PLibraryCapability extends Model protected $appends = ['title', 'description']; - public function library() + /** + * @return BelongsTo + */ + public function library(): BelongsTo { return $this->belongsTo(H5PLibrary::class); } - public function scopeActive($query) + /** + * @param Builder $query + */ + public function scopeActive(Builder $query): void { - return $query->where('enabled', 1); + $query->where('enabled', 1); } - public function getTitleAttribute() + public function getTitleAttribute(): string { $locale = Lang::getLocale(); $trans = LibraryDescription::where('locale', $locale)->where('library_id', $this->library_id)->first(); @@ -34,7 +42,7 @@ public function getTitleAttribute() return $trans->title; } - public function getDescriptionAttribute() + public function getDescriptionAttribute(): string { $locale = Lang::getLocale(); $trans = LibraryDescription::where('locale', $locale)->where('library_id', $this->library_id)->first(); diff --git a/sourcecode/apis/contentauthor/app/H5PLibraryLanguage.php b/sourcecode/apis/contentauthor/app/H5PLibraryLanguage.php index 7fdf725d0c..d58e53d531 100644 --- a/sourcecode/apis/contentauthor/app/H5PLibraryLanguage.php +++ b/sourcecode/apis/contentauthor/app/H5PLibraryLanguage.php @@ -2,7 +2,9 @@ namespace App; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; class H5PLibraryLanguage extends Model { @@ -16,15 +18,22 @@ class H5PLibraryLanguage extends Model public $timestamps = false; - public function library() + /** + * @return BelongsTo + */ + public function library(): BelongsTo { return $this->belongsTo(H5PLibrary::class); } - public function scopeFromLibrary($query, $library) + /** + * @param Builder $query + */ + public function scopeFromLibrary(Builder $query, array $library): void { list($machineName, $majorVersion, $minorVersion) = array_values($library); - $query->whereHas('library', function ($query) use ($machineName, $majorVersion, $minorVersion) { + $query->whereHas('library', function (Builder $query) use ($machineName, $majorVersion, $minorVersion) { + /** @var Builder $query */ $query->fromLibrary([$machineName, $majorVersion, $minorVersion]); }); } diff --git a/sourcecode/apis/contentauthor/app/H5PLibraryLibrary.php b/sourcecode/apis/contentauthor/app/H5PLibraryLibrary.php index b9664cabe0..e69fbf01a8 100644 --- a/sourcecode/apis/contentauthor/app/H5PLibraryLibrary.php +++ b/sourcecode/apis/contentauthor/app/H5PLibraryLibrary.php @@ -19,11 +19,17 @@ class H5PLibraryLibrary extends Model public $timestamps = false; + /** + * @return BelongsTo + */ public function library(): BelongsTo { return $this->belongsTo(H5PLibrary::class); } + /** + * @return HasOne + */ public function requiredLibrary(): HasOne { return $this->hasOne(H5PLibrary::class, 'id', 'required_library_id'); diff --git a/sourcecode/apis/contentauthor/app/Http/Controllers/EmbedController.php b/sourcecode/apis/contentauthor/app/Http/Controllers/EmbedController.php index 24ddcabd6d..9d3dfd2657 100644 --- a/sourcecode/apis/contentauthor/app/Http/Controllers/EmbedController.php +++ b/sourcecode/apis/contentauthor/app/Http/Controllers/EmbedController.php @@ -44,8 +44,7 @@ public function create(Request $request) $licenses = License::getLicenses($ltiRequest); $license = License::getDefaultLicense($ltiRequest); $emails = ''; - /** @var Link $link */ - $link = app(Link::class); + $link = new Link(); $redirectToken = $request->get('redirectToken'); $userPublishEnabled = false; $canPublish = true; diff --git a/sourcecode/apis/contentauthor/app/Http/Controllers/H5PController.php b/sourcecode/apis/contentauthor/app/Http/Controllers/H5PController.php index 0aa2cecf1a..983ffd4762 100644 --- a/sourcecode/apis/contentauthor/app/Http/Controllers/H5PController.php +++ b/sourcecode/apis/contentauthor/app/Http/Controllers/H5PController.php @@ -105,6 +105,7 @@ public function doShow($id, $context, $preview = false): View ->setContext($context) ->loadContent($id) ->setAlterParameterSettings(H5PAlterParametersSettingsDataObject::create(['useImageWidth' => $h5pContent->library->includeImageWidth()])); + $h5pView = $this->h5p->createView($viewConfig); $content = $viewConfig->getContent(); $settings = $h5pView->getSettings(); @@ -155,8 +156,8 @@ public function create(Request $request, H5PCore $core, $contenttype = null): Vi ->setUserName(Session::get('name', false)) ->setDisplayHub(empty($contenttype)) ->setRedirectToken($request->input('redirectToken')) - ->setDisplayHub(empty($contenttype)) ->setLanguage(Iso639p3::code2letters($language)); + $h5pView = $this->h5p->createView($editorConfig); $jwtTokenInfo = Session::get('jwtToken', null); @@ -252,6 +253,7 @@ public function edit(Request $request, int $id): View ->setRedirectToken($request->input('redirectToken')) ->setLanguage(LtiToH5PLanguage::convert(Session::get('locale'))) ->loadContent($id); + $h5pView = $this->h5p->createView($editorConfig); $content = $editorConfig->getContent(); diff --git a/sourcecode/apis/contentauthor/app/Http/Controllers/LinkController.php b/sourcecode/apis/contentauthor/app/Http/Controllers/LinkController.php index f2b691a6a2..dadf9aac53 100644 --- a/sourcecode/apis/contentauthor/app/Http/Controllers/LinkController.php +++ b/sourcecode/apis/contentauthor/app/Http/Controllers/LinkController.php @@ -50,7 +50,7 @@ public function create(Request $request) $license = License::getDefaultLicense($ltiRequest); $emails = ''; - $link = app(Link::class); + $link = new Link(); $redirectToken = $request->get('redirectToken'); $userPublishEnabled = $adapter->isUserPublishEnabled(); $canPublish = true; @@ -72,8 +72,7 @@ public function store(LinksRequest $request): JsonResponse $inputs = $request->all(); $metadata = json_decode($inputs['linkMetadata']); - /** @var Link $link */ - $link = app(Link::class); + $link = new Link(); $link->link_type = $inputs['linkType']; $link->link_url = $inputs['linkUrl']; $link->owner_id = Session::get('authId'); @@ -146,8 +145,7 @@ public function edit(Request $request, $id) public function update(LinksRequest $request, $id) { - /** @var Link $link */ - $link = app(Link::class); + $link = new Link(); $oldLink = $link::findOrFail($id); if (!$this->canCreate()) { @@ -178,7 +176,6 @@ public function update(LinksRequest $request, $id) $link = $oldLink->makeCopy(Session::get('authId')); break; } - $link->setParentId($oldLink->version_id); } $metadata = json_decode($inputs['linkMetadata']); diff --git a/sourcecode/apis/contentauthor/app/Libraries/H5P/Adapters/CerpusH5PAdapter.php b/sourcecode/apis/contentauthor/app/Libraries/H5P/Adapters/CerpusH5PAdapter.php index c74c26e98b..6f55d283f4 100644 --- a/sourcecode/apis/contentauthor/app/Libraries/H5P/Adapters/CerpusH5PAdapter.php +++ b/sourcecode/apis/contentauthor/app/Libraries/H5P/Adapters/CerpusH5PAdapter.php @@ -44,7 +44,7 @@ public function getEditorSettings(): array public function getCustomEditorScripts(): array { - return ['/js/videos/streamps.js', asset('js/videos/brightcove.js')]; + return ['/js/videos/streamps.js', '/js/videos/brightcove.js']; } diff --git a/sourcecode/apis/contentauthor/app/Libraries/H5P/Adapters/NDLAH5PAdapter.php b/sourcecode/apis/contentauthor/app/Libraries/H5P/Adapters/NDLAH5PAdapter.php index 0f71981209..9c2ea8a515 100644 --- a/sourcecode/apis/contentauthor/app/Libraries/H5P/Adapters/NDLAH5PAdapter.php +++ b/sourcecode/apis/contentauthor/app/Libraries/H5P/Adapters/NDLAH5PAdapter.php @@ -198,9 +198,10 @@ public function getCustomViewCss(): array { $css = []; $ndlaCustomCssOption = H5POption::where('option_name', H5POption::NDLA_CUSTOM_CSS_TIMESTAMP)->first(); - if ($ndlaCustomCssOption && !empty($this->config->content)) { + $content = $this->config->getContent(); + if ($ndlaCustomCssOption && !empty($content)) { $customCssBreakpoint = Carbon::parse($ndlaCustomCssOption->option_value); - $updated = $this->config->content['updated_at']; + $updated = $content['updated_at']; if ($customCssBreakpoint > $updated) { $css[] = (string) mix('css/ndlah5p-iframe-legacy.css'); } @@ -254,6 +255,14 @@ public function overrideAdapterSettings() 'feature.collaboration', 'feature.export_h5p_on_save', 'export_h5p_with_local_files', + 'h5p.video.enable', + 'h5p.video.url', + 'h5p.video.key', + 'h5p.video.secret', + 'h5p.video.accountId', + 'h5p.video.authUrl', + 'h5p.video.deleteVideoSourceAfterConvertToStream', + 'h5p.video.pingDelay', 'h5p.image.authDomain', 'h5p.image.key', 'h5p.image.secret', diff --git a/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PConfigAbstract.php b/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PConfigAbstract.php index a20fd8e61a..134fcf8d35 100644 --- a/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PConfigAbstract.php +++ b/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PConfigAbstract.php @@ -14,7 +14,7 @@ abstract class H5PConfigAbstract implements ConfigInterface { - protected const CACHE_BUSTER_STRING = '2.0.3'; + public const CACHE_BUSTER_STRING = '2.0.3'; protected const EMBED_TEMPLATE = ''; public function __construct( diff --git a/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PCreateConfig.php b/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PCreateConfig.php index 0fb5326fd6..28b51ac503 100644 --- a/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PCreateConfig.php +++ b/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PCreateConfig.php @@ -33,6 +33,11 @@ public function __construct(H5PAdapterInterface $adapter, \H5PCore $h5pCore) $this->config['ajax']['contentUserData'] = '/api/progress?action=h5p_preview&c=1'; $this->config['ajax']['setFinished'] = '/api/progress?action=h5p_preview&f=1'; + $editorSettings = $this->adapter->getEditorSettings(); + if (!empty($editorSettings)) { + $this->editorConfig = array_merge($this->editorConfig, $editorSettings); + } + $this->addCoreAssets(); $this->addDefaultEditorAssets(); $this->addCustomEditorStyles(); @@ -48,6 +53,7 @@ protected function addInheritorConfig(): void { $this->editorConfig['language'] = $this->language ?? 'en'; $this->editorConfig['ajaxPath'] = sprintf("/ajax?redirectToken=%s&h5p_id=&action=", $this->redirectToken); + $this->config['editor'] = (object) $this->editorConfig; } } diff --git a/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PEditConfig.php b/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PEditConfig.php index 477aaa546f..243eef2ba3 100644 --- a/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PEditConfig.php +++ b/sourcecode/apis/contentauthor/app/Libraries/H5P/H5PEditConfig.php @@ -37,6 +37,11 @@ public function __construct(H5PAdapterInterface $adapter, \H5PCore $h5pCore) $this->config['ajax']['contentUserData'] = '/api/progress?action=h5p_preview&c=1'; $this->config['ajax']['setFinished'] = '/api/progress?action=h5p_preview&f=1'; + $editorSettings = $this->adapter->getEditorSettings(); + if (!empty($editorSettings)) { + $this->editorConfig = array_merge($this->editorConfig, $editorSettings); + } + $this->addCoreAssets(); $this->addDefaultEditorAssets(); $this->addCustomEditorStyles(); @@ -58,6 +63,7 @@ protected function addInheritorConfig(): void if ($this->content) { $this->editorConfig['ajaxPath'] = sprintf("/ajax?redirectToken=%s&h5p_id=%s&action=", $this->redirectToken, $this->content['id']); } + $this->config['editor'] = (object) $this->editorConfig; } } diff --git a/sourcecode/apis/contentauthor/app/LibraryDescription.php b/sourcecode/apis/contentauthor/app/LibraryDescription.php index 67accbb325..3d5f9e915e 100644 --- a/sourcecode/apis/contentauthor/app/LibraryDescription.php +++ b/sourcecode/apis/contentauthor/app/LibraryDescription.php @@ -3,12 +3,16 @@ namespace App; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; class LibraryDescription extends Model { protected $appends = ['capability_id']; - public function library() + /** + * @return BelongsTo + */ + public function library(): BelongsTo { return $this->belongsTo(H5PLibrary::class); } diff --git a/sourcecode/apis/contentauthor/app/Link.php b/sourcecode/apis/contentauthor/app/Link.php index ad43a3b668..e20ad2e242 100644 --- a/sourcecode/apis/contentauthor/app/Link.php +++ b/sourcecode/apis/contentauthor/app/Link.php @@ -3,9 +3,10 @@ namespace App; use App\Libraries\Versioning\VersionableObject; -use App\Traits\UuidForKey; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Http\Request; use Iso639p3; @@ -20,29 +21,23 @@ * * @property Collection $collaborators * - * @method Link replicate(array $except = null) - * * @method static self find($id, $columns = ['*']) * @method static self findOrFail($id, $columns = ['*']) */ class Link extends Content implements VersionableObject { use HasFactory; - use UuidForKey; - - private $parentId; - - public function setParentId($parentId) - { - $this->parentId = $parentId; - } + use HasUuids; - public function givesScore() + public function givesScore(): int { return 0; } - public function collaborators() + /** + * @return HasMany + */ + public function collaborators(): HasMany { return $this->hasMany(ArticleCollaborator::class, 'article_id'); } @@ -57,7 +52,7 @@ public function getISO6393Language(): string return Iso639p3::code3letters('eng'); } - public function makeCopy($owner = null) + public function makeCopy($owner = null): static { $newLink = $this->replicate(); //$newLink->id = Uuid::uuid4()->toString(); @@ -99,12 +94,12 @@ public function setParentVersionId(string $parentVersionId): bool return false; // Not stored } - public function setVersionId(string $versionId) + public function setVersionId(string $versionId): void { $this->version_id = $versionId; } - public function getIsPrivateAttribute() + public function getIsPrivateAttribute(): false { return false; // Defaults to public / listed } diff --git a/sourcecode/apis/contentauthor/app/NdlaArticleId.php b/sourcecode/apis/contentauthor/app/NdlaArticleId.php index 00c0cdb5f5..9710bdbe72 100644 --- a/sourcecode/apis/contentauthor/app/NdlaArticleId.php +++ b/sourcecode/apis/contentauthor/app/NdlaArticleId.php @@ -3,6 +3,7 @@ namespace App; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; class NdlaArticleId extends Model { @@ -13,12 +14,15 @@ public function getJsonAttribute($value) return json_decode($value); } - public function setJsonAttribute($value) + public function setJsonAttribute($value): void { $this->attributes['json'] = json_encode($value); } - public function messages() + /** + * @return HasMany + */ + public function messages(): HasMany { return $this->hasMany(NdlaArticleImportStatus::class, 'ndla_id'); } diff --git a/sourcecode/apis/contentauthor/app/NdlaArticleImportStatus.php b/sourcecode/apis/contentauthor/app/NdlaArticleImportStatus.php index 4f1fc6d67b..f28ccb073a 100644 --- a/sourcecode/apis/contentauthor/app/NdlaArticleImportStatus.php +++ b/sourcecode/apis/contentauthor/app/NdlaArticleImportStatus.php @@ -3,6 +3,7 @@ namespace App; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * @todo remove @@ -37,12 +38,15 @@ public static function mostRecentStatuses() return self::orderBy('id', 'desc')->limit(500)->get(); } - public function ndlaArticle() + /** + * @return BelongsTo + */ + public function ndlaArticle(): BelongsTo { return $this->belongsTo(NdlaArticleId::class, 'ndla_id'); } - public static function addStatus($id, $message, $importId = null, $logLevel = self::LOG_LEVEL_DEBUG) + public static function addStatus($id, $message, $importId = null, $logLevel = self::LOG_LEVEL_DEBUG): self { $status = [ 'ndla_id' => $id, @@ -59,12 +63,12 @@ public static function addStatus($id, $message, $importId = null, $logLevel = se return $response; } - public static function logDebug($id, $message, $importId = null) + public static function logDebug($id, $message, $importId = null): self { return self::addStatus($id, $message, $importId, self::LOG_LEVEL_DEBUG); } - public static function logError($id, $message, $importId = null) + public static function logError($id, $message, $importId = null): self { return self::addStatus($id, $message, $importId, self::LOG_LEVEL_ERROR); } diff --git a/sourcecode/apis/contentauthor/app/NdlaIdMapper.php b/sourcecode/apis/contentauthor/app/NdlaIdMapper.php index b764395365..7d41b0392e 100644 --- a/sourcecode/apis/contentauthor/app/NdlaIdMapper.php +++ b/sourcecode/apis/contentauthor/app/NdlaIdMapper.php @@ -2,8 +2,10 @@ namespace App; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Query\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * @property int|null $metadata_fetch @@ -22,7 +24,7 @@ class NdlaIdMapper extends Model 'language_code', ]; - public function getOerLink() + public function getOerLink(): string|false { if (!empty($this->launch_url)) { return route("lti.launch", [], false) . "?" . http_build_query(['url' => $this->launch_url]); @@ -42,32 +44,32 @@ public function getOerLink() return $url; } - public static function byNdlaId($id) + public static function byNdlaId($id): ?self { return self::where('ndla_id', $id)->first(); } - public static function articleByNdlaId($id) + public static function articleByNdlaId($id): ?self { return self::where('ndla_id', $id)->where('type', 'article')->first(); } - public static function articlesByNdlaId($id) + public static function articlesByNdlaId($id): Collection { return self::where('ndla_id', $id)->where('type', 'article')->get(); } - public static function h5pByNdlaId($id) + public static function h5pByNdlaId($id): ?self { return self::where('ndla_id', $id)->where('type', 'h5p')->first(); } - public static function byNdlaIdAndLanguage($id, $language) + public static function byNdlaIdAndLanguage($id, $language): ?self { return self::where('ndla_id', $id)->where('language_code', $language)->first(); } - public static function articleByNdlaIdAndLanguage($id, $language) + public static function articleByNdlaIdAndLanguage($id, $language): ?self { return self::where('ndla_id', $id) ->where('language_code', $language) @@ -75,7 +77,7 @@ public static function articleByNdlaIdAndLanguage($id, $language) ->first(); } - public static function h5pByNdlaIdAndLanguage($id, $language) + public static function h5pByNdlaIdAndLanguage($id, $language): ?self { return self::where('ndla_id', $id) ->where('language_code', $language) @@ -83,35 +85,38 @@ public static function h5pByNdlaIdAndLanguage($id, $language) ->first(); } - public static function byNdlaChecksum($checksum) + public static function byNdlaChecksum($checksum): ?self { return self::where('ndla_checksum', $checksum)->latest()->first(); } - public function scopeH5P($query) + /** + * @param Builder $query + */ + public function scopeH5P(Builder $query): void { - return $query->where('type', 'h5p'); + $query->where('type', 'h5p'); } - public function h5pContents() + /** + * @return BelongsTo + */ + public function h5pContents(): BelongsTo { return $this->belongsTo(H5PContent::class, 'ca_id'); } /** - * @param \Illuminate\Database\Eloquent\Builder $query - * @return \Illuminate\Database\Eloquent\Builder + * @param Builder $query */ - public function scopeWithH5PMetadata($query) + public function scopeWithH5PMetadata(Builder $query): void { $query ->with('h5pContents.metadata') ->h5p() ->whereNull('metadata_fetch') - ->where(function ($query) { - /** @var \Illuminate\Database\Eloquent\Builder $query */ - $query->whereHas('h5pContents.metadata', function ($query) { - /** @var \Illuminate\Database\Eloquent\Builder $query */ + ->where(function (Builder $query) { + $query->whereHas('h5pContents.metadata', function (Builder $query) { $query->whereNull('license') ->orWhereNull('authors') ->orWhere('authors', '[]') @@ -119,16 +124,18 @@ public function scopeWithH5PMetadata($query) }) ->orDoesntHave('h5pContents.metadata'); }); - return $query; } - public static function byLaunchUrl($url) + public static function byLaunchUrl($url): ?self { return self::where('launch_url', $url)->first(); } - public function scopeArticle($query) + /** + * @param Builder $query + */ + public function scopeArticle(Builder $query): void { - return $query->where('type', 'article'); + $query->where('type', 'article'); } } diff --git a/sourcecode/apis/contentauthor/app/QuestionSet.php b/sourcecode/apis/contentauthor/app/QuestionSet.php index 6eb2fea48d..1085b36eef 100644 --- a/sourcecode/apis/contentauthor/app/QuestionSet.php +++ b/sourcecode/apis/contentauthor/app/QuestionSet.php @@ -4,9 +4,10 @@ use App\Libraries\DataObjects\ContentTypeDataObject; use App\Traits\Collaboratable; -use App\Traits\UuidForKey; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Http\Request; use Iso639p3; @@ -24,22 +25,25 @@ class QuestionSet extends Content { use Collaboratable; use HasFactory; - use UuidForKey; + use HasUuids; public string $editRouteName = 'questionset.edit'; - public function questions() + /** + * @return HasMany + */ + public function questions(): HasMany { return $this->hasMany(QuestionSetQuestion::class)->ordered(); } - protected function getRequestContent(Request $request) + protected function getRequestContent(Request $request): true { // TODO: Implement getRequestContent() method. return true; } - protected function getContentContent() + protected function getContentContent(): true { // TODO: Implement getContentContent() method. return true; diff --git a/sourcecode/apis/contentauthor/app/QuestionSetQuestion.php b/sourcecode/apis/contentauthor/app/QuestionSetQuestion.php index 63c725334d..e54fa0f688 100644 --- a/sourcecode/apis/contentauthor/app/QuestionSetQuestion.php +++ b/sourcecode/apis/contentauthor/app/QuestionSetQuestion.php @@ -2,10 +2,13 @@ namespace App; -use App\Traits\UuidForKey; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; /** * @property string $id @@ -18,19 +21,28 @@ class QuestionSetQuestion extends Model { use HasFactory; - use UuidForKey; + use HasUuids; - public function questionset() + /** + * @return BelongsTo + */ + public function questionset(): BelongsTo { return $this->belongsTo(QuestionSet::class); } - public function scopeOrdered($query) + /** + * @param Builder $query + */ + public function scopeOrdered(Builder $query): void { - return $query->orderBy('order'); + $query->orderBy('order'); } - public function answers() + /** + * @return HasMany + */ + public function answers(): HasMany { return $this->hasMany(QuestionSetQuestionAnswer::class, 'question_id')->ordered(); } diff --git a/sourcecode/apis/contentauthor/app/QuestionSetQuestionAnswer.php b/sourcecode/apis/contentauthor/app/QuestionSetQuestionAnswer.php index e6a6666fc9..afcb2e751f 100644 --- a/sourcecode/apis/contentauthor/app/QuestionSetQuestionAnswer.php +++ b/sourcecode/apis/contentauthor/app/QuestionSetQuestionAnswer.php @@ -2,7 +2,8 @@ namespace App; -use App\Traits\UuidForKey; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -15,16 +16,18 @@ class QuestionSetQuestionAnswer extends Model { use HasFactory; - use UuidForKey; + use HasUuids; public function question() { return $this->belongsTo(QuestionSetQuestion::class, 'question_id')->ordered(); } - public function scopeOrdered($query) + /** + * @param Builder $query + */ + public function scopeOrdered(Builder $query): void { $query->orderBy('order'); - return $query; } } diff --git a/sourcecode/apis/contentauthor/app/Traits/HasLanguage.php b/sourcecode/apis/contentauthor/app/Traits/HasLanguage.php index d3ec0511d6..5ca4ca5cbc 100644 --- a/sourcecode/apis/contentauthor/app/Traits/HasLanguage.php +++ b/sourcecode/apis/contentauthor/app/Traits/HasLanguage.php @@ -2,6 +2,7 @@ namespace App\Traits; +use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Support\Facades\Session; use App\ContentLanguage; @@ -10,7 +11,10 @@ */ trait HasLanguage { - public function language() + /** + * @return HasOne + */ + public function language(): HasOne { return $this->hasOne(ContentLanguage::class, 'content_id'); } diff --git a/sourcecode/apis/contentauthor/app/Traits/UuidForKey.php b/sourcecode/apis/contentauthor/app/Traits/UuidForKey.php deleted file mode 100644 index a72dd5094c..0000000000 --- a/sourcecode/apis/contentauthor/app/Traits/UuidForKey.php +++ /dev/null @@ -1,43 +0,0 @@ -keyType = 'string'; - $model->incrementing = false; - - /** @var Model $model */ - $primaryKey = $model->getKeyName(); - if ($model->isFillable($primaryKey) === false || empty($model->{$primaryKey})) { - $model->{$primaryKey} = Uuid::uuid4()->toString(); - } - }); - } -} diff --git a/sourcecode/apis/contentauthor/composer.json b/sourcecode/apis/contentauthor/composer.json index 9b5adb50e8..be9b5acc0e 100644 --- a/sourcecode/apis/contentauthor/composer.json +++ b/sourcecode/apis/contentauthor/composer.json @@ -48,6 +48,7 @@ }, "require-dev": { "barryvdh/laravel-ide-helper": "^2.10", + "ekino/phpstan-banned-code": "^1.0", "fakerphp/faker": "^1.16", "mockery/mockery": "^1.0", "nunomaduro/larastan": "^2.0", diff --git a/sourcecode/apis/contentauthor/composer.lock b/sourcecode/apis/contentauthor/composer.lock index e3b70b5acf..b4762e51d0 100644 --- a/sourcecode/apis/contentauthor/composer.lock +++ b/sourcecode/apis/contentauthor/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5bad76ecae7092883dc8eda732e02555", + "content-hash": "f8f90b383667fa459cb93c1d1c6f8360", "packages": [ { "name": "auth0/auth0-php", @@ -9508,6 +9508,71 @@ ], "time": "2022-12-30T00:23:10+00:00" }, + { + "name": "ekino/phpstan-banned-code", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/ekino/phpstan-banned-code.git", + "reference": "4f0d7c8a0c9f5d222ffc24234aa6c5b3b71bf4c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ekino/phpstan-banned-code/zipball/4f0d7c8a0c9f5d222ffc24234aa6c5b3b71bf4c3", + "reference": "4f0d7c8a0c9f5d222ffc24234aa6c5b3b71bf4c3", + "shasum": "" + }, + "require": { + "php": "^7.3 || ^8.0", + "phpstan/phpstan": "^1.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.6", + "friendsofphp/php-cs-fixer": "^3.0", + "nikic/php-parser": "^4.3", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/var-dumper": "^5.0" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Ekino\\PHPStanBannedCode\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "RĂ©mi Marseille", + "email": "remi.marseille@ekino.com", + "homepage": "https://www.ekino.com" + } + ], + "description": "Detected banned code using PHPStan", + "homepage": "https://github.com/ekino/phpstan-banned-code", + "keywords": [ + "PHPStan", + "code quality" + ], + "support": { + "issues": "https://github.com/ekino/phpstan-banned-code/issues", + "source": "https://github.com/ekino/phpstan-banned-code/tree/v1.0.0" + }, + "time": "2021-11-02T08:37:34+00:00" + }, { "name": "fakerphp/faker", "version": "v1.21.0", diff --git a/sourcecode/apis/contentauthor/config/ndla-mode.php b/sourcecode/apis/contentauthor/config/ndla-mode.php index 400b76cc4e..d535e5543f 100644 --- a/sourcecode/apis/contentauthor/config/ndla-mode.php +++ b/sourcecode/apis/contentauthor/config/ndla-mode.php @@ -38,6 +38,16 @@ 'audience' => env("NDLA_H5P_IMAGE_AUDIENCE"), 'url' => env("NDLA_H5P_IMAGE_URL"), ], + 'video' => [ + 'enable' => env("NDLA_H5P_VIDEO_STREAM_ENABLED", true), + 'url' => env("NDLA_H5P_VIDEO_URL"), + 'key' => env("NDLA_H5P_VIDEO_ADAPTER_KEY"), + 'secret' => env("NDLA_H5P_VIDEO_ADAPTER_SECRET"), + 'deleteVideoSourceAfterConvertToStream' => (bool)env("NDLA_H5P_VIDEO_ADAPTER_DELETEVIDEO", false), + 'pingDelay' => env("NDLA_H5P_VIDEO_DELAY", 10), + 'accountId' => env("NDLA_H5P_VIDEO_ACCOUNT_ID"), + 'authUrl' => env("NDLA_H5P_VIDEO_AUTH_URL"), + ], 'saveFrequency' => env('NDLA_H5P_SAVE_FREQUENCY', false), ] ]; diff --git a/sourcecode/apis/contentauthor/phpstan-baseline.neon b/sourcecode/apis/contentauthor/phpstan-baseline.neon index ba8659e36d..3fa6b722d6 100644 --- a/sourcecode/apis/contentauthor/phpstan-baseline.neon +++ b/sourcecode/apis/contentauthor/phpstan-baseline.neon @@ -35,6 +35,11 @@ parameters: count: 2 path: app/Console/Commands/VersionAllUnversionedContent.php + - + message: "#^Should not use node with type \"Stmt_Echo\", please change the code\\.$#" + count: 2 + path: app/Console/Commands/VersionAllUnversionedContent.php + - message: "#^Access to an undefined property App\\\\ContentLanguageLink\\:\\:\\$link_content_id\\.$#" count: 1 @@ -55,21 +60,11 @@ parameters: count: 3 path: app/Content.php - - - message: "#^Expression on left side of \\?\\? is not nullable\\.$#" - count: 1 - path: app/Content.php - - message: "#^Right side of && is always true\\.$#" count: 1 path: app/Content.php - - - message: "#^Strict comparison using \\=\\=\\= between false and true will always evaluate to false\\.$#" - count: 1 - path: app/Content.php - - message: "#^Ternary operator condition is always true\\.$#" count: 1 @@ -110,11 +105,6 @@ parameters: count: 1 path: app/Exceptions/Handler.php - - - message: "#^Access to an undefined property App\\\\File\\:\\:\\$article\\.$#" - count: 1 - path: app/File.php - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$email\\.$#" count: 1 @@ -125,11 +115,6 @@ parameters: count: 1 path: app/H5PCollaborator.php - - - message: "#^Access to an undefined property App\\\\H5PContent\\:\\:\\$contentLibraries\\.$#" - count: 1 - path: app/H5PContent.php - - message: "#^Call to function is_null\\(\\) with App\\\\H5PContentsMetadata will always evaluate to false\\.$#" count: 1 @@ -155,11 +140,6 @@ parameters: count: 1 path: app/Http/Controllers/API/ArticleInfoController.php - - - message: "#^Relation 'collaborators' is not found in App\\\\Article model\\.$#" - count: 1 - path: app/Http/Controllers/API/ArticleInfoController.php - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$email\\.$#" count: 1 @@ -175,16 +155,6 @@ parameters: count: 1 path: app/Http/Controllers/API/H5PInfoController.php - - - message: "#^Relation 'library' is not found in App\\\\H5PContent model\\.$#" - count: 1 - path: app/Http/Controllers/API/H5PInfoController.php - - - - message: "#^Relation 'library' is not found in App\\\\H5PContent model\\.$#" - count: 1 - path: app/Http/Controllers/API/H5PTypeApi.php - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$created_at\\.$#" count: 1 @@ -205,11 +175,6 @@ parameters: count: 1 path: app/Http/Controllers/API/LinkInfoController.php - - - message: "#^Relation 'collaborators' is not found in App\\\\Link model\\.$#" - count: 1 - path: app/Http/Controllers/API/LinkInfoController.php - - message: "#^Left side of && is always true\\.$#" count: 1 @@ -265,11 +230,6 @@ parameters: count: 1 path: app/Http/Controllers/Admin/AdminController.php - - - message: "#^Relation 'library' is not found in App\\\\H5PContent model\\.$#" - count: 1 - path: app/Http/Controllers/Admin/AdminController.php - - message: "#^Static call to instance method App\\\\H5PContent\\:\\:noMaxScoreScope\\(\\)\\.$#" count: 1 @@ -310,16 +270,6 @@ parameters: count: 1 path: app/Http/Controllers/Admin/AdminUserController.php - - - message: "#^Relation 'capability' is not found in App\\\\H5PLibrary model\\.$#" - count: 1 - path: app/Http/Controllers/Admin/Capability.php - - - - message: "#^Relation 'capability' is not found in App\\\\H5PLibrary model\\.$#" - count: 1 - path: app/Http/Controllers/Admin/CapabilityController.php - - message: "#^Method App\\\\Libraries\\\\H5P\\\\Interfaces\\\\H5PAdapterInterface\\:\\:emptyArticleImportLog\\(\\) invoked with 0 parameters, 1 required\\.$#" count: 1 @@ -376,22 +326,22 @@ parameters: path: app/Http/Controllers/GameController.php - - message: "#^Method App\\\\Http\\\\Controllers\\\\H5PController\\:\\:create\\(\\) invoked with 1 parameter, 2\\-3 required\\.$#" + message: "#^Called 'isNotEmpty' on Laravel collection, but could have been retrieved as a query\\.$#" count: 1 path: app/Http/Controllers/H5PController.php - - message: "#^Method App\\\\Http\\\\Controllers\\\\H5PController\\:\\:getContentLicense\\(\\) should return Illuminate\\\\Http\\\\Response but returns int\\|string\\|false\\.$#" + message: "#^Method App\\\\Http\\\\Controllers\\\\H5PController\\:\\:create\\(\\) invoked with 1 parameter, 2\\-3 required\\.$#" count: 1 path: app/Http/Controllers/H5PController.php - - message: "#^Parameter \\#2 \\$current of method H5PCore\\:\\:getStorableDisplayOptions\\(\\) expects int, null given\\.$#" + message: "#^Method App\\\\Http\\\\Controllers\\\\H5PController\\:\\:getContentLicense\\(\\) should return Illuminate\\\\Http\\\\Response but returns int\\|string\\|false\\.$#" count: 1 path: app/Http/Controllers/H5PController.php - - message: "#^Relation 'library' is not found in App\\\\H5PContent model\\.$#" + message: "#^Parameter \\#2 \\$current of method H5PCore\\:\\:getStorableDisplayOptions\\(\\) expects int, null given\\.$#" count: 1 path: app/Http/Controllers/H5PController.php @@ -465,11 +415,6 @@ parameters: count: 1 path: app/Http/Libraries/ContentTypes/H5PContentType.php - - - message: "#^Relation 'capability' is not found in App\\\\H5PLibrary model\\.$#" - count: 1 - path: app/Http/Libraries/ContentTypes/InteractivityContentType.php - - message: "#^PHPDoc tag @return with type array is incompatible with native type App\\\\Http\\\\Libraries\\\\ContentTypes\\\\ContentType\\.$#" count: 1 @@ -676,39 +621,14 @@ parameters: path: app/Libraries/H5P/AjaxRequest.php - - message: "#^Ternary operator condition is always true\\.$#" - count: 1 - path: app/Libraries/H5P/ContentType/BaseH5PContent.php - - - - message: "#^Access to an undefined property App\\\\H5PLibrariesHubCache\\:\\:\\$libraries\\.$#" - count: 2 - path: app/Libraries/H5P/EditorAjax.php - - - - message: "#^Access to an undefined property App\\\\H5PLibrary\\:\\:\\$capability\\.$#" - count: 1 - path: app/Libraries/H5P/EditorAjax.php - - - - message: "#^Access to an undefined property App\\\\H5PLibraryLanguage\\:\\:\\$library\\.$#" - count: 1 - path: app/Libraries/H5P/EditorAjax.php - - - - message: "#^Relation 'capability' is not found in App\\\\H5PLibrary model\\.$#" - count: 1 - path: app/Libraries/H5P/EditorAjax.php + message: "#^Should not use node with type \"Expr_Exit\", please change the code\\.$#" + count: 3 + path: app/Libraries/H5P/AjaxRequest.php - - message: "#^Relation 'libraries' is not found in App\\\\H5PLibrariesHubCache model\\.$#" + message: "#^Ternary operator condition is always true\\.$#" count: 1 - path: app/Libraries/H5P/EditorAjax.php - - - - message: "#^Relation 'library' is not found in App\\\\H5PLibraryLanguage model\\.$#" - count: 2 - path: app/Libraries/H5P/EditorAjax.php + path: app/Libraries/H5P/ContentType/BaseH5PContent.php - message: "#^Access to an undefined property App\\\\H5PLibrary\\:\\:\\$isOld\\.$#" @@ -851,11 +771,6 @@ parameters: count: 1 path: app/Libraries/H5P/Framework.php - - - message: "#^Relation 'library' is not found in App\\\\H5PContent model\\.$#" - count: 1 - path: app/Libraries/H5P/Framework.php - - message: "#^Call to method toArray\\(\\) on an unknown class Cerpus\\\\Helper\\\\Traits\\\\CreateTrait\\.$#" count: 1 @@ -941,6 +856,16 @@ parameters: count: 1 path: app/Libraries/H5P/H5PProgress.php + - + message: "#^Should not use node with type \"Expr_Exit\", please change the code\\.$#" + count: 2 + path: app/Libraries/H5P/H5PProgress.php + + - + message: "#^Access to an undefined property object\\:\\:\\$path\\.$#" + count: 1 + path: app/Libraries/H5P/H5PViewConfig.php + - message: "#^Unreachable statement \\- code above always terminates\\.$#" count: 1 @@ -1031,11 +956,6 @@ parameters: count: 1 path: app/Libraries/H5P/Storage/H5PCerpusStorage.php - - - message: "#^Access to an undefined property object\\:\\:\\$path\\.$#" - count: 1 - path: app/Libraries/H5P/H5PViewConfig.php - - message: "#^Parameter \\#1 \\$content of method H5peditor\\:\\:processParameters\\(\\) expects stdClass, int given\\.$#" count: 1 @@ -1091,11 +1011,6 @@ parameters: count: 4 path: app/Libraries/QuestionSet/QuestionSetHandler.php - - - message: "#^Access to an undefined property App\\\\LibraryDescription\\:\\:\\$library\\.$#" - count: 1 - path: app/LibraryDescription.php - - message: "#^PHPDoc tag @var has invalid value \\(\\$leafs VersionData\\[\\]\\)\\: Unexpected token \"\\$leafs\", expected type at offset 9$#" count: 1 @@ -1156,11 +1071,6 @@ parameters: count: 1 path: app/Listeners/H5P/HandleVersioning.php - - - message: "#^Call to an undefined method Illuminate\\\\Database\\\\Eloquent\\\\Builder\\:\\:h5p\\(\\)\\.$#" - count: 1 - path: app/NdlaIdMapper.php - - message: "#^PHPDoc type array of property App\\\\Providers\\\\AuthServiceProvider\\:\\:\\$policies is not covariant with PHPDoc type array\\ of overridden property Illuminate\\\\Foundation\\\\Support\\\\Providers\\\\AuthServiceProvider\\:\\:\\$policies\\.$#" count: 1 @@ -1181,11 +1091,6 @@ parameters: count: 1 path: app/QuestionSet.php - - - message: "#^Access to an undefined property App\\\\QuestionSetQuestion\\:\\:\\$questionset\\.$#" - count: 1 - path: app/Transformers/QuestionSetsQuestionTransformer.php - - message: "#^PHPDoc type array of property App\\\\User\\:\\:\\$fillable is not covariant with PHPDoc type array\\ of overridden property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$fillable\\.$#" count: 1 @@ -1256,11 +1161,6 @@ parameters: count: 1 path: database/migrations/2020_12_07_133958_set_admin_password.php - - - message: "#^Access to an undefined property App\\\\Article\\:\\:\\$files\\.$#" - count: 1 - path: tests/Integration/Article/ArticleFileVersionerTest.php - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$auth_id\\.$#" count: 10 diff --git a/sourcecode/apis/contentauthor/phpstan.neon.dist b/sourcecode/apis/contentauthor/phpstan.neon.dist index 0447723e9c..53bae1bb18 100644 --- a/sourcecode/apis/contentauthor/phpstan.neon.dist +++ b/sourcecode/apis/contentauthor/phpstan.neon.dist @@ -1,4 +1,5 @@ includes: + - vendor/ekino/phpstan-banned-code/extension.neon - vendor/nunomaduro/larastan/extension.neon - phpstan-baseline.neon @@ -16,3 +17,18 @@ parameters: stubFiles: - stubs/h5p-core/H5PCore.stub - stubs/h5p-core/H5PExport.stub + banned_code: + nodes: + - + type: Expr_FuncCall + functions: + - dd + - dump + - phpinfo + - print_r + - printf + - var_dump + - { type: Expr_ShellExec, functions: null } + - { type: Stmt_Echo, functions: null } + - { type: Stmt_Exit, functions: null } + - { type: Stmt_Print, functions: null } diff --git a/sourcecode/apis/contentauthor/phpunit.xml b/sourcecode/apis/contentauthor/phpunit.xml index 0e852e735a..c9ed33b0e8 100644 --- a/sourcecode/apis/contentauthor/phpunit.xml +++ b/sourcecode/apis/contentauthor/phpunit.xml @@ -53,5 +53,6 @@ + diff --git a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/H5PControllerTest.php b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/H5PControllerTest.php index c7a00d1b42..48878700cc 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/H5PControllerTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/H5PControllerTest.php @@ -10,12 +10,15 @@ use App\H5PContentsMetadata; use App\H5PContentsUserData; use App\H5PLibrary; +use App\H5PLibraryLibrary; use App\Http\Controllers\H5PController; use App\Http\Libraries\License; +use App\Libraries\H5P\H5PConfigAbstract; use Faker\Factory; use H5PCore; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use Illuminate\View\View; @@ -27,7 +30,8 @@ class H5PControllerTest extends TestCase use RefreshDatabase; use MockAuthApi; - public function testCreate(): void + /** @dataProvider provider_adapterMode */ + public function testCreate(string $adapterMode): void { $faker = Factory::create(); $this->session([ @@ -39,6 +43,7 @@ public function testCreate(): void 'jwtToken' => [ 'raw' => 'a unique token', ], + 'adapterMode' => $adapterMode, ]); $request = Request::create('lti-content/create', 'POST', [ 'redirectToken' => $faker->uuid, @@ -92,10 +97,19 @@ public function testCreate(): void $this->assertNull($state['libraryid']); $this->assertSame('nob', $state['language_iso_639_3']); $this->assertEquals(config('license.default-license'), $state['license']); + + // Adapter specific + if ($adapterMode === 'ndla') { + $this->assertContains('/js/react-contentbrowser.js', $result['configJs']); + } elseif ($adapterMode === 'cerpus') { + $this->assertSame([], $data['configJs']); + } } - public function testEdit(): void + /** @dataProvider provider_adapterMode */ + public function testEdit(string $adapterMode): void { + Session::put('adapterMode', $adapterMode); $faker = Factory::create(); $user = new User(42, 'Emily', 'Quackfaster', 'emily.quackfaster@duckburg.quack'); $this->setupAuthApi([ @@ -150,13 +164,13 @@ public function testEdit(): void /** @var H5PController $articleController */ $articleController = app(H5PController::class); $result = $articleController->edit($request, $h5pContent->id); - $this->assertNotEmpty($result); $this->assertInstanceOf(View::class, $result); $data = $result->getData(); $this->assertSame('a unique token', $data['jwtToken']); $this->assertSame($h5pContent->id, $data['id']); + $this->assertInstanceOf(H5PContent::class, $data['h5p']); $this->assertSame($h5pContent->id, $data['h5p']->id); $this->assertNotEmpty($data['config']); @@ -168,7 +182,6 @@ public function testEdit(): void $this->assertNotEmpty($data['hasUserProgress']); $this->assertNotEmpty($data['editorSetup']); $this->assertNotEmpty($data['state']); - $this->assertSame([], $data['configJs']); $config = json_decode(substr($result['config'], 25, -9), true, flags: JSON_THROW_ON_ERROR); $this->assertFalse($config['canGiveScore']); @@ -199,6 +212,13 @@ public function testEdit(): void $this->assertNotEmpty($state['parameters']); $this->assertNotEmpty($state['redirectToken']); $this->assertNotEmpty($state['title']); + + // Adapter specific + if ($adapterMode === 'ndla') { + $this->assertContains('/js/react-contentbrowser.js', $result['configJs']); + } elseif ($adapterMode === 'cerpus') { + $this->assertSame([], $data['configJs']); + } } /** @@ -243,15 +263,18 @@ public function invalidRequestsProvider(): iterable yield [['language_iso_639_3' => 'eeee'], ['language_iso_639_3']]; } - public function testDoShow(): void + /** @dataProvider provider_adapterMode */ + public function testDoShow(string $adapterMode): void { + Session::put('adapterMode', $adapterMode); $faker = Factory::create(); Storage::fake('test'); $resourceId = $faker->uuid; $resourceApi = $this->createMock(ResourceApiService::class); $this->instance(ResourceApiService::class, $resourceApi); - H5PLibrary::factory()->create(); + $depH5PVideo = H5PLibrary::factory()->create(['name' => 'H5P.Video', 'major_version' => 2, 'minor_version' => 9]); + $depCerpusVideo = H5PLibrary::factory()->create(['name' => 'H5P.CerpusVideo', 'major_version' => 3, 'minor_version' => 8]); /** @var H5PLibrary $library */ $library = H5PLibrary::factory()->create([ 'minor_version' => 18, @@ -264,6 +287,17 @@ public function testDoShow(): void 'preloaded_js' => 'deplib.js', 'preloaded_css' => 'deplib.css', ]); + H5PLibraryLibrary::create([ + 'library_id' => $library->id, + 'required_library_id' => $depH5PVideo->id, + 'dependency_type' => 'preloaded', + ]); + H5PLibraryLibrary::create([ + 'library_id' => $library->id, + 'required_library_id' => $depCerpusVideo->id, + 'dependency_type' => 'preloaded', + ]); + Storage::put('libraries/H5P.DepLib-2.19/deplib.js', 'Here be JS content'); Storage::put('libraries/H5P.DepLib-2.19/deplib.css', 'Here be CSS content'); H5PContent::factory()->create([ @@ -283,6 +317,20 @@ public function testDoShow(): void 'weight' => 1, 'drop_css' => 0, ]); + H5PContentLibrary::create([ + 'content_id' => $content->id, + 'library_id' => $depH5PVideo->id, + 'dependency_type' => 'preloaded', + 'weight' => 1, + 'drop_css' => 0, + ]); + H5PContentLibrary::create([ + 'content_id' => $content->id, + 'library_id' => $depCerpusVideo->id, + 'dependency_type' => 'preloaded', + 'weight' => 1, + 'drop_css' => 0, + ]); $resourceApi ->expects($this->atLeastOnce()) @@ -308,7 +356,11 @@ public function testDoShow(): void $config = json_decode(substr($result['config'], 25, -9), flags: JSON_THROW_ON_ERROR); $this->assertObjectHasAttribute('baseUrl', $config); $this->assertObjectHasAttribute('url', $config); - $this->assertObjectHasAttribute('user', $config); + if (config('h5p.saveFrequency') === false) { + $this->assertObjectNotHasAttribute('user', $config); + } else { + $this->assertObjectHasAttribute('user', $config); + } $this->assertObjectHasAttribute('tokens', $config); $this->assertObjectHasAttribute('siteUrl', $config); $this->assertObjectHasAttribute('l10n', $config); @@ -329,5 +381,25 @@ public function testDoShow(): void $this->assertObjectHasAttribute('displayOptions', $contents); $this->assertObjectHasAttribute('contentUserData', $contents); $this->assertStringContainsString("/s/resources/$resourceId", $contents->embedCode); + + // Adapter specific + $this->assertContains('//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-AMS-MML_SVG', $result['jsScripts']); + $this->assertContains('/js/videos/brightcove.js', $result['jsScripts']); + + if ($adapterMode === "ndla") { + $this->assertContains('/js/h5p/wiris/view.js', $result['jsScripts']); + $this->assertContains('/js/h5peditor-custom.js', $result['jsScripts']); + + $this->assertContains('/css/ndlah5p-iframe-legacy.css?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $result['styles']); + $this->assertContains('/css/ndlah5p-iframe.css?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $result['styles']); + } elseif ($adapterMode === "cerpus") { + $this->assertContains('/js/videos/streamps.js', $result['jsScripts']); + } + } + + public function provider_adapterMode(): \Generator + { + yield 'cerpus' => ['cerpus']; + yield 'ndla' => ['ndla']; } } diff --git a/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PConfigAbstractTest.php b/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PConfigAbstractTest.php index e60ec074fe..548e033a07 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PConfigAbstractTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PConfigAbstractTest.php @@ -1,6 +1,6 @@ getConfig(); + Session::put('adapterMode', $adapterMode); + + $config = app(H5PCreateConfig::class); + $data = $config->getConfig(); // Check that the common attributes are present $this->assertObjectHasAttribute('baseUrl', $data); $this->assertObjectHasAttribute('url', $data); $this->assertObjectHasAttribute('postUserStatistics', $data); $this->assertObjectHasAttribute('ajaxPath', $data); - $this->assertObjectHasAttribute('user', $data); + if (config('h5p.saveFrequency') === false) { + $this->assertObjectNotHasAttribute('user', $data); + } else { + $this->assertObjectHasAttribute('user', $data); + } $this->assertObjectHasAttribute('canGiveScore', $data); $this->assertObjectHasAttribute('hubIsEnabled', $data); $this->assertObjectHasAttribute('ajax', $data); @@ -60,6 +69,32 @@ public function test_getConfig(): void $this->assertNotEmpty($data->editor->extraAllowedContent); $this->assertSame('en', $data->editor->language); $this->assertSame('en', $data->editor->defaultLanguage); + + // Adapter specific + if ($adapterMode === 'ndla') { + $this->assertContains('/css/ndlah5p-editor.css', $data->editor->assets->css); + $this->assertContains('/js/cropperjs/cropper.min.css', $data->editor->assets->css); + $this->assertContains('/css/ndlah5p-youtube.css', $data->editor->assets->css); + + $this->assertContains('/js/h5p/wiris/h5peditor-html-wiris-addon.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/ndla-contentbrowser.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/videos/brightcove.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/h5peditor-image-popup.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/h5peditor-custom.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/h5p/ndlah5p-youtube.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + + $this->assertSame('https://www.wiris.net/client/plugins/ckeditor/plugin.js', $data->editor->wirisPath); + } elseif ($adapterMode === 'cerpus') { + $this->assertContains('/js/videos/streamps.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/videos/brightcove.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertObjectNotHasAttribute('wirisPath', $data->editor); + } + } + + public function provider_adapterMode(): \Generator + { + yield 'cerpusMode' => ['cerpus']; + yield 'ndlaMode' => ['ndla']; } public function test_setDisplayHub(): void diff --git a/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PEditConfigTest.php b/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PEditConfigTest.php index ee5d2dd152..d5b5e2af88 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PEditConfigTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PEditConfigTest.php @@ -5,25 +5,34 @@ use App\H5PContent; use App\H5PContentsMetadata; use App\H5PLibrary; +use App\Libraries\H5P\H5PConfigAbstract; use App\Libraries\H5P\H5PEditConfig; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Facades\Session; use Tests\TestCase; class H5PEditConfigTest extends TestCase { use RefreshDatabase; - public function test_getConfig(): void + /** @dataProvider provider_adapterMode */ + public function test_getConfig(string $adapterMode): void { - $data = app(H5PEditConfig::class) - ->getConfig(); + Session::put('adapterMode', $adapterMode); + + $config = app(H5PEditConfig::class); + $data = $config->getConfig(); // Check that the common attributes are present $this->assertObjectHasAttribute('baseUrl', $data); $this->assertObjectHasAttribute('url', $data); $this->assertObjectHasAttribute('postUserStatistics', $data); $this->assertObjectHasAttribute('ajaxPath', $data); - $this->assertObjectHasAttribute('user', $data); + if (config('h5p.saveFrequency') === false) { + $this->assertObjectNotHasAttribute('user', $data); + } else { + $this->assertObjectHasAttribute('user', $data); + } $this->assertObjectHasAttribute('canGiveScore', $data); $this->assertObjectHasAttribute('hubIsEnabled', $data); $this->assertObjectHasAttribute('ajax', $data); @@ -62,6 +71,32 @@ public function test_getConfig(): void $this->assertNotEmpty($data->editor->extraAllowedContent); $this->assertSame('en', $data->editor->language); $this->assertSame('en', $data->editor->defaultLanguage); + + // Adapter specific + if ($adapterMode === 'ndla') { + $this->assertContains('/css/ndlah5p-editor.css', $data->editor->assets->css); + $this->assertContains('/js/cropperjs/cropper.min.css', $data->editor->assets->css); + $this->assertContains('/css/ndlah5p-youtube.css', $data->editor->assets->css); + + $this->assertContains('/js/h5p/wiris/h5peditor-html-wiris-addon.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/ndla-contentbrowser.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/videos/brightcove.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/h5peditor-image-popup.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/h5peditor-custom.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/h5p/ndlah5p-youtube.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + + $this->assertSame('https://www.wiris.net/client/plugins/ckeditor/plugin.js', $data->editor->wirisPath); + } elseif ($adapterMode === 'cerpus') { + $this->assertContains('/js/videos/streamps.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertContains('/js/videos/brightcove.js?ver=' . H5PConfigAbstract::CACHE_BUSTER_STRING, $data->editor->assets->js); + $this->assertObjectNotHasAttribute('wirisPath', $data->editor); + } + } + + public function provider_adapterMode(): \Generator + { + yield 'cerpus' => ['cerpus']; + yield 'ndla' => ['ndla']; } public function test_loadContent(): void diff --git a/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PViewConfigTest.php b/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PViewConfigTest.php index efb6a04185..96b6b83a5c 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PViewConfigTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Libraries/H5P/H5PViewConfigTest.php @@ -21,17 +21,24 @@ class H5PViewConfigTest extends TestCase { use RefreshDatabase; - public function test_getConfig(): void + /** @dataProvider provider_adapterMode */ + public function test_getConfig(string $adapterMode): void { - $data = app(H5PViewConfig::class) - ->getConfig(); + Session::put('adapterMode', $adapterMode); + + $config = app(H5PViewConfig::class); + $data = $config->getConfig(); // Check that the common attributes are present $this->assertObjectHasAttribute('baseUrl', $data); $this->assertObjectHasAttribute('url', $data); $this->assertObjectHasAttribute('postUserStatistics', $data); $this->assertObjectHasAttribute('ajaxPath', $data); - $this->assertObjectHasAttribute('user', $data); + if (config('h5p.saveFrequency') === false) { + $this->assertObjectNotHasAttribute('user', $data); + } else { + $this->assertObjectHasAttribute('user', $data); + } $this->assertObjectHasAttribute('canGiveScore', $data); $this->assertObjectHasAttribute('hubIsEnabled', $data); $this->assertObjectHasAttribute('ajax', $data); @@ -58,6 +65,12 @@ public function test_getConfig(): void $this->assertSame('/api/progress?action=h5p_setFinished', $data->ajax['setFinished']); } + public function provider_adapterMode(): \Generator + { + yield 'cerpus' => ['cerpus']; + yield 'ndla' => ['ndla']; + } + /** @dataProvider provider_setPreview */ public function test_setPreview(bool $preview, string $contentUserData, string $setFinished): void { @@ -84,11 +97,11 @@ public function provider_setPreview(): \Generator ]; } - /** @dataProvider provider_saveFrequency */ - public function test_loadContent(int|false $frequency): void + /** @dataProvider provider_adapterMode */ + public function test_loadContent(string $adapterMode): void { + Session::put('adapterMode', $adapterMode); $faker = Factory::create(); - config()->set('h5p.saveFrequency', $frequency); $resourceId = $faker->uuid; $context = $faker->uuid; @@ -144,9 +157,9 @@ public function test_loadContent(int|false $frequency): void $this->assertStringContainsString("/s/resources/$resourceId", $contentData->embedCode); $this->assertNotEmpty($data->url); $this->assertSame($content->title, $contentData->title); - $this->assertSame($frequency, $data->saveFreq); + $this->assertSame(config('h5p.saveFrequency'), $data->saveFreq); - if ($frequency === false) { + if (config('h5p.saveFrequency') === false) { $this->assertObjectNotHasAttribute('user', $data); } else { $this->assertObjectHasAttribute('user', $data); @@ -167,12 +180,6 @@ public function test_loadContent(int|false $frequency): void $this->assertFalse($contentData->contentUserData['state']); } - public function provider_saveFrequency() - { - yield [15]; - yield [false]; - } - public function test_setAlterParameterSettings(): void { $faker = Factory::create(); diff --git a/sourcecode/apis/version/pom.xml b/sourcecode/apis/version/pom.xml index f27bc03566..2d909cdcb9 100644 --- a/sourcecode/apis/version/pom.xml +++ b/sourcecode/apis/version/pom.xml @@ -62,7 +62,7 @@ org.postgresql postgresql - 42.2.5 + 42.4.1