Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Part of NDLA learningpath-api
* Copyright (C) 2025 NDLA
*
* See LICENSE
*
*/

package no.ndla.learningpathapi.db.migration

import io.circe.Json
import no.ndla.common.CirceUtil
import no.ndla.common.model.domain.Author
import no.ndla.common.model.domain.learningpath.LearningpathCopyright
import no.ndla.learningpathapi.db.util.*

class V59__CopyContributorsToLearningStep extends LearningPathAndStepMigration {
override def convertPathAndSteps(
lpData: LpDocumentRow,
stepDatas: List[StepDocumentRow]
): (LpDocumentRow, List[StepDocumentRow]) = {
val learningPathJson = CirceUtil.unsafeParse(lpData.learningPathDocument)
val contributorsOpt = for {
copyright <- learningPathJson.hcursor.downField("copyright").as[LearningpathCopyright].toOption
contributors <- Option(copyright.contributors)
} yield contributors

// extract contributors from learning path and copy to each step of type TEXT without embedUrl
val updatedSteps = stepDatas.map { step =>
val json = CirceUtil.unsafeParse(step.learningStepDocument)
val cursor = json.hcursor
val isText = cursor.get[String]("type").toOption.contains("TEXT")
val hasEmbedUrl = cursor.get[String]("embedUrl").toOption.isDefined
val hasArticleId = cursor.get[Long]("articleId").toOption.isDefined

if (isText && !hasEmbedUrl && !hasArticleId && contributorsOpt.isDefined) {
addContributorsToCopyright(json, contributorsOpt.get) match {
case Some(updated) => step.copy(learningStepDocument = updated.noSpaces)
case None => step
}
} else {
step
}
}
(lpData, updatedSteps)

}

private def addContributorsToCopyright(json: Json, contributors: Seq[Author]): Option[Json] = {
import no.ndla.common.model.domain.learningpath.LearningpathCopyright.encoder
val changed = json.hcursor.get[Option[LearningpathCopyright]]("copyright") match {
case Left(value) => throw new RuntimeException("Parsing learningstep failed")
case Right(Some(value)) =>
val copyrightObject = value.copy(contributors = contributors)
json.mapObject(obj => obj.remove("copyright").add("copyright", encoder.apply(copyrightObject)))
case Right(None) => json
}

Option.when(changed != json) { changed }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Part of NDLA learningpath-api
* Copyright (C) 2025 NDLA
*
* See LICENSE
*
*/

package no.ndla.learningpathapi.db.migration

import no.ndla.common.CirceUtil
import no.ndla.learningpathapi.db.util.{LpDocumentRow, StepDocumentRow}
import no.ndla.learningpathapi.{TestEnvironment, UnitSuite}

class V59__CopyContributorsToLearningStepTest extends UnitSuite with TestEnvironment {

test("that license is moved to copyright with empty contributors") {
val migration = new V59__CopyContributorsToLearningStep
val learningpath =
"""
|{
| "copyright": { "license": "CC BY-NC-SA 4.0", "contributors": [{"name":"Forfatter","type":"writer"}]},
| "title": [{"title":"Test Step", "language":"nb"}],
| "description": [{"description":"This is a test step.", "language":"nb"}],
| "isMyNDLAOwner": true
|}
|""".stripMargin

val oldStepNoContributors =
"""
|{
| "title": [{"title":"Test Step", "language":"nb"}],
| "description": [{"description":"This is a test step.", "language":"nb"}],
| "copyright": { "license": "CC BY-NC-SA 4.0", "contributors": []},
| "type": "TEXT",
| "embedUrl": [],
| "articleId": null
|}
|""".stripMargin

val expectedDocument =
"""
|{
| "title": [{"title":"Test Step", "language":"nb"}],
| "description": [{"description":"This is a test step.", "language":"nb"}],
| "copyright": { "license": "CC BY-NC-SA 4.0", "contributors": [{"name":"Forfatter","type":"writer"}]},
| "type": "TEXT",
| "embedUrl": [],
| "articleId": null
|}
|""".stripMargin

val expectedConverted = CirceUtil.unsafeParse(expectedDocument)

val lpDoc = LpDocumentRow(1, learningpath)
val stepDoc1 = StepDocumentRow(1, oldStepNoContributors)
val (resultLpDoc, resultSteps) = migration.convertPathAndSteps(lpDoc, List(stepDoc1))

resultLpDoc should be(lpDoc)
val result1Json = CirceUtil.unsafeParse(resultSteps.head.learningStepDocument)

result1Json should be(expectedConverted)
}
}