antville/code/Global/Exporter.js

400 lines
15 KiB
JavaScript
Raw Normal View History

// The Antville Project
// http://code.google.com/p/antville
//
// Copyright 20012014 by the Workers of Antville.
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
2014-07-04 15:32:18 +02:00
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileOverview Defines the Exporter namespace.
*/
global.Exporter = (function() {
const addMetadata = (object, Prototype) => {
object.metadata = {};
const sql = new Sql();
sql.retrieve("select name, value, type from metadata where parent_type = '$0' and parent_id = $1 order by lower(name)", Prototype.name, object.id);
sql.traverse(function() {
object.metadata[this.name] = global[this.type](this.value).valueOf();
});
return object;
};
const addImage = function(type, index) {
app.log('Exporting ' + type + ' image #' + this.id);
const image = Image.getById(this.id);
if (image) {
this.href = image.href();
addMetadata(this, Image);
index.images.push(this);
} else {
app.logger.warn('Could not export Image #' + this.id + '; might be a cache problem');
}
};
const addAssets = (site, zip) => {
const dir = site.getStaticFile();
if (dir.exists()) zip.add(dir, site.name);
};
/**
* The Exporter namespace provides methods for exporting a site.
* @namespace
*/
const Exporter = {}
/**
* Exports a site with the specified users content
* The created XML file will be added to the sites file collection.
* @param {Site} site The site to export.
* @param {User} user The user whose content will be exported.
*/
Exporter.run = function(target, user) {
switch (target.constructor) {
case Site:
Exporter.saveSite(target, user);
break;
case User:
Exporter.saveAccount(target);
break;
2014-07-04 15:32:18 +02:00
}
};
Exporter.saveSite = function(site, user) {
const sql = new Sql();
const zip = new helma.Zip();
const fileName = 'antville-site-' + java.util.UUID.randomUUID() + '.zip';
try {
if (site.export) {
let file = File.getById(site.export);
if (file) File.remove.call(file);
}
const index = {
comments: [],
files: [],
images: [],
members: [],
polls: [],
sites: [],
skins: [],
stories: []
};
sql.retrieve('select s.*, c.name as creator_name, m.name as modifier_name from site s, account c, account m where s.id = $0 and s.creator_id = c.id and s.modifier_id = m.id order by lower(s.name)', site._id);
sql.traverse(function() {
app.log('Exporting site #' + this.id + ' (' + this.name + ')');
const site = Site.getById(this.id);
this.href = site.href();
addAssets(site, zip);
addMetadata(this, Site);
index.sites.push(this);
const skinsSql = new Sql();
sql.retrieve('select * from skin where site_id = $0', this.id);
sql.traverse(function() {
app.log('Exporting skin #' + this.id);
index.skins.push(this);
});
});
sql.retrieve('select m.*, c.name as creator_name, mod.name as modifier_name from site s, membership m, account c, account mod where s.id = $0 and s.id = m.site_id and m.creator_id = c.id and m.modifier_id = mod.id order by lower(m.name)', site._id);
sql.traverse(function() {
app.log('Exporting membership #' + this.creator_id);
index.members.push(this);
});
sql.retrieve('select c.*, crt.name as creator_name, m.name as modifier_name from content c, account crt, account m where c.site_id = $0 and c.creator_id = crt.id and c.modifier_id = m.id order by created desc', site._id);
sql.traverse(function() {
app.log('Exporting story #' + this.id);
const content = Story.getById(this.id);
this.href = content.href();
addMetadata(this, Story);
this.rendered = content.format_filter(this.metadata.text, {}, 'markdown');
if (this.prototype === 'Story') {
index.stories.push(this);
} else {
index.comments.push(this);
}
});
sql.retrieve('select f.*, c.name as creator_name, m.name as modifier_name from file f, account c, account m where f.site_id = $0 and f.creator_id = c.id and f.modifier_id = m.id order by created desc', site._id);
sql.traverse(function() {
app.log('Exporting file #' + this.id);
const file = File.getById(this.id);
this.href = file.href();
addMetadata(this, File);
index.files.push(this);
});
sql.retrieve("select i.*, c.name as creator_name, m.name as modifier_name from image i, account c, account m where i.parent_type = 'Site' and i.parent_id = $0 and i.creator_id = c.id and i.modifier_id = m.id order by created desc", site._id);
sql.traverse(function() {
addImage.call(this, 'site', index);
});
sql.retrieve("select i.*, c.name as creator_name, m.name as modifier_name from image i, layout l, account c, account m where i.parent_type = 'Layout' and i.parent_id = l.id and l.site_id = $0 and i.creator_id = c.id and i.modifier_id = m.id order by created desc", site._id);
sql.traverse(function() {
addImage.call(this, 'layout', index);
});
sql.retrieve('select p.*, c.name as creator_name, m.name as modifier_name from poll p, account c, account m where p.site_id = $0 and p.creator_id = c.id and p.modifier_id = m.id order by created desc', site._id);
sql.traverse(function() {
app.log('Exporting poll #' + this.id);
const poll = Poll.getById(this.id);
this.href = poll.href();
this.choices = poll.list().map(choice => {
return {
id: choice._id,
title: choice.title,
votes: choice.size()
};
});
addMetadata(this, Poll);
index.polls.push(this);
});
const json = JSON.stringify(index);
const data = new java.lang.String(json).getBytes('UTF-8');
zip.addData(data, 'index.json');
var xml = Exporter.getSiteXml(site, user);
zip.addData(xml, site.name + '-export.xml');
zip.close();
const mime = {
file: new Packages.helma.util.MimePart(fileName, zip.getData(), 'application/zip'),
file_origin: site.href('export')
};
const file = File.add(mime, site, user);
site.export = file._id;
} catch (ex) {
app.log(ex.rhinoException);
}
// Reset the sites export status
site.job = null;
return;
};
Exporter.saveAccount = account => {
const zip = new helma.Zip();
const sql = new Sql();
const dirName = app.appsProperties['static'] + '/export';
const fileName = 'antville-account-' + java.util.UUID.randomUUID() + '.zip';
const dir = new java.io.File(dirName);
const file = new java.io.File(dir, fileName);
if (!dir.exists()) dir.mkdirs();
if (account.export) {
const archive = new java.io.File(dirName, account.export.split('/').pop());
if (archive.exists()) archive['delete']();
}
const index = {
accounts: [],
comments: [],
files: [],
images: [],
memberships: [],
polls: [],
sites: [],
skins: [],
stories: []
};
sql.retrieve("select * from account where id = $0", account._id);
// Cannot really include other accounts with the same e-mail address because we do not verify e-mail addresses
//sql.retrieve("select * from account where email = '$0' order by lower(name)", account.email);
sql.traverse(function() {
app.log('Exporting account #' + this.id + ' (' + this.name + ')');
addMetadata(this, User);
index.accounts.push(this);
});
sql.retrieve("select s.*, m.role, c.name as creator_name, mod.name as modifier_name from site s, membership m, account c, account mod where m.creator_id = $0 and m.site_id = s.id and s.creator_id = c.id and s.modifier_id = mod.id order by lower(s.name)", account._id);
sql.traverse(function() {
app.log('Exporting site #' + this.id + ' (' + this.name + ')');
const site = Site.getById(this.id);
this.href = site.href();
if (this.role === Membership.OWNER) addMetadata(this, Site);
index.sites.push(this);
});
sql.retrieve('select s.*, m.name as modifier_name from skin s, account m where s.creator_id = $0 and s.modifier_id = m.id', account._id);
sql.traverse(function() {
app.log('Exporting skin #' + this.id);
index.skins.push(this);
});
sql.retrieve('select m.*, mod.name as modifier_name from site s, membership m, account mod where m.creator_id = $0 and s.id = m.site_id and m.modifier_id = mod.id order by lower(m.name)', account._id);
sql.traverse(function() {
app.log('Exporting membership #' + this.id);
this.creator_name = account.name;
index.memberships.push(this);
});
sql.retrieve('select c.*, m.name as modifier_name from content c, account m where creator_id = $0 and c.modifier_id = m.id order by c.created desc', account._id);
sql.traverse(function() {
app.log('Exporting story #' + this.id);
const content = Story.getById(this.id);
this.href = content.href();
this.creator_name = account.name;
addMetadata(this, Story);
this.rendered = content.format_filter(this.metadata.text, {}, 'markdown');
if (this.prototype === 'Story') {
index.stories.push(this);
} else {
index.comments.push(this);
}
});
sql.retrieve('select f.*, m.name as modifier_name from file f, account m where f.creator_id = $0 and f.modifier_id = m.id order by f.created desc', account._id);
sql.traverse(function() {
app.log('Exporting file #' + this.id);
const file = File.getById(this.id);
const asset = file.getFile();
if (asset.exists()) zip.add(asset, file.site.name + '/files');
this.href = file.href();
this.creator_name = account.name;
addMetadata(this, File);
index.files.push(this);
});
sql.retrieve('select i.*, m.name as modifier_name from image i, account m where i.creator_id = $0 and i.modifier_id = m.id order by i.created desc', account._id);
sql.traverse(function() {
app.log('Exporting image #' + this.id);
const image = Image.getById(this.id);
if (image) {
try {
const asset = image.getFile();
const path = this.parent_type === 'Layout' ? image.parent.site.name + '/layout' : image.parent.name + '/images';
if (asset.exists()) zip.add(asset, path);
} catch (ex) {
console.warn('Could not export image #' + this.id);
console.warn(ex.rhinoException);
}
this.href = image.href();
this.creator_name = account.name;
addMetadata(this, Image);
index.images.push(this);
} else {
app.logger.warn('Could not export Image #' + this.id + '; might be a cache problem');
}
});
sql.retrieve('select p.*, m.name as modifier_name from poll p, account m where p.creator_id = $0 and p.modifier_id = m.id order by p.created desc', account._id);
sql.traverse(function() {
app.log('Exporting poll #' + this.id);
const poll = Poll.getById(this.id);
this.href = poll.href();
this.creator_name = account.name;
this.choices = poll.list().map(choice => {
return {
id: choice._id,
title: choice.title,
votes: choice.size()
};
});
const vote = poll.votes.get(account.name);
if (vote) this.vote = vote.choice._id;
addMetadata(this, Poll);
index.polls.push(this);
});
const json = JSON.stringify(index);
const data = new java.lang.String(json).getBytes('UTF-8');
zip.addData(data, 'index.json');
zip.save(file);
account.export = app.appsProperties.staticMountpoint + '/export/' + fileName;
account.job = null;
return zip;
};
Exporter.getSiteXml = (site, user) => {
var rssUrl = site.href('rss.xml');
2014-07-04 15:32:18 +02:00
var baseDir = site.getStaticFile();
var member = site.members.get(user.name);
2015-05-25 22:05:11 +02:00
var xml = [];
2014-07-04 15:32:18 +02:00
var add = function(s) {
2015-05-25 22:05:11 +02:00
return xml.push(s);
};
2014-07-04 15:32:18 +02:00
add('<?xml version="1.0" encoding="UTF-8"?>');
add('<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>');
add('<feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:thr="http://purl.org/syndication/thread/1.0">');
add('<id>tag:blogger.com,1999:blog-' + site._id + '.archive</id>');
add('<updated>' + site.modified.format(Date.ISOFORMAT) + '</updated>');
add('<title type="text">' + encodeXml(site.title) + '</title>');
add('<link rel="http://schemas.google.com/g/2005#feed" type="application/rss+xml" href="' + rssUrl + '"/>');
add('<link rel="self" type="application/rss+xml" href="' + rssUrl + '"/>');
add('<link rel="http://schemas.google.com/g/2005#post" type="application/rss+xml" href="' + rssUrl + '"/>');
add('<link rel="alternate" type="text/html" href="' + site.href() + '"/>');
add('<author>');
add('<name>' + site.creator.name + '</name>');
add('<email>' + site.creator.email + '</email>');
add('</author>');
// Currently, blogger.com does not accept other generators
//add('<generator version="' + Root.VERSION + '" uri="' + root.href() + '">Antville</generator>');
add('<generator version="7.00" uri="http://www.blogger.com">Blogger</generator>');
member.stories.forEach(function() {
add('<entry>');
add('<id>tag:blogger.com,1999:blog-' + site._id + '.post-' + this._id + '</id>');
add('<published>' + this.created.format(Date.ISOFORMAT) + '</published>');
add('<updated>' + this.modified.format(Date.ISOFORMAT) + '</updated>');
add('<title type="text">' + (this.title ? encodeXml(this.title.stripTags()) : '') + '</title>');
add('<content type="html">' + encodeXml(this.format_filter(this.text, {})) + '</content>');
add('<link rel="alternate" type="text/html" href="' + this.href() + '"></link>');
add('<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/blogger/2008/kind#post"/>');
add('<author>');
2014-07-04 15:32:18 +02:00
add('<name>' + this.creator.name + '</name>');
this.creator.url && add('<uri>' + this.creator.url + '</uri>');
add('<email>' + this.creator.email + '</email>');
add('</author>');
2014-07-04 15:32:18 +02:00
add('</entry>');
});
add('</feed>');
return java.lang.String(xml.join(String.EMPTY)).getBytes('utf-8');
2018-05-04 17:02:00 +02:00
};
return Exporter;
})();