app/services/editions/db/FrontsQueries.scala (168 lines of code) (raw):

package services.editions.db import logging.Logging import model.editions.{EditionsFront, EditionsFrontMetadata} import services.editions.DbEditionsFront import scalikejdbc._ import play.api.libs.json._ import com.gu.pandomainauth.model.User import java.time.OffsetDateTime import scala.util.Try import scala.util.Failure import services.editions.DbEditionsCollection import services.editions.DbEditionsCard import model.editions.EditionsCollection case class FrontAndNestedEntitiesRow( front: Option[DbEditionsFront], collection: Option[DbEditionsCollection], card: Option[DbEditionsCard] ) trait FrontsQueries extends Logging { def updateFrontMetadata( id: String, metadata: EditionsFrontMetadata ): Option[EditionsFrontMetadata] = DB localTx { implicit session => val updatedMetadata = metadata.copy(nameOverride = metadata.nameOverride.map(_.trim())) sql""" UPDATE fronts SET metadata = ${updatedMetadata.toPGobject} WHERE id = $id """.execute.apply() sql""" SELECT metadata FROM fronts WHERE id = $id """ .map { rs => rs.stringOpt("metadata").map { metadataString => // Throw if we can't parse the metadata to signal to the user that something is broken Json.parse(metadataString).validate[EditionsFrontMetadata].get } } .single .apply() .flatten } def getFrontMetadata(id: String): EditionsFrontMetadata = DB localTx { implicit session => val rawJson = sql""" SELECT metadata from fronts WHERE id = $id """.map(rs => { rs.string("metadata") match { case "" => "{}" case s: String => s } }).single .apply() .get Json.fromJson[EditionsFrontMetadata](Json.parse(rawJson)).get } // TODO: sihil this should really escalate an error if this is attempted when is_special is false but we don't // have a clean way of doing that right now. def updateFrontHiddenState(id: String, isHidden: Boolean): Option[Boolean] = DB localTx { implicit session => sql""" UPDATE fronts SET is_hidden = $isHidden WHERE id = $id AND is_special = TRUE """.execute.apply() val newState = sql""" SELECT is_hidden, is_special FROM fronts WHERE id = $id """ .map { rs => (rs.boolean("is_hidden"), rs.boolean("is_special")) } .single .apply() newState.map { case (isHidden, isSpecial) => if (!isSpecial) logger.warn( s"Tried to update hidden state on front $id which is not a special front" ) isHidden } } def getFront( frontId: String )(implicit session: DBSession): Option[EditionsFront] = { val rows: List[FrontAndNestedEntitiesRow] = sql""" SELECT ${FrontsQueries.frontAndNestedEntitiesColumns} FROM fronts LEFT JOIN collections ON (collections.front_id = fronts.id) LEFT JOIN cards ON (cards.collection_id = collections.id) WHERE fronts.id = $frontId """ .map { rs => FrontAndNestedEntitiesRow( DbEditionsFront.fromRowOpt(rs, "fronts_"), DbEditionsCollection.fromRowOpt(rs, "collections_"), DbEditionsCard.fromRowOpt(rs, "cards_") ) } .list .apply() FrontsQueries.toEditionsFront(rows).headOption } } object FrontsQueries { def toEditionsFront( rows: List[FrontAndNestedEntitiesRow] ): List[EditionsFront] = { rows .flatMap(_.front) .sortBy(_.index) .map(_.front) .distinctBy(_.id) .map { front => val collectionsForFront = rows .flatMap { _.collection.filter(_.frontId == front.id) } .sortBy(_.index) .map(_.collection) .foldLeft(List.empty[EditionsCollection]) { (acc, cur) => if (acc.exists(c => c.id == cur.id)) acc else acc :+ cur } .map { collection => val cards = rows .flatMap(_.card.filter(_.collectionId == collection.id)) .sortBy(_.index) .map(_.card) collection .copy(items = cards) } front.copy(collections = collectionsForFront) } } val frontAndNestedEntitiesColumns = sqls""" fronts.id AS fronts_id, fronts.issue_id AS fronts_issue_id, fronts.index AS fronts_index, fronts.name AS fronts_name, fronts.is_special AS fronts_is_special, fronts.is_hidden AS fronts_is_hidden, fronts.metadata AS fronts_metadata, fronts.updated_on AS fronts_updated_on, fronts.updated_by AS fronts_updated_by, fronts.updated_email AS fronts_updated_email, collections.id AS collections_id, collections.front_id AS collections_front_id, collections.index AS collections_index, collections.name AS collections_name, collections.is_hidden AS collections_is_hidden, collections.metadata AS collections_metadata, collections.updated_on AS collections_updated_on, collections.updated_by AS collections_updated_by, collections.updated_email AS collections_updated_email, collections.prefill AS collections_prefill, collections.path_type AS collections_path_type, collections.content_prefill_window_start AS collections_content_prefill_window_start, collections.content_prefill_window_end AS collections_content_prefill_window_end, collections.targeted_regions AS collections_targeted_regions, collections.excluded_regions AS collections_excluded_regions, cards.collection_id AS cards_collection_id, cards.id AS cards_id, cards.card_type AS cards_card_type, cards.index AS cards_index, cards.added_on AS cards_added_on, cards.metadata AS cards_metadata """ }