Skip to content

Commit

Permalink
sconesite: Support multiple template stores, improve db setup.
Browse files Browse the repository at this point in the history
Support add_templates on sconesite module and individual profiles, to add directories containing templates.
By default load template from /usr/share/sconeserver/sconesite/tpl.
Allow db to be specified directly when creating sconesite profile.
Change default starting template from default.xml to start.xml.
  • Loading branch information
sconemad committed Aug 20, 2015
1 parent 81bb7a1 commit f965006
Show file tree
Hide file tree
Showing 11 changed files with 349 additions and 78 deletions.
2 changes: 2 additions & 0 deletions sconesite/Makefile.am
Expand Up @@ -16,6 +16,7 @@ Heading.cpp \
Profile.cpp \
RenderMarkup.cpp \
Template.cpp \
TemplateManager.cpp \
XMLDoc.cpp

sconesiteincludedir = $(includedir)/sconesite
Expand All @@ -30,6 +31,7 @@ Heading.h \
Profile.h \
RenderMarkup.h \
Template.h \
TemplateManager.h \
XMLDoc.h

sconesite_la_LDFLAGS = -module -avoid-version
Expand Down
119 changes: 69 additions & 50 deletions sconesite/Profile.cpp
Expand Up @@ -52,24 +52,20 @@ Profile::Profile(
SconesiteModule& module,
const std::string& name,
http::Host* host,
const std::string& dbtype
scx::Database* db
) : m_module(module),
m_name(name),
m_host(new http::Host::Ref(host)),
m_db(0)
m_db(new scx::Database::Ref(db)),
m_use_default_templates(true)
{
m_parent = &m_module;

// Open article database
scx::ScriptMap::Ref args(new scx::ScriptMap());
args.object()->give("profile",scx::ScriptString::new_ref(name));
m_db = scx::Database::open(dbtype,&args);

if (!m_db) throw std::exception();

check_database();
configure_docroot("default");
configure_docroot("secure");

m_templates.add(get_path() + TPLDIR);

refresh();
}

Expand All @@ -80,10 +76,6 @@ Profile::~Profile()
it_a != m_articles.end(); ++it_a) {
delete it_a->second;
}
for (TemplateMap::iterator it_t = m_templates.begin();
it_t != m_templates.end(); ++it_t) {
delete it_t->second;
}

delete m_db;
delete m_host;
Expand All @@ -92,36 +84,7 @@ Profile::~Profile()
//=========================================================================
void Profile::refresh()
{
// Add new templates
scx::FileDir dir(get_path() + TPLDIR);
while (dir.next()) {
std::string file = dir.name();
if (file != "." && file != "..") {
std::string::size_type idot = file.find_first_of(".");
if (idot != std::string::npos) {
std::string name = file.substr(0,idot);
std::string extn = file.substr(idot+1,std::string::npos);
if (extn == "xml" && !lookup_template(name)) {
Template* tpl = new Template(*this,name,dir.root());
m_templates[name] = new Template::Ref(tpl);
LOG("Adding template '" + name + "'");
}
}
}
}

// Remove deleted templates
for (TemplateMap::iterator it_t = m_templates.begin();
it_t != m_templates.end();
++it_t) {
Template::Ref* tpl_ref = it_t->second;
Template* tpl = tpl_ref->object();
if (!scx::FileStat(tpl->get_filepath()).is_file()) {
LOG("Removing template '" + tpl->get_name() + "'");
it_t = m_templates.erase(it_t);
delete tpl_ref;
}
}
m_templates.refresh();

// Calculate purge time for cached articles
scx::Date purge_time;
Expand Down Expand Up @@ -532,11 +495,10 @@ bool Profile::rename_article(int id,
//=========================================================================
Template* Profile::lookup_template(const std::string& name)
{
TemplateMap::iterator it = m_templates.find(name);
if (it != m_templates.end()) {
return it->second->object();
}
return 0;
Template* t = m_templates.lookup(name);
if (t) return t;
if (m_use_default_templates) t = m_module.lookup_template(name);
return t;
}

//=========================================================================
Expand All @@ -559,7 +521,9 @@ scx::ScriptRef* Profile::script_op(const scx::ScriptAuth& auth,
"lookup" == name ||
"create_article" == name ||
"remove_article" == name ||
"rename_article" == name) {
"rename_article" == name ||
"add_templates" == name ||
"set_use_default_templates" == name) {
return new scx::ScriptMethodRef(ref,name);
}

Expand All @@ -570,6 +534,9 @@ scx::ScriptRef* Profile::script_op(const scx::ScriptAuth& auth,
if ("path" == name)
return scx::ScriptString::new_ref(get_path().path());

if ("db" == name)
return m_db->ref_copy();

if ("article_cache" == name) {
scx::ScriptList::Ref* list =
new scx::ScriptList::Ref(new scx::ScriptList());
Expand All @@ -588,6 +555,9 @@ scx::ScriptRef* Profile::script_op(const scx::ScriptAuth& auth,
}
return list;
}

if ("use_default_templates" == name)
return scx::ScriptInt::new_ref(m_use_default_templates);
}

return scx::ScriptObject::script_op(auth,ref,op,right);
Expand Down Expand Up @@ -693,6 +663,33 @@ scx::ScriptRef* Profile::script_method(const scx::ScriptAuth& auth,
return 0;
}

if ("add_templates" == name) {
if (!auth.admin()) return scx::ScriptError::new_ref("Not permitted");

const scx::ScriptString* a_path =
scx::get_method_arg<scx::ScriptString>(args,0,"path");
if (!a_path) {
return scx::ScriptError::new_ref("No path specified");
}
m_templates.add(a_path->get_string());

return 0;
}

if ("set_use_default_templates" == name) {
if (!auth.admin()) return scx::ScriptError::new_ref("Not permitted");

const scx::ScriptInt* a_value =
scx::get_method_arg<scx::ScriptInt>(args,0,"value");
if (!a_value) {
return scx::ScriptError::new_ref("No value specified");
}

m_use_default_templates = (a_value->get_int() != 0);

return 0;
}

return scx::ScriptObject::script_method(auth,ref,name,args);
}

Expand Down Expand Up @@ -770,4 +767,26 @@ void Profile::configure_docroot(const std::string& docroot)
}
}

//=============================================================================
void Profile::check_database()
{
if (!m_db) throw std::exception();

// Create article table if not present
if (!m_db->object()->simple_query(
"CREATE TABLE IF NOT EXISTS article ( "
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"parent INTEGER, "
"path VARCHAR(128) )")) {
LOG("Failed to create article table");
}

// Create root article if not present
if (m_db->object()->simple_query_num(
"SELECT COUNT(*) FROM article WHERE id = 1") != 1) {
m_db->object()->simple_query(
"INSERT INTO article (id,parent,path) VALUES (1,0,\"\")");
}
}

};
12 changes: 6 additions & 6 deletions sconesite/Profile.h
Expand Up @@ -23,7 +23,7 @@ Free Software Foundation, Inc.,
#define sconesiteProfile_h

#include <sconesite/Article.h>
#include <sconesite/Template.h>
#include <sconesite/TemplateManager.h>
#include <http/Host.h>
#include <sconex/Stream.h>
#include <sconex/FilePath.h>
Expand All @@ -44,7 +44,7 @@ class Profile : public scx::ScriptObject {
Profile(SconesiteModule& module,
const std::string& name,
http::Host* host,
const std::string& dbtype);
scx::Database* db);

~Profile();

Expand Down Expand Up @@ -117,6 +117,7 @@ class Profile : public scx::ScriptObject {
const std::string& link,
const std::string& type="");

void check_database();
void configure_docroot(const std::string& docroot);

private:
Expand All @@ -139,10 +140,9 @@ class Profile : public scx::ScriptObject {
typedef HASH_TYPE<std::string,int> ArticleLinkMap;
ArticleLinkMap m_article_links;

// Templates
typedef HASH_TYPE<std::string,Template::Ref*> TemplateMap;
TemplateMap m_templates;

TemplateManager m_templates;
bool m_use_default_templates;

scx::Time m_purge_threshold;

};
Expand Down
37 changes: 29 additions & 8 deletions sconesite/SconesiteModule.cpp
Expand Up @@ -169,6 +169,7 @@ void SconesiteModule::provide(const std::string& type,
//=========================================================================
void SconesiteModule::refresh()
{
m_templates.refresh();
for (ProfileMap::iterator it = m_profiles.begin();
it != m_profiles.end();
++it) {
Expand All @@ -184,10 +185,15 @@ Profile* SconesiteModule::lookup_profile(const std::string& profile)
if (it != m_profiles.end()) {
return it->second->object();
}

return 0;
}

//=============================================================================
Template* SconesiteModule::lookup_template(const std::string& name)
{
return m_templates.lookup(name);
}

//=============================================================================
scx::ScriptRef* SconesiteModule::script_op(const scx::ScriptAuth& auth,
const scx::ScriptRef& ref,
Expand All @@ -198,7 +204,8 @@ scx::ScriptRef* SconesiteModule::script_op(const scx::ScriptAuth& auth,
const std::string name = right->object()->get_string();

// Methods
if ("add" == name) {
if ("add" == name ||
"add_templates" == name) {
return new scx::ScriptMethodRef(ref,name);
}

Expand Down Expand Up @@ -254,17 +261,31 @@ scx::ScriptRef* SconesiteModule::script_method(const scx::ScriptAuth& auth,
if (it != m_profiles.end())
return scx::ScriptError::new_ref("Profile already exists");

std::string s_dbtype = "MySQL";
const scx::ScriptString* a_dbtype =
scx::get_method_arg<scx::ScriptString>(args,1,"dbtype");
if (a_dbtype) s_dbtype = a_dbtype->get_string();
scx::Database* a_db =
const_cast<scx::Database*>(
scx::get_method_arg<scx::Database>(args,1,"db"));
if (!a_db)
return scx::ScriptError::new_ref("No database specified");

LOG("Adding profile '" + s_profile + "' dbtype '" + s_dbtype + "'");
Profile* profile = new Profile(*this,s_profile,host,s_dbtype);
LOG("Adding profile '" + s_profile);
Profile* profile = new Profile(*this,s_profile,host,a_db);
m_profiles[s_profile] = new Profile::Ref(profile);

return new Profile::Ref(profile);
}

if ("add_templates" == name) {
if (!auth.admin()) return scx::ScriptError::new_ref("Not permitted");

const scx::ScriptString* a_path =
scx::get_method_arg<scx::ScriptString>(args,0,"path");
if (!a_path) {
return scx::ScriptError::new_ref("No path specified");
}
m_templates.add(a_path->get_string());

return 0;
}

return scx::Module::script_method(auth,ref,name,args);
}
Expand Down
5 changes: 5 additions & 0 deletions sconesite/SconesiteModule.h
Expand Up @@ -46,6 +46,9 @@ class SconesiteModule : public scx::Module,
void refresh();
Profile* lookup_profile(const std::string& name);

// Lookup a template in the standard template stores
Template* lookup_template(const std::string& name);

// Module methods
virtual scx::ScriptRef* script_op(const scx::ScriptAuth& auth,
const scx::ScriptRef& ref,
Expand Down Expand Up @@ -76,6 +79,8 @@ class SconesiteModule : public scx::Module,
typedef HASH_TYPE<std::string,Profile::Ref*> ProfileMap;
ProfileMap m_profiles;

TemplateManager m_templates;

scx::JobID m_job;

};
Expand Down
4 changes: 2 additions & 2 deletions sconesite/SconesiteStream.cpp
Expand Up @@ -303,9 +303,9 @@ scx::Condition SconesiteStream::send_response()
}

// Find the template to use
Template* tpl = m_profile.lookup_template("default");
Template* tpl = m_profile.lookup_template("start");
if (!tpl) {
log("No default template");
log("start template not found");
resp.set_status(http::Status::InternalServerError);
return scx::Close;
}
Expand Down
6 changes: 2 additions & 4 deletions sconesite/Template.cpp
Expand Up @@ -32,13 +32,11 @@ namespace scs {

//=========================================================================
Template::Template(
Profile& profile,
const std::string& name,
const scx::FilePath& path
) : XMLDoc(name,path,name + ".xml"),
m_profile(profile)
) : XMLDoc(name,path,name + ".xml")
{
m_parent = &profile;

}

//=========================================================================
Expand Down
9 changes: 1 addition & 8 deletions sconesite/Template.h
Expand Up @@ -34,20 +34,13 @@ class Template : public XMLDoc {

public:

Template(Profile& profile,
const std::string& name,
Template(const std::string& name,
const scx::FilePath& path);

~Template();

typedef scx::ScriptRefTo<Template> Ref;

protected:

private:

Profile& m_profile;

};

};
Expand Down

0 comments on commit f965006

Please sign in to comment.