complete wiki refactoring

This commit is contained in:
Thibault Duplessis 2013-03-14 00:19:11 +01:00
parent 5418e90e13
commit 00792f894c
12 changed files with 148 additions and 12 deletions

View file

@ -1,15 +1,13 @@
package lila.app
package wiki
package lila.wiki
import user.User
import lila.user.User
import org.joda.time.DateTime
import com.novus.salat.annotations.Key
import java.text.Normalizer
import java.util.regex.Matcher.quoteReplacement
case class Page(
@Key("_id") id: String,
id: String,
name: String,
title: String,
body: String) {

View file

@ -6,7 +6,7 @@ import play.api.libs.functional.syntax._
case class JsonTube[Doc](
reads: Reads[Doc],
writes: Writes[Doc],
writeTransformer: Reads[JsObject]) {
writeTransformer: Option[Reads[JsObject]] = None) {
lazy val implicits = new {
implicit val iReads = reads
@ -15,9 +15,10 @@ case class JsonTube[Doc](
def read(js: JsObject): JsResult[Doc] = reads reads js
def write(doc: Doc): JsResult[JsObject] = (writes writes doc) match {
case obj: JsObject obj transform writeTransformer
case value JsError()
def write(doc: Doc): JsResult[JsObject] = (writes writes doc, writeTransformer) match {
case (obj: JsObject, Some(transformer)) obj transform transformer
case (obj: JsObject, _) JsSuccess(obj)
case (value, _) JsError()
}
def toMongo(doc: Doc): JsResult[JsObject] = write(doc) flatMap JsonTube.toMongo

View file

@ -49,6 +49,8 @@ abstract class Repo[Doc <: WithStringId](coll: ReactiveColl, json: JsonTube[Doc]
ids.map(docsMap.get).flatten.toList
}
def all: Fu[List[Doc]] = apply(select.all)
def apply(q: JsObject): Fu[List[Doc]] = cursor(q).toList map (_.flatten)
def apply(q: JsObject, nb: Int): Fu[List[Doc]] = cursor(q, nb) toList nb map (_.flatten)
@ -89,6 +91,11 @@ abstract class Repo[Doc <: WithStringId](coll: ReactiveColl, json: JsonTube[Doc]
update(select(id), $set(field -> value))
}
object remove {
def apply(selector: JsObject): Funit = (coll remove selector).void
}
object primitive {
def apply[A](q: JsObject, field: String, modifier: QueryBuilder QueryBuilder = identity)(extract: JsValue Option[A]): Fu[List[A]] =

View file

@ -98,7 +98,7 @@ object ApplicationBuild extends Build with Resolvers with Dependencies {
lazy val wiki = project("wiki", Seq(common, db)).settings(
libraryDependencies ++= Seq(
playProvided, reactivemongo, playReactivemongo)
playProvided, reactivemongo, playReactivemongo, jgit, actuarius, guava)
).settings(srcMain: _*)
lazy val scalachess = project("scalachess").settings(

View file

@ -1,8 +1,6 @@
package lila.user
import lila.db.ReactiveColl
import com.mongodb.casbah.MongoCollection
import akka.actor.ActorSystem
import chess.EloCalculator

11
wiki/src/main/Api.scala Normal file
View file

@ -0,0 +1,11 @@
package lila.wiki
import play.api.libs.concurrent.Execution.Implicits._
final class Api(pageRepo: PageRepo) {
def show(slug: String): Fu[Option[(Page, List[Page])]] = for {
page pageRepo.find byId slug
pages pageRepo.find.all
} yield page map { _ -> pages }
}

44
wiki/src/main/Fetch.scala Normal file
View file

@ -0,0 +1,44 @@
package lila.wiki
import java.io.File
import com.google.common.io.Files
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.storage.file.FileRepository
import eu.henkelmann.actuarius.ActuariusTransformer
import scala.collection.JavaConversions._
import scala.concurrent.Future
import play.api.libs.concurrent.Execution.Implicits._
final class Fetch(gitUrl: String, pageRepo: PageRepo) {
def apply: Funit = getFiles flatMap { files =>
val pages = files.map(filePage).flatten
pageRepo.clear >> Future.sequence(pages.map(pageRepo.insert.apply)).void
}
private def filePage(file: File): Option[Page] = {
val name = """^(.+)\.md$""".r.replaceAllIn(file.getName, _ group 1)
(name != "Home") option Pages(name, toHtml(fileContent(file)))
}
private def getFiles: Fu[List[File]] = Future {
val dir = Files.createTempDir
dir.deleteOnExit
Git.cloneRepository
.setURI(gitUrl)
.setDirectory(dir)
.setBare(false)
.call
dir.listFiles.toList filter (_.isFile) sortBy (_.getName)
}
private def fileContent(file: File) =
scala.io.Source.fromFile(file.getCanonicalPath).mkString
private def toHtml(input: String): String =
new ActuariusTransformer() apply input
}

39
wiki/src/main/Page.scala Normal file
View file

@ -0,0 +1,39 @@
package lila.wiki
import lila.db.JsonTube
import org.joda.time.DateTime
import java.text.Normalizer
import java.util.regex.Matcher.quoteReplacement
case class Page(id: String, name: String, title: String, body: String) {
def slug = id
}
object Pages {
import play.api.libs.json._
val json = JsonTube[Page](
reads = Json.reads[Page],
writes = Json.writes[Page]
)
def apply(name: String, body: String): Page = new Page(
id = dropNumber(slugify(name)),
name = name,
title = dropNumber(name.replace("-", " ")),
body = body)
// does not lowercase
private def slugify(input: String) = {
val nowhitespace = input.replace(" ", "_")
val normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD)
"""[^\w-]""".r.replaceAllIn(normalized, "")
}
private def dropNumber(input: String) =
"""^\d+_(.+)$""".r.replaceAllIn(input, m => quoteReplacement(m group 1))
}

View file

@ -0,0 +1,9 @@
package lila.wiki
import lila.db.{ Repo, DbApi }
import lila.db.Implicits._
final class PageRepo(coll: ReactiveColl) extends Repo[Page](coll, Pages.json) {
def clear: Funit = remove(select.all)
}

View file

@ -0,0 +1,10 @@
package lila.wiki
import lila.common.ConfigSettings
import com.typesafe.config.Config
final class Settings(config: Config) extends ConfigSettings(config getObject "wiki") {
val CollectionPage = getString("collection.page")
val GitUrl = getString("git.url")
}

View file

@ -0,0 +1,16 @@
package lila.wiki
import lila.db.ReactiveColl
final class WikiEnv(settings: Settings, db: String ReactiveColl) {
import settings._
// lazy val pageRepo = new PageRepo(mongodb(WikiCollectionPage))
// lazy val api = new Api(pageRepo = pageRepo)
// lazy val fetch = new Fetch(
// gitUrl = WikiGitUrl,
// pageRepo = pageRepo)
}

View file

@ -0,0 +1,3 @@
package lila
package object wiki extends PackageObject with WithPlay with WithDb