Let's make (git) history!
This commit is contained in:
164
handlers/handlerpageview.cpp
Normal file
164
handlers/handlerpageview.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/* Copyright (c) 2018 Albert S.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "handlerpageview.h"
|
||||
#include "../database/exceptions.h"
|
||||
#include "../logger.h"
|
||||
#include "../parser.h"
|
||||
#include "../htmllink.h"
|
||||
|
||||
bool HandlerPageView::canAccess(std::string page)
|
||||
{
|
||||
return this->userSession->user.permissions.canRead();
|
||||
}
|
||||
|
||||
std::string HandlerPageView::createIndexContent(IParser &parser, std::string content)
|
||||
{
|
||||
std::vector<Headline> headlines = parser.extractHeadlines(content);
|
||||
std::string indexcontent = "";
|
||||
unsigned int l = 0;
|
||||
for(const Headline &h : headlines)
|
||||
{
|
||||
if(h.level > l)
|
||||
{
|
||||
indexcontent += "<ul>";
|
||||
}
|
||||
else if(h.level < l)
|
||||
{
|
||||
indexcontent += "</ul>";
|
||||
}
|
||||
l = h.level;
|
||||
HtmlLink link;
|
||||
link.href = "#" + h.title;
|
||||
link.innervalue = h.title;
|
||||
link.cssclass = "indexlink";
|
||||
indexcontent += "<li>" + link.render() + "</li>";
|
||||
}
|
||||
indexcontent += "</ul>";
|
||||
return indexcontent;
|
||||
}
|
||||
|
||||
Response HandlerPageView::handleRequest(PageDao &pageDao, std::string pagename, const Request &r)
|
||||
{
|
||||
|
||||
std::string revisionparam = r.get("revision");
|
||||
unsigned int revisionid = 0;
|
||||
if(!revisionparam.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
revisionid = utils::toUInt(revisionparam);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
return errorResponse("Error", "Supplied revisionid is misformated");
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Revision> revision;
|
||||
std::string templatepartname;
|
||||
try
|
||||
{
|
||||
if(revisionid > 0)
|
||||
{
|
||||
revision = this->database->createRevisionDao()->getRevisionForPage(pagename, revisionid);
|
||||
if(!revision)
|
||||
{
|
||||
return errorResponse("Revision not found", "No such revision found");
|
||||
}
|
||||
templatepartname = "page_view_revision";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!this->userSession->loggedIn)
|
||||
{
|
||||
auto content = this->cache->get("page:foranon:" + pagename);
|
||||
if(content)
|
||||
{
|
||||
Response r;
|
||||
r.setBody(*content);
|
||||
// TODO: etag?
|
||||
return r;
|
||||
}
|
||||
}
|
||||
revision = this->database->createRevisionDao()->getCurrentForPage(pagename);
|
||||
templatepartname = "page_view";
|
||||
}
|
||||
}
|
||||
catch(const DatabaseException &e)
|
||||
{
|
||||
Logger::error() << "DatabaseException in handlerpageview: " << e.what();
|
||||
return errorResponse("Database error", "While trying to fetch revision, a database error occured");
|
||||
}
|
||||
|
||||
TemplatePage &page = this->templ->getPage(templatepartname);
|
||||
|
||||
Parser parser;
|
||||
Response result;
|
||||
result.setStatus(200);
|
||||
std::string indexcontent;
|
||||
std::string parsedcontent;
|
||||
|
||||
if(revisionid > 0)
|
||||
{
|
||||
indexcontent = createIndexContent(parser, revision->content);
|
||||
parsedcontent = parser.parse(pageDao, *this->urlProvider, revision->content);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string cachekeyindexcontent = "page:indexcontent:" + pagename;
|
||||
std::string cachekeyparsedcontent = "page:parsedcontent:" + pagename;
|
||||
auto cachedindexcontent = this->cache->get(cachekeyindexcontent);
|
||||
auto cachedparsedcontent = this->cache->get(cachekeyparsedcontent);
|
||||
if(cachedindexcontent)
|
||||
{
|
||||
indexcontent = *cachedindexcontent;
|
||||
}
|
||||
else
|
||||
{
|
||||
indexcontent = createIndexContent(parser, revision->content);
|
||||
this->cache->put(cachekeyindexcontent, indexcontent);
|
||||
}
|
||||
if(cachedparsedcontent)
|
||||
{
|
||||
parsedcontent = *cachedparsedcontent;
|
||||
}
|
||||
else
|
||||
{
|
||||
parsedcontent = parser.parse(pageDao, *this->urlProvider, revision->content);
|
||||
this->cache->put(cachekeyparsedcontent, parsedcontent);
|
||||
}
|
||||
}
|
||||
page.setVar("content", parsedcontent);
|
||||
page.setVar("index", indexcontent);
|
||||
page.setVar("editedby", revision->author);
|
||||
page.setVar("editedon", utils::toISODate(revision->timestamp));
|
||||
page.setVar("historyurl", this->urlProvider->pageHistory(pagename));
|
||||
page.setVar("revision", revisionparam);
|
||||
setPageVars(page, pagename);
|
||||
std::string body = page.render();
|
||||
if(revisionid == 0 && !this->userSession->loggedIn)
|
||||
{
|
||||
this->cache->put("page:foranon:" + pagename, body);
|
||||
}
|
||||
result.addHeader("ETAG", std::to_string(revision->revision) + "+" + std::to_string(this->userSession->loggedIn));
|
||||
result.setBody(body);
|
||||
return result;
|
||||
}
|
Посилання в новій задачі
Block a user