vgquotes/Src/VideoGameQuotes.Web/Controllers/QuoteController.cs
tmont a41335c5ba * improved default browse page
* fixed bug where you couldn't add more categories if none already existed
* added ability to delete quotes
* added call handler to delete the search index when a quote is deleted
2011-03-04 08:20:20 +00:00

304 lines
9.4 KiB
C#

using System;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using Portoa.Persistence;
using Portoa.Search;
using Portoa.Validation.DataAnnotations;
using Portoa.Web.Controllers;
using Portoa.Web.Filters;
using Portoa.Web.Models;
using Portoa.Web.Results;
using Portoa.Web.Security;
using VideoGameQuotes.Api;
using VideoGameQuotes.Web.Models;
using VideoGameQuotes.Web.Security;
using VideoGameQuotes.Web.Services;
namespace VideoGameQuotes.Web.Controllers {
public class QuoteController : Controller {
private readonly IQuoteService quoteService;
private readonly ICurrentUserProvider<User> currentUserProvider;
private readonly ISearcher<Quote, int> quoteSearcher;
public QuoteController(IQuoteService quoteService, ICurrentUserProvider<User> currentUserProvider, ISearcher<Quote, int> quoteSearcher) {
this.quoteService = quoteService;
this.currentUserProvider = currentUserProvider;
this.quoteSearcher = quoteSearcher;
}
protected new ActionResult Json(object data) {
return this.SerializeToJson(data);
}
[HttpPost, VerifyUser(Group = UserGroup.Admin)]
public ActionResult Delete(int id) {
try {
quoteService.Delete(id);
return Json(this.CreateJsonResponse());
} catch (Exception e) {
return Json(this.CreateJsonErrorResponse(e));
}
}
public ActionResult Browse(BrowseModel model, int page = 1) {
if (page < 1) {
return new StatusOverrideResult(View("BadPaging")) { StatusCode = HttpStatusCode.BadRequest };
}
if (model.IsEmpty) {
return View("DefaultBrowse", quoteService.GetDefaultBrowseModel());
}
model.CurrentUser = currentUserProvider.CurrentUser;
var pagingModel = new PagedModel<Quote> {
CurrentPage = page,
PageSize = 10
};
int totalCount;
var quotes = quoteService.GetBrowsableQuotes(model, pagingModel.Start, pagingModel.End, out totalCount);
pagingModel.Records = quotes;
pagingModel.TotalCount = totalCount;
return View("QualifiedBrowse", new QualifiedBrowseModel(model) { PagedModel = pagingModel });
}
[HttpPost, VerifyUser]
public ActionResult Flag(ReportModel model) {
if (!ModelState.IsValid) {
return Json(this.CreateJsonErrorResponse("Invalid request"));
}
try {
var quote = quoteService.GetQuote(model.QuoteId);
quote.AddFlag(model.Comment, model.FlagType, currentUserProvider.CurrentUser);
quoteService.SaveQuote(quote);
return Json(this.CreateJsonResponse());
} catch {
return Json(this.CreateJsonErrorResponse("Unable to create your report"));
}
}
[HttpPost, VerifyUser]
public ActionResult Vote(VoteModel model) {
if (!ModelState.IsValid) {
return Json(this.CreateJsonErrorResponse("Invalid request"));
}
try {
var quote = quoteService.SaveQuote(quoteService.GetQuote(model.QuoteId).VoteFor(currentUserProvider.CurrentUser, model.Direction));
var data = new {
score = quote.Score,
upVotes = quote.UpVotes,
downVotes = quote.DownVotes
};
return Json(this.CreateJsonResponse(null, data));
} catch (CannotVoteTwiceException) {
return Json(this.CreateJsonErrorResponse("You have already voted for this quote; you can reverse your vote by voting in the other direction"));
} catch {
return Json(this.CreateJsonErrorResponse("An error occurred while trying to process your vote"));
}
}
public ActionResult Recent(int page) {
if (page < 1) {
return new StatusOverrideResult(View("BadPaging")) { StatusCode = HttpStatusCode.BadRequest };
}
const int pageSize = 10;
int totalCount;
var model = new PagedModelWithUser<Quote> {
CurrentUser = currentUserProvider.CurrentUser,
CurrentPage = page,
PageSize = pageSize
};
model.Records = quoteService.GetRecentQuotes(model.Start, model.End, out totalCount);
model.TotalCount = totalCount;
return View(model);
}
public ActionResult Best(int page) {
if (page < 1) {
return new StatusOverrideResult(View("BadPaging")) { StatusCode = HttpStatusCode.BadRequest };
}
const int pageSize = 10;
int totalCount;
var model = new PagedModelWithUser<Quote> {
CurrentUser = currentUserProvider.CurrentUser,
CurrentPage = page,
PageSize = pageSize
};
model.Records = quoteService.GetBestQuotes(model.Start, model.End, out totalCount);
model.TotalCount = totalCount;
return View(model);
}
public ActionResult Random() {
var quote = quoteService.GetRandomQuote();
if (quote == null) {
return View("NoQuotes");
}
return RedirectToAction("Quote", new { id = quote.Id, text = quote.GetUrlFriendlyText() });
}
[PrivateAction]
public ActionResult QuoteOfTheDay() {
var today = DateTime.UtcNow.DayOfYear;
var quote = quoteService.GetQuoteForDayOfYear(today);
return PartialView("QuoteOfTheDay", quote);
}
[HttpPost, VerifyUser(Group = UserGroup.Admin)]
public ActionResult DismissFlag([GreaterThanZero]int quoteId, [GreaterThanZero]int flagId) {
if (!ModelState.IsValid) {
return Json(this.CreateJsonErrorResponse("quote/flag is invalid"));
}
try {
var quote = quoteService.GetQuote(quoteId);
var flag = quote.Flags.FirstOrDefault(f => f.Id == flagId);
if (flag == null) {
return Json(this.CreateJsonErrorResponse(string.Format("Flag {0} not found for quote {1}", flagId, quote.Id)));
}
quote.RemoveFlag(flag);
quoteService.SaveQuote(quote);
return Json(this.CreateJsonResponse());
} catch (Exception e) {
return Json(this.CreateJsonErrorResponse(e));
}
}
[HttpGet, VerifyUser(Group = UserGroup.Admin)]
public ActionResult Edit(int id) {
if (id < 1) {
return View("QuoteNotFound");
}
try {
return View(ResetEditQuoteModel(new EditQuoteModel(quoteService.GetQuote(id))));
} catch (EntityNotFoundException) {
return View("QuoteNotFound");
}
}
[HttpPost, VerifyUser(Group = UserGroup.Admin)]
public ActionResult Edit(EditQuoteModelBase model) {
return CreateOrEditQuote(model, "Edit");
}
[VerifyUser]
public ActionResult Submit() {
return View(ResetEditQuoteModel(new SubmitQuoteModel()));
}
[HttpPost, VerifyUser]
public ActionResult Submit(SubmitQuoteModel model) {
if (CaptchaUtil.Hash(model.CaptchaAnswer) != model.HashedCaptchaAnswer) {
ModelState.AddModelError("CaptchaAnswer", "You are not human");
}
return CreateOrEditQuote(model, "Submit");
}
private ActionResult CreateOrEditQuote(EditQuoteModelBase model, string viewName) {
if (!ModelState.IsValid) {
model = ResetEditQuoteModel(model);
return View(viewName, model);
}
try {
var editModel = model as EditQuoteModel;
var quote = editModel != null && editModel.QuoteId > 0
? quoteService.GetQuote(editModel.QuoteId)
: new Quote { Creator = currentUserProvider.CurrentUser };
quote.Game = new Game { Id = model.GameId };
quote.Text = model.QuoteText;
if (model.CategoryIds != null && model.CategoryIds.Count > 0) {
quote.ClearCategories();
foreach (var categoryId in model.CategoryIds) {
quote.AddCategory(new Category { Id = categoryId });
}
}
if (quote.Game == null) {
return View(viewName, ResetEditQuoteModel(model));
}
quote = quoteService.SaveQuote(quote);
return RedirectToAction("Quote", new { id = quote.Id, text = quote.GetUrlFriendlyText() });
} catch (Exception e) {
ModelState.AddModelError("save", e.Message);
return View(viewName, ResetEditQuoteModel(model));
}
}
private EditQuoteModelBase ResetEditQuoteModel(EditQuoteModelBase model) {
model.CurrentUser = currentUserProvider.CurrentUser;
model.AllGames = quoteService.GetAllGames().OrderBy(game => game.Name);
model.AllSystems = quoteService.GetAllSystems().OrderBy(system => system.ReleaseDate);
model.AllPublishers = quoteService.GetAllPublishers().OrderBy(publisher => publisher.Name);
model.AllCategories = quoteService.GetAllCategories().OrderBy(category => category.Name);
var submitModel = model as SubmitQuoteModel;
if (submitModel != null) {
submitModel.UnhashedCaptchaAnswer = CaptchaUtil.GetRandomAnswer();
submitModel.HashedCaptchaAnswer = CaptchaUtil.Hash(submitModel.UnhashedCaptchaAnswer);
submitModel.CaptchaAnswer = null;
return submitModel;
}
return model;
}
public ActionResult Quote(int id, string text = null) {
try {
var model = new QuoteModel {
Quote = quoteService.GetQuote(id),
User = currentUserProvider.CurrentUser
};
return View(model);
} catch (EntityNotFoundException) {
return new StatusOverrideResult(View("QuoteNotFound")) { StatusCode = HttpStatusCode.NotFound };
}
}
[VerifyUser(Group = UserGroup.Admin)]
public ActionResult Flags(int id) {
try {
var model = new QuoteModel {
Quote = quoteService.GetQuote(id),
User = currentUserProvider.CurrentUser
};
return View(model);
} catch (EntityNotFoundException) {
return new StatusOverrideResult(View("QuoteNotFound")) { StatusCode = HttpStatusCode.NotFound };
}
}
public ActionResult Search(string searchQuery) {
var model = new SearchModel {
User = currentUserProvider.CurrentUser,
Results = quoteSearcher.Search(searchQuery),
SearchQuery = searchQuery
};
return View(model);
}
}
}