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 currentUserProvider; private readonly ISearcher quoteSearcher; public QuoteController(IQuoteService quoteService, ICurrentUserProvider currentUserProvider, ISearcher quoteSearcher) { this.quoteService = quoteService; this.currentUserProvider = currentUserProvider; this.quoteSearcher = quoteSearcher; } 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"); } model.CurrentUser = currentUserProvider.CurrentUser; var pagingModel = new PagedModel { 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 JsonResult 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 JsonResult 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 { 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 { 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 { var model = new EditQuoteModel(quoteService.GetQuote(id)); ResetEditQuoteModel(model); return View(model); } catch (EntityNotFoundException) { return View("QuoteNotFound"); } } [HttpPost, VerifyUser(Group = UserGroup.Admin)] public ActionResult Edit(EditQuoteModel model) { return CreateOrEditQuote(model, "Edit"); } [VerifyUser] public ActionResult Submit() { var model = new EditQuoteModel(); ResetEditQuoteModel(model); return View(model); } [HttpPost, VerifyUser] public ActionResult Submit(EditQuoteModel model) { return CreateOrEditQuote(model, "Submit"); } private ActionResult CreateOrEditQuote(EditQuoteModel model, string viewName) { if (!ModelState.IsValid) { ResetEditQuoteModel(model); return View(viewName, model); } try { var quote = model.QuoteId > 0 ? quoteService.GetQuote(model.QuoteId) : new Quote { Creator = currentUserProvider.CurrentUser }; quote.Game = quoteService.GetGame(model.GameId); quote.Text = model.QuoteText; if (model.CategoryIds != null && model.CategoryIds.Count > 0) { quote.ClearCategories(); foreach (var categoryId in model.CategoryIds) { quote.AddCategory(quoteService.GetCategory(categoryId)); } } if (quote.Game == null) { ResetEditQuoteModel(model); return View(viewName, model); } quote = quoteService.SaveQuote(quote); return RedirectToAction("Quote", new { id = quote.Id, text = quote.GetUrlFriendlyText() }); } catch (Exception e) { ModelState.AddModelError("save", e.Message); ResetEditQuoteModel(model); return View(viewName, model); } } private void ResetEditQuoteModel(EditQuoteModel 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); } public ActionResult Quote(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 }; } } [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); } } }