Begin HandlerFeedGenerator: Generates Atom feeds for categories (or all pages)
This commit is contained in:
parent
16c352c6af
commit
4854ea85f2
129
handlers/handlerfeedgenerator.cpp
Normal file
129
handlers/handlerfeedgenerator.cpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#include "handlerfeedgenerator.h"
|
||||||
|
#include "../parser.h"
|
||||||
|
std::vector<HandlerFeedGenerator::EntryRevisionPair> HandlerFeedGenerator::fetchEntries(
|
||||||
|
std::vector<std::string> categories)
|
||||||
|
{
|
||||||
|
auto revisionDao = this->database->createRevisionDao();
|
||||||
|
auto pageDao = this->database->createPageDao();
|
||||||
|
|
||||||
|
std::vector<EntryRevisionPair> result;
|
||||||
|
QueryOption option;
|
||||||
|
option.includeInvisible = false;
|
||||||
|
// option.limit = 20;
|
||||||
|
std::set<std::string> members;
|
||||||
|
if(categories.empty())
|
||||||
|
{
|
||||||
|
auto pages = pageDao->getPageList(option);
|
||||||
|
std::copy(pages.begin(), pages.end(), std::inserter(members, members.end()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto categoryDao = this->database->createCategoryDao();
|
||||||
|
for(std::string cat : categories)
|
||||||
|
{
|
||||||
|
auto catmembers = categoryDao->fetchMembers(cat, option);
|
||||||
|
std::copy(catmembers.begin(), catmembers.end(), std::inserter(members, members.end()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(const std::string &member : members)
|
||||||
|
{
|
||||||
|
auto page = pageDao->find(member).value();
|
||||||
|
auto revision = revisionDao->getRevisionForPage(page.name, 1).value();
|
||||||
|
result.push_back({page, revision});
|
||||||
|
}
|
||||||
|
std::sort(result.begin(), result.end(),
|
||||||
|
[](EntryRevisionPair &a, EntryRevisionPair &b) { return a.second.timestamp > b.second.timestamp; });
|
||||||
|
|
||||||
|
const int maxResults = 20;
|
||||||
|
if(result.size() > maxResults)
|
||||||
|
{
|
||||||
|
result.erase(result.begin() + maxResults - 1, result.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Response HandlerFeedGenerator::generateAtom(const std::vector<HandlerFeedGenerator::EntryRevisionPair> &entries,
|
||||||
|
std::string filter)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::stringstream stream;
|
||||||
|
// don't care about offset for now especially since "%z" does not return what we need exactly (with ':')
|
||||||
|
const std::string dateformat = "%Y-%m-%dT%T";
|
||||||
|
|
||||||
|
time_t newestPublished = 0;
|
||||||
|
std::string atomfooter = this->templ->loadResolvedPart("feeds/atomfooter");
|
||||||
|
auto revisionDao = this->database->createRevisionDao();
|
||||||
|
auto pageDao = this->database->createPageDao();
|
||||||
|
|
||||||
|
if(utils::trim(filter).empty())
|
||||||
|
{
|
||||||
|
filter = "All pages";
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const EntryRevisionPair &entry : entries)
|
||||||
|
{
|
||||||
|
const Page &page = entry.first;
|
||||||
|
const Revision &initialRevision = entry.second;
|
||||||
|
Revision current = revisionDao->getCurrentForPage(page.name).value();
|
||||||
|
std::string url = this->urlProvider->rootUrl() + this->urlProvider->page(page.name);
|
||||||
|
if(initialRevision.timestamp > newestPublished)
|
||||||
|
{
|
||||||
|
newestPublished = initialRevision.timestamp;
|
||||||
|
}
|
||||||
|
std::string entryPublished = utils::formatLocalDate(initialRevision.timestamp, dateformat) + "Z";
|
||||||
|
std::string entryurl =
|
||||||
|
this->urlProvider->combine({this->urlProvider->rootUrl(), this->urlProvider->page(page.name)});
|
||||||
|
TemplatePage atomentry = this->templ->getPage("feeds/atomentry");
|
||||||
|
atomentry.setVar("entrytitle", utils::html_xss(page.title));
|
||||||
|
atomentry.setVar("entryurl", utils::html_xss(entryurl));
|
||||||
|
atomentry.setVar("entryid", utils::html_xss(entryurl));
|
||||||
|
atomentry.setVar("entrypublished", entryPublished);
|
||||||
|
Parser parser;
|
||||||
|
atomentry.setVar("entrycontent", utils::html_xss(parser.parse(*pageDao, *this->urlProvider, current.content)));
|
||||||
|
stream << atomentry.render();
|
||||||
|
}
|
||||||
|
stream << atomfooter;
|
||||||
|
TemplatePage atomheader = this->templ->getPage("feeds/atomheader");
|
||||||
|
atomheader.setVar("subtitle", filter);
|
||||||
|
atomheader.setVar("atomfeeduniqueid", utils::html_xss(this->urlProvider->atomFeed(filter)));
|
||||||
|
atomheader.setVar("atomfeedupdate", utils::formatLocalDate(newestPublished, dateformat) + "Z");
|
||||||
|
|
||||||
|
Response result;
|
||||||
|
result.setStatus(200);
|
||||||
|
result.setContentType("application/atom+xml");
|
||||||
|
result.setBody(atomheader.render() + stream.str());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Response HandlerFeedGenerator::handleRequest(const Request &r)
|
||||||
|
{
|
||||||
|
Response response;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::string type = r.get("type");
|
||||||
|
std::string categories = r.get("cats");
|
||||||
|
|
||||||
|
auto entries = fetchEntries(utils::split(categories, ','));
|
||||||
|
if(type == "atom")
|
||||||
|
{
|
||||||
|
std::string filter = categories;
|
||||||
|
response = generateAtom(entries, filter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return errorResponse("Invalid feed type", "Unknown feed type, try atom", 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(std::runtime_error &e)
|
||||||
|
{
|
||||||
|
Logger::error() << "Error while serving feed: " << e.what();
|
||||||
|
return errorResponse("Error", "An error occured while trying to serve the feed", 500);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HandlerFeedGenerator::canAccess(const Permissions &perms)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
21
handlers/handlerfeedgenerator.h
Normal file
21
handlers/handlerfeedgenerator.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef HANDLERFEEDGENERATOR_H
|
||||||
|
#define HANDLERFEEDGENERATOR_H
|
||||||
|
#include "handler.h"
|
||||||
|
#include "../page.h"
|
||||||
|
#include "../revision.h"
|
||||||
|
class HandlerFeedGenerator : public Handler
|
||||||
|
{
|
||||||
|
typedef std::pair<Page, Revision> EntryRevisionPair;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<EntryRevisionPair> fetchEntries(std::vector<std::string> categories);
|
||||||
|
Response generateAtom(const std::vector<EntryRevisionPair> &entries, std::string atomtitle);
|
||||||
|
Response generateRss(const std::vector<EntryRevisionPair> &entries);
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Handler::Handler;
|
||||||
|
Response handleRequest(const Request &r) override;
|
||||||
|
bool canAccess(const Permissions &perms) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HANDLERFEEDGENERATOR_H
|
Loading…
Reference in New Issue
Block a user