/**
* Copyright 2009 Google Inc.
*
* 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
*
* 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.
*/
import("fastJSON");
import("sqlbase.sqlobj");
import("cache_utils.syncedWithCache");
import("stringutils");
import("etherpad.pad.padutils");
import("etherpad.collab.collab_server");
import("etherpad.pro.pro_pad_editors");
import("etherpad.pro.domains");
import("etherpad.pro.pro_accounts.getSessionProAccount");
jimport("java.lang.System.out.println");
// TODO: actually implement the cache part
// NOTE: must return a deep-CLONE of the actual record, because caller
// may proceed to mutate the returned record.
function _makeRecord(r) {
if (!r) {
return null;
}
r.proAttrs = {};
if (r.proAttrsJson) {
r.proAttrs = fastJSON.parse(r.proAttrsJson);
}
if (!r.proAttrs.editors) {
r.proAttrs.editors = [];
}
r.proAttrs.editors.sort();
return r;
}
function getSingleRecord(domainId, localPadId) {
// TODO: make clone
// TODO: use cache
var record = sqlobj.selectSingle('pro_padmeta', {domainId: domainId, localPadId: localPadId});
return _makeRecord(record);
}
function update(padRecord) {
// TODO: use cache
padRecord.proAttrsJson = fastJSON.stringify(padRecord.proAttrs);
delete padRecord.proAttrs;
sqlobj.update('pro_padmeta', {id: padRecord.id}, padRecord);
}
//--------------------------------------------------------------------------------
// create/edit/destory events
//--------------------------------------------------------------------------------
function onCreatePad(pad) {
if (!padutils.isProPad(pad)) { return; }
var data = {
domainId: padutils.getDomainId(pad.getId()),
localPadId: padutils.getLocalPadId(pad),
createdDate: new Date(),
};
if (getSessionProAccount()) {
data.creatorId = getSessionProAccount().id;
}
sqlobj.insert('pro_padmeta', data);
}
// Not a normal part of the UI. This is only called from admin interface,
// and thus should actually destroy all record of the pad.
function onDestroyPad(pad) {
if (!padutils.isProPad(pad)) { return; }
sqlobj.deleteRows('pro_padmeta', {
domainId: padutils.getDomainId(pad.getId()),
localPadId: padutils.getLocalPadId(pad)
});
}
// Called within the context of a comet post.
function onEditPad(pad, padAuthorId) {
if (!padutils.isProPad(pad)) { return; }
var editorId = undefined;
if (getSessionProAccount()) {
editorId = getSessionProAccount().id;
}
if (!(editorId && (editorId > 0))) {
return; // etherpad admins
}
pro_pad_editors.notifyEdit(
padutils.getDomainId(pad.getId()),
padutils.getLocalPadId(pad),
editorId,
new Date()
);
}
//--------------------------------------------------------------------------------
// accessing the pad list.
//--------------------------------------------------------------------------------
function _makeRecordList(lis) {
lis.forEach(function(r) {
r = _makeRecord(r);
});
return lis;
}
function listMyPads() {
var domainId = domains.getRequestDomainId();
var accountId = getSessionProAccount().id;
var padlist = sqlobj.selectMulti('pro_padmeta', {domainId: domainId, creatorId: accountId, isDeleted: false, isArchived: false});
return _makeRecordList(padlist);
}
function listAllDomainPads() {
var domainId = domains.getRequestDomainId();
var padlist = sqlobj.selectMulti('pro_padmeta', {domainId: domainId, isDeleted: false, isArchived: false});
return _makeRecordList(padlist);
}
function listArchivedPads() {
var domainId = domains.getRequestDomainId();
var padlist = sqlobj.selectMulti('pro_padmeta', {domainId: domainId, isDeleted: false, isArchived: true});
return _makeRecordList(padlist);
}
function listPadsByEditor(editorId) {
editorId = Number(editorId);
var domainId = domains.getRequestDomainId();
var padlist = sqlobj.selectMulti('pro_padmeta', {domainId: domainId, isDeleted: false, isArchived: false});
padlist = _makeRecordList(padlist);
padlist = padlist.filter(function(p) {
// NOTE: could replace with binary search to speed things up,
// since we know that editors array is sorted.
return (p.proAttrs.editors.indexOf(editorId) >= 0);
});
return padlist;
}
function listLiveDomainPads() {
var thisDomainId = domains.getRequestDomainId();
var allLivePadIds = collab_server.getAllPadsWithConnections();
var livePadMap = {};
allLivePadIds.forEach(function(globalId) {
if (padutils.isProPadId(globalId)) {
var domainId = padutils.getDomainId(globalId);
var localId = padutils.globalToLocalId(globalId);
if (domainId == thisDomainId) {
livePadMap[localId] = true;
}
}
});
var padList = listAllDomainPads();
padList = padList.filter(function(p) {
return (!!livePadMap[p.localPadId]);
});
return padList;
}
//--------------------------------------------------------------------------------
// misc utils
//--------------------------------------------------------------------------------
function _withCache(name, fn) {
return syncedWithCache('pro-padmeta.'+name, fn);
}
function _withDomainCache(domainId, name, fn) {
return _withCache(name+"."+domainId, fn);
}
// returns the next pad ID to use for a newly-created pad on this domain.
function getNextPadId() {
var domainId = domains.getRequestDomainId();
return _withDomainCache(domainId, 'padcounters', function(c) {
var ret;
if (c.x === undefined) {
c.x = _getLargestNumericPadId(domainId) + 1;
}
while (sqlobj.selectSingle('pro_padmeta', {domainId: domainId, localPadId: String(c.x)})) {
c.x++;
}
ret = c.x;
c.x++;
return ret;
});
}
function _getLargestNumericPadId(domainId) {
var max = 0;
var allPads = listAllDomainPads();
allPads.forEach(function(p) {
if (stringutils.isNumeric(p.localPadId)) {
max = Math.max(max, Number(p.localPadId));
}
});
return max;
}