Compare commits

..

No commits in common. "634cb2d7ee5c7376a56253ce929e8820c2f29f7e" and "91951abe9c5de814d36b8a1f87c11fc0fd056c9b" have entirely different histories.

28 changed files with 47 additions and 219 deletions

View File

@ -141,9 +141,10 @@ std::pair<bool, std::string> CLIHandler::page_list([[maybe_unused]] const std::v
QueryOption o; QueryOption o;
auto result = pageDao->getPageList(o); auto result = pageDao->getPageList(o);
std::stringstream stream; std::stringstream stream;
for(Page &page : result) for(std::string pagename : result)
{ {
stream << page.name << " " << page.pageid << " " << std::string(page.listed ? "listed" : "unlisted") << std::endl; Page p = pageDao->find(pagename).value();
stream << p.name << " " << p.pageid << " " << std::string(p.listed ? "listed" : "unlisted") << std::endl;
} }
return {true, stream.str()}; return {true, stream.str()};
} }
@ -270,9 +271,9 @@ std::pair<bool, std::string> CLIHandler::category_show(const std::vector<std::st
auto categoryDao = this->db->createCategoryDao(); auto categoryDao = this->db->createCategoryDao();
auto members = categoryDao->fetchMembers(args.at(0), QueryOption{}); auto members = categoryDao->fetchMembers(args.at(0), QueryOption{});
std::stringstream stream; std::stringstream stream;
for(Page &member : members) for(std::string &member : members)
{ {
stream << member.name << std::endl; stream << member << std::endl;
} }
return {true, stream.str()}; return {true, stream.str()};
} }

View File

@ -78,9 +78,7 @@ Config::Config(const std::map<std::string, std::string> &map)
this->templatepath = required("templatepath"); this->templatepath = required("templatepath");
this->urls.linkallcats = required("linkallcats"); this->urls.linkallcats = required("linkallcats");
this->urls.linkallpages = required("linkallpages"); this->urls.linkallpages = required("linkallpages");
this->urls.linkallpagesrendertype = required ("linkallpagesrendertype");
this->urls.linkcategory = required("linkcategory"); this->urls.linkcategory = required("linkcategory");
this->urls.linkcategoryrendertype = required("linkcategoryrendertype");
this->urls.linkdelete = required("linkdelete"); this->urls.linkdelete = required("linkdelete");
this->urls.linkedit = required("linkedit"); this->urls.linkedit = required("linkedit");
this->urls.linkhistory = required("linkhistory"); this->urls.linkhistory = required("linkhistory");

View File

@ -23,7 +23,6 @@ struct ConfigUrls
std::string linkindex; std::string linkindex;
std::string linkrecent; std::string linkrecent;
std::string linkallpages; std::string linkallpages;
std::string linkallpagesrendertype;
std::string linkallcats; std::string linkallcats;
std::string linkshere; std::string linkshere;
std::string linkpage; std::string linkpage;
@ -35,7 +34,6 @@ struct ConfigUrls
std::string linkdelete; std::string linkdelete;
std::string linklogout; std::string linklogout;
std::string linkcategory; std::string linkcategory;
std::string linkcategoryrendertype;
std::string loginurl; std::string loginurl;
std::string linkrecentsort; std::string linkrecentsort;
std::string actionurl; std::string actionurl;

View File

@ -5,7 +5,7 @@
#include <optional> #include <optional>
#include "queryoption.h" #include "queryoption.h"
#include "../category.h" #include "../category.h"
#include "../page.h"
class CategoryDao class CategoryDao
{ {
public: public:
@ -14,7 +14,7 @@ class CategoryDao
virtual std::vector<std::string> fetchList(QueryOption o) = 0; virtual std::vector<std::string> fetchList(QueryOption o) = 0;
virtual std::optional<Category> find(std::string name) = 0; virtual std::optional<Category> find(std::string name) = 0;
virtual void deleteCategory(std::string name) = 0; virtual void deleteCategory(std::string name) = 0;
virtual std::vector<Page> fetchMembers(std::string name, QueryOption o) = 0; virtual std::vector<std::string> fetchMembers(std::string name, QueryOption o) = 0;
}; };
#endif // CATEGORYDAO_H #endif // CATEGORYDAO_H

View File

@ -94,10 +94,9 @@ std::vector<std::string> CategoryDaoSqlite::fetchList(QueryOption o)
} }
return result; return result;
} }
std::vector<std::string> CategoryDaoSqlite::fetchMembers(std::string name, QueryOption o)
std::vector<Page> CategoryDaoSqlite::fetchMembers(std::string name, QueryOption o)
{ {
std::vector<Page> result; std::vector<std::string> result;
SqliteQueryOption queryOption{o}; SqliteQueryOption queryOption{o};
std::string queryoptions = std::string queryoptions =
@ -105,18 +104,11 @@ std::vector<Page> CategoryDaoSqlite::fetchMembers(std::string name, QueryOption
try try
{ {
auto query = *db << "SELECT page.id, page.name AS name, page.title, page.lastrevision, page.visible FROM categorymember INNER JOIN page ON page.id = " auto query = *db << "SELECT page.name AS name FROM categorymember INNER JOIN page ON page.id = "
"categorymember.page WHERE category = (SELECT id FROM category WHERE name = ? ) AND " + "categorymember.page WHERE category = (SELECT id FROM category WHERE name = ? ) AND " +
queryoptions queryoptions
<< name; << name;
query >> [&](unsigned int id, std::string name, std::string title, unsigned int lastrevision, bool visible) { query >> [&](std::string p) { result.push_back(p); };
Page p;
p.name = name;
p.pageid = id;
p.title = title;
p.current_revision = lastrevision;
p.listed = visible;
result.push_back(p); };
} }
catch(const sqlite::exceptions::no_rows &e) catch(const sqlite::exceptions::no_rows &e)
{ {

View File

@ -3,13 +3,12 @@
#include "categorydao.h" #include "categorydao.h"
#include "sqlitedao.h" #include "sqlitedao.h"
#include "../page.h"
class CategoryDaoSqlite : public CategoryDao, protected SqliteDao class CategoryDaoSqlite : public CategoryDao, protected SqliteDao
{ {
public: public:
CategoryDaoSqlite(); CategoryDaoSqlite();
std::vector<std::string> fetchList(QueryOption o) override; std::vector<std::string> fetchList(QueryOption o) override;
std::vector<Page> fetchMembers(std::string name, QueryOption o) override; std::vector<std::string> fetchMembers(std::string name, QueryOption o) override;
void save(const Category &c) override; void save(const Category &c) override;
void deleteCategory(std::string name) override; void deleteCategory(std::string name) override;
std::optional<Category> find(std::string name) override; std::optional<Category> find(std::string name) override;

View File

@ -15,7 +15,7 @@ class PageDao
virtual std::optional<Page> find(std::string name) = 0; virtual std::optional<Page> find(std::string name) = 0;
virtual std::optional<Page> findByTitle(std::string title) = 0; virtual std::optional<Page> findByTitle(std::string title) = 0;
virtual std::optional<Page> find(unsigned int id) = 0; virtual std::optional<Page> find(unsigned int id) = 0;
virtual std::vector<Page> getPageList(QueryOption option) = 0; virtual std::vector<std::string> getPageList(QueryOption option) = 0;
virtual std::vector<std::string> fetchCategories(std::string pagename, QueryOption option) = 0; virtual std::vector<std::string> fetchCategories(std::string pagename, QueryOption option) = 0;
virtual void deletePage(std::string page) = 0; virtual void deletePage(std::string page) = 0;
virtual void save(const Page &page) = 0; virtual void save(const Page &page) = 0;

View File

@ -127,28 +127,21 @@ void PageDaoSqlite::save(const Page &page)
throwFrom(e); throwFrom(e);
} }
} }
std::vector<std::string> PageDaoSqlite::getPageList(QueryOption option)
std::vector<Page> PageDaoSqlite::getPageList(QueryOption option)
{ {
std::vector<Page> result; std::vector<std::string> result;
try try
{ {
std::string queryOption = SqliteQueryOption(option) std::string queryOption = SqliteQueryOption(option)
.setOrderByColumn("lower(name)") .setOrderByColumn("lower(name)")
.setVisibleColumnName("visible") .setVisibleColumnName("visible")
.setPrependWhere(true) .setPrependWhere(true)
.build(); .build();
std::string query = "SELECT id, name, title, lastrevision, visible FROM page " + queryOption; std::string query = "SELECT name FROM page " + queryOption;
*db << query >> [&](unsigned int pageid, std::string name, std::string title,unsigned int current_revision, bool visible ) {
Page tmp; *db << query >> [&](std::string name) { result.push_back(name); };
tmp.pageid = pageid;
tmp.name = name;
tmp.title = title;
tmp.current_revision = current_revision;
tmp.listed = visible;
result.push_back(tmp); };
} }
catch(const sqlite::errors::no_rows &e) catch(const sqlite::errors::no_rows &e)
{ {

View File

@ -22,7 +22,7 @@ class PageDaoSqlite : public PageDao, protected SqliteDao
std::optional<Page> find(std::string name) override; std::optional<Page> find(std::string name) override;
std::optional<Page> findByTitle(std::string title) override; std::optional<Page> findByTitle(std::string title) override;
std::optional<Page> find(unsigned int id) override; std::optional<Page> find(unsigned int id) override;
std::vector<Page> getPageList(QueryOption option) override; std::vector<std::string> getPageList(QueryOption option) override;
std::vector<std::string> fetchCategories(std::string pagename, QueryOption option) override; std::vector<std::string> fetchCategories(std::string pagename, QueryOption option) override;
using SqliteDao::SqliteDao; using SqliteDao::SqliteDao;
int fetchPageId(std::string pagename); int fetchPageId(std::string pagename);

View File

@ -10,10 +10,10 @@ std::string DynamicContentPostList::render()
option.includeInvisible = false; option.includeInvisible = false;
auto members = categoryDao->fetchMembers(this->argument, option); auto members = categoryDao->fetchMembers(this->argument, option);
std::vector<std::pair<std::string, time_t>> pageList; std::vector<std::pair<std::string, time_t>> pageList;
for(const Page &member : members) for(std::string &member : members)
{ {
auto revision = revisionDao->getRevisionForPage(member.name, 1); auto revision = revisionDao->getRevisionForPage(member, 1);
pageList.push_back({member.name, revision->timestamp}); pageList.push_back({member, revision->timestamp});
} }
std::sort(pageList.begin(), pageList.end(), std::sort(pageList.begin(), pageList.end(),
[](std::pair<std::string, time_t> &a, std::pair<std::string, time_t> &b) { return a.second > b.second; }); [](std::pair<std::string, time_t> &a, std::pair<std::string, time_t> &b) { return a.second > b.second; });

View File

View File

@ -1,26 +0,0 @@
#include "utils.h"
template<class G, class V, class C>
class Grouper
{
std::map<G, std::vector<const V*>, C> results;
public:
Grouper(C c)
{
results = std::map<G, std::vector<const V*>, C>(c);
}
void group(const std::function<G(const V&)> &map, const std::vector<V> &values)
{
for(const V &v : values)
{
results[map(v)].push_back(&v);
}
}
std::map<G, std::vector<const V*>, C> &getResults()
{
return this->results;
}
};

View File

@ -19,8 +19,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include "handlerallpages.h" #include "handlerallpages.h"
#include "../grouper.h"
#include "../pagelistrenderer.h"
Response HandlerAllPages::handleRequest(const Request &r) Response HandlerAllPages::handleRequest(const Request &r)
{ {
@ -29,21 +27,17 @@ Response HandlerAllPages::handleRequest(const Request &r)
Response response; Response response;
auto pageDao = this->database->createPageDao(); auto pageDao = this->database->createPageDao();
QueryOption qo = queryOption(r); QueryOption qo = queryOption(r);
std::vector<Page> pageList = pageDao->getPageList(qo); auto resultList = pageDao->getPageList(qo);
if(pageList.size() == 0) if(resultList.size() == 0)
{ {
return errorResponse("No pages", "This wiki does not have any pages yet"); return errorResponse("No pages", "This wiki does not have any pages yet");
} }
TemplatePage searchPage = this->templ->getPage("allpages");
PageListRenderer pagelistrender(*this->templ, *this->urlProvider, *this->database); std::string body = this->templ->renderSearch(resultList);
TemplatePage allPages = this->templ->getPage("allpages"); searchPage.setVar("pagelist", body);
allPages.setVar("pagelistcontent", pagelistrender.render(pageList, r.get("rendertype"))); searchPage.setVar("title", createPageTitle("All pages"));
allPages.setVar("pagelistletterlink", this->urlProvider->allPages(PageListRenderer::RENDER_GROUP_BY_LETTER)); setGeneralVars(searchPage);
allPages.setVar("pagelistcreationdatelink", this->urlProvider->allPages(PageListRenderer::RENDER_GROUP_BY_CREATIONDATE)); response.setBody(searchPage.render());
allPages.setVar("title", createPageTitle("All pages"));
setGeneralVars(allPages);
response.setBody(allPages.render());
response.setStatus(200); response.setStatus(200);
return response; return response;
} }

View File

@ -19,7 +19,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include "handlercategory.h" #include "handlercategory.h"
#include "../pagelistrenderer.h"
Response HandlerCategory::handleRequest(const Request &r) Response HandlerCategory::handleRequest(const Request &r)
{ {
@ -35,12 +34,8 @@ Response HandlerCategory::handleRequest(const Request &r)
QueryOption qo = queryOption(r); QueryOption qo = queryOption(r);
auto resultList = categoryDao->fetchMembers(categoryname, qo); auto resultList = categoryDao->fetchMembers(categoryname, qo);
TemplatePage searchPage = this->templ->getPage("show_category"); TemplatePage searchPage = this->templ->getPage("show_category");
PageListRenderer pagelistrender(*this->templ, *this->urlProvider, *this->database); std::string body = this->templ->renderSearch(resultList);
searchPage.setVar("pagelist", body);
std::string body = pagelistrender.render(resultList, r.get("rendertype"));
searchPage.setVar("pagelistcontent", body);
searchPage.setVar("pagelistletterlink", this->urlProvider->category(categoryname, PageListRenderer::RENDER_GROUP_BY_LETTER));
searchPage.setVar("pagelistcreationdatelink", this->urlProvider->category(categoryname, PageListRenderer::RENDER_GROUP_BY_CREATIONDATE));
searchPage.setVar("categoryname", categoryname); searchPage.setVar("categoryname", categoryname);
setGeneralVars(searchPage); setGeneralVars(searchPage);
searchPage.setVar("title", createPageTitle("Category: " + categoryname)); searchPage.setVar("title", createPageTitle("Category: " + categoryname));

View File

@ -10,9 +10,7 @@ std::vector<HandlerFeedGenerator::EntryRevisionPair> HandlerFeedGenerator::fetch
QueryOption option; QueryOption option;
option.includeInvisible = false; option.includeInvisible = false;
// option.limit = 20; // option.limit = 20;
std::set<std::string> members;
auto comppage = [](const Page &a, const Page &b) { return a.name == b.name; };
std::set<Page, decltype(comppage)> members (comppage);
if(categories.empty()) if(categories.empty())
{ {
auto pages = pageDao->getPageList(option); auto pages = pageDao->getPageList(option);
@ -31,10 +29,11 @@ std::vector<HandlerFeedGenerator::EntryRevisionPair> HandlerFeedGenerator::fetch
std::copy(catmembers.begin(), catmembers.end(), std::inserter(members, members.end())); std::copy(catmembers.begin(), catmembers.end(), std::inserter(members, members.end()));
} }
} }
for(const Page &member : members) for(const std::string &member : members)
{ {
auto revision = revisionDao->getRevisionForPage(member.name, 1).value(); auto page = pageDao->find(member).value();
result.push_back({member, revision}); auto revision = revisionDao->getRevisionForPage(page.name, 1).value();
result.push_back({page, revision});
} }
std::sort(result.begin(), result.end(), std::sort(result.begin(), result.end(),
[](EntryRevisionPair &a, EntryRevisionPair &b) { return a.second.timestamp > b.second.timestamp; }); [](EntryRevisionPair &a, EntryRevisionPair &b) { return a.second.timestamp > b.second.timestamp; });

View File

@ -1,66 +0,0 @@
#include "pagelistrenderer.h"
#include "grouper.h"
PageListRenderer::PageListRenderer(Template &templ, UrlProvider &provider, Database &database)
{
this->templ = &templ;
this->urlProvider = &provider;
this->database = &database;
}
std::string PageListRenderer::render(const std::vector<Page> &pagelist, std::string type) const
{
TemplatePage pagelistrendergroup = this->templ->loadResolvedPart("pagelistrender_group");
TemplatePage pagelistlink = this->templ->loadResolvedPart("pagelistrender_link");
std::function<bool(const std::string &, const std::string &)> lesser = [](const std::string &a, const std::string &b) -> bool {
return a < b;
};
std::function<bool(const std::string &, const std::string &)> greater = [](const std::string &a, const std::string &b) -> bool {
return a > b;
};
using Grouper = Grouper<std::string, Page, std::function<bool(const std::string &,const std::string &)>>;
Grouper grouper = (type == "letter") ? Grouper(lesser) : Grouper(greater);
if(type == "letter")
{
auto az = [&](const Page &p) -> std::string {
int upper = toupper(p.title[0]); // TODO: this is not unicode safe.
return { (char)upper };
};
grouper.group(az, pagelist);
}
else
{
auto revisionDao = this->database->createRevisionDao();
auto creationdate = [&revisionDao](const Page &p) -> std::string {
return utils::formatLocalDate(revisionDao->getRevisionForPage(p.name, 1).value().timestamp, "%Y-%m");
};
grouper.group(creationdate, pagelist);
}
std::stringstream stream;
std::string lastGroup = "";
for(auto &entry : grouper.getResults())
{
std::string groupname = entry.first;
const std::vector<const Page*> &pages = entry.second;
if(lastGroup != groupname)
{
lastGroup = groupname;
pagelistrendergroup.setVar("groupname", groupname);
stream << pagelistrendergroup.render();
}
for(const Page *p : pages)
{
pagelistlink.setVar("inner", p->title);
pagelistlink.setVar("href", this->urlProvider->page(p->name));
stream << pagelistlink.render();
}
}
return stream.str();
}

View File

@ -1,27 +0,0 @@
#ifndef PAGELISTRENDERER_H
#define PAGELISTRENDERER_H
#include "utils.h"
#include "page.h"
#include "template.h"
#include "htmllink.h"
#include "urlprovider.h"
#include "database/database.h"
class PageListRenderer
{
private:
Template *templ;
UrlProvider *urlProvider;
Database *database;
public:
PageListRenderer(Template &templ, UrlProvider &provider, Database &database);
std::string render(const std::vector<Page> &pages, std::string type) const;
inline static const std::string RENDER_GROUP_BY_LETTER { "letter" };
inline static const std::string RENDER_GROUP_BY_CREATIONDATE { "creationdate" };
};
#endif

View File

@ -40,7 +40,7 @@ std::pair<std::string, std::string> Request::createPairFromVar(std::string var)
else else
{ {
std::string key = var.substr(0, equal); std::string key = var.substr(0, equal);
std::string val = utils::html_xss(utils::urldecode(var.substr(equal + 1))); std::string val = utils::html_xss(var.substr(equal + 1));
return std::make_pair(std::move(key), std::move(val)); return std::make_pair(std::move(key), std::move(val));
} }
} }

View File

@ -1,6 +1,6 @@
{qswiki:include:general_header} {qswiki:include:general_header}
<div id="content" style="margin-top: 10px;"> <div id="content" style="margin-top: 10px;">
<h2>All pages</h2> <h2>All pages</h2>
{qswiki:include:pagelistrender} {qswiki:var:pagelist}
</div> </div>
{qswiki:include:general_footer} {qswiki:include:general_footer}

View File

@ -1,3 +0,0 @@
{qswiki:include:pagelistrender_header}
{qswiki:var:pagelistcontent}
{qswiki:include:pagelistrender_footer}

View File

@ -1 +0,0 @@
<div class="letter_search_result">{qswiki:var:groupname}</div>

View File

@ -1 +0,0 @@
Sort by: <a href="{qswiki:var:pagelistletterlink}">A-Z</a> - <a href="{qswiki:var:pagelistcreationdatelink}">Creation date</a>

View File

@ -1 +0,0 @@
<a href="{qswiki:var:href}">{qswiki:var:inner}</a><br>

View File

@ -1,6 +1,6 @@
{qswiki:include:general_header} {qswiki:include:general_header}
<main id="content"> <main id="content">
<h2>Category: {qswiki:var:categoryname}</h2> <h2>Category: {qswiki:var:categoryname}</h2>
{qswiki:include:pagelistrender} {qswiki:var:pagelist}
</main> </main>
{qswiki:include:general_footer} {qswiki:include:general_footer}

View File

@ -53,11 +53,6 @@ std::string UrlProvider::allPages()
return config->linkallpages; return config->linkallpages;
} }
std::string UrlProvider::allPages(std::string rendertype)
{
return replaceSingleVar(config->linkallpagesrendertype, "type", rendertype);
}
std::string UrlProvider::allCats() std::string UrlProvider::allCats()
{ {
return config->linkallcats; return config->linkallcats;
@ -126,16 +121,6 @@ std::string UrlProvider::category(std::string catname)
{ {
return replaceSingleVar(config->linkcategory, "category", catname); return replaceSingleVar(config->linkcategory, "category", catname);
} }
std::string UrlProvider::category(std::string catname, std::string rendertype)
{
Varreplacer replace("{");
replace.addKeyValue("category", catname);
replace.addKeyValue("type", rendertype);
return replace.parse(config->linkcategoryrendertype);
}
std::string UrlProvider::login(std::string page) std::string UrlProvider::login(std::string page)
{ {
return replaceOnlyPage(config->loginurl, page); return replaceOnlyPage(config->loginurl, page);

View File

@ -22,7 +22,6 @@ class UrlProvider
std::string recentSorted(unsigned int limit, unsigned int offset, unsigned int sort); std::string recentSorted(unsigned int limit, unsigned int offset, unsigned int sort);
std::string allPages(); std::string allPages();
std::string allPages(std::string rendertype);
std::string allCats(); std::string allCats();
@ -49,7 +48,6 @@ class UrlProvider
std::string refreshSession(); std::string refreshSession();
std::string category(std::string catname); std::string category(std::string catname);
std::string category(std::string catname, std::string rendertype);
std::string login(std::string page); std::string login(std::string page);

View File

@ -136,10 +136,11 @@ std::string utils::getenv(const std::string &key)
std::string utils::readCompleteFile(std::string_view filepath) std::string utils::readCompleteFile(std::string_view filepath)
{ {
std::fstream stream(std::string{filepath}); std::fstream stream(std::string{filepath});
if(!stream.is_open()) if(!stream.is_open())
{ {
throw std::runtime_error("utils::readCompleteFile(): stream is not open"); throw std::runtime_error("stream is not open");
} }
std::stringstream ss; std::stringstream ss;
ss << stream.rdbuf(); ss << stream.rdbuf();