'use strict'; let db = require('../db'); let tools = require('../tools'); let shortid = require('shortid'); let segments = require('./segments'); let subscriptions = require('./subscriptions'); let _ = require('../translate')._; let tableHelpers = require('../table-helpers'); const UnsubscriptionMode = { ONE_STEP: 0, ONE_STEP_WITH_FORM: 1, TWO_STEP: 2, TWO_STEP_WITH_FORM: 3, MANUAL: 4, MAX: 5 }; module.exports.UnsubscriptionMode = UnsubscriptionMode; let allowedKeys = ['description', 'default_form', 'public_subscribe', 'unsubscription_mode']; module.exports.list = (start, limit, callback) => { tableHelpers.list('lists', ['*'], 'name', null, start, limit, callback); }; module.exports.filter = (request, parent, callback) => { tableHelpers.filter('lists', ['*'], request, ['#', 'name', 'cid', 'subscribers', 'description'], ['name'], 'name ASC', null, callback); }; module.exports.filterQuicklist = (request, callback) => { tableHelpers.filter('lists', ['id', 'name', 'subscribers'], request, ['#', 'name', 'subscribers'], ['name'], 'name ASC', null, callback); }; module.exports.quicklist = callback => { db.getConnection((err, connection) => { if (err) { return callback(err); } connection.query('SELECT id, name, subscribers FROM lists ORDER BY name LIMIT 1000', (err, rows) => { if (err) { connection.release(); return callback(err); } let lists = (rows || []).map(tools.convertKeys); connection.query('SELECT id, list, name FROM segments ORDER BY list, name LIMIT 1000', (err, rows) => { connection.release(); if (err) { return callback(err); } let segments = (rows || []).map(tools.convertKeys); lists.forEach(list => { list.segments = segments.filter(segment => segment.list === list.id); }); return callback(null, lists); }); }); }); }; module.exports.getListsWithEmail = (email, callback) => { db.getConnection((err, connection) => { if (err) { return callback(err); } connection.query('SELECT id, name FROM lists', (err, rows) => { connection.release(); if (err) { return callback(err); } let lists = (rows || []).map(tools.convertKeys); const results = []; lists.forEach((list, index, arr) => { subscriptions.getByEmail(list.id, email, (err, sub) => { if (sub) { results.push(list.id); } if (index === arr.length - 1) { callback(null, lists.filter(list => results.includes(list.id))); } }); }); }); }); } module.exports.getByCid = (cid, callback) => { resolveCid(cid, (err, id) => { if (err) { return callback(err); } if (!id) { return callback(null, false); } module.exports.get(id, callback); }); }; module.exports.get = (id, callback) => { id = Number(id) || 0; if (id < 1) { return callback(new Error(_('Missing List ID'))); } db.getConnection((err, connection) => { if (err) { return callback(err); } connection.query('SELECT * FROM lists WHERE id=?', [id], (err, rows) => { connection.release(); if (err) { return callback(err); } if (!rows || !rows.length) { return callback(null, false); } let list = tools.convertKeys(rows[0]); segments.list(list.id, (err, segmentList) => { if (err || !segmentList) { segmentList = []; } list.segments = segmentList; return callback(null, list); }); }); }); }; module.exports.update = (id, updates, callback) => { updates = updates || {}; id = Number(id) || 0; if (id < 1) { return callback(new Error(_('Missing List ID'))); } const data = tools.convertKeys(updates); const keys = []; const values = []; // The update can be only partial when executed from forms/:list if (!data.customFormChangeOnly) { data.publicSubscribe = data.publicSubscribe ? 1 : 0; data.unsubscriptionMode = Number(data.unsubscriptionMode); let name = (data.name || '').toString().trim(); if (!name) { return callback(new Error(_('List Name must be set'))); } keys.push('name'); values.push(name); } Object.keys(data).forEach(key => { let value = data[key].toString().trim(); key = tools.toDbKey(key); if (key === 'description') { value = tools.purifyHTML(value); } if (allowedKeys.indexOf(key) >= 0) { keys.push(key); values.push(value); } }); db.getConnection((err, connection) => { if (err) { return callback(err); } values.push(id); connection.query('UPDATE lists SET ' + keys.map(key => key + '=?').join(', ') + ' WHERE id=? LIMIT 1', values, (err, result) => { connection.release(); if (err) { return callback(err); } return callback(null, result && result.affectedRows || false); }); }); }; module.exports.create = (list, callback) => { let data = tools.convertKeys(list); data.publicSubscribe = data.publicSubscribe ? 1 : 0; let name = (data.name || '').toString().trim(); if (!data) { return callback(new Error(_('List Name must be set'))); } let keys = ['name']; let values = [name]; Object.keys(data).forEach(key => { let value = data[key].toString().trim(); key = tools.toDbKey(key); if (key === 'description') { value = tools.purifyHTML(value); } if (allowedKeys.indexOf(key) >= 0) { keys.push(key); values.push(value); } }); let cid = shortid.generate(); keys.push('cid'); values.push(cid); db.getConnection((err, connection) => { if (err) { return callback(err); } let query = 'INSERT INTO lists (`' + keys.join('`, `') + '`) VALUES (' + values.map(() => '?').join(',') + ')'; connection.query(query, values, (err, result) => { connection.release(); if (err) { return callback(err); } let listId = result && result.insertId || false; if (!listId) { return callback(null, false); } createSubscriptionTable(listId, err => { if (err) { // FIXME: rollback return callback(err); } return callback(null, listId); }); }); }); }; module.exports.delete = (id, callback) => { id = Number(id) || 0; if (id < 1) { return callback(new Error(_('Missing List ID'))); } db.getConnection((err, connection) => { if (err) { return callback(err); } connection.query('DELETE FROM lists WHERE id=? LIMIT 1', id, (err, result) => { connection.release(); if (err) { return callback(err); } let affected = result && result.affectedRows || 0; removeSubscriptionTable(id, err => { if (err) { return callback(err); } return callback(null, affected); }); }); }); }; function resolveCid(cid, callback) { cid = (cid || '').toString().trim(); if (!cid) { return callback(new Error(_('Missing List CID'))); } db.getConnection((err, connection) => { if (err) { return callback(err); } connection.query('SELECT id FROM lists WHERE cid=?', [cid], (err, rows) => { connection.release(); if (err) { return callback(err); } return callback(null, rows && rows[0] && rows[0].id || false); }); }); } function createSubscriptionTable(id, callback) { let query = 'CREATE TABLE `subscription__' + id + '` LIKE subscription'; db.getConnection((err, connection) => { if (err) { return callback(err); } connection.query(query, err => { connection.release(); if (err) { return callback(err); } return callback(null, true); }); }); } function removeSubscriptionTable(id, callback) { let query = 'DROP TABLE IF EXISTS `subscription__' + id + '`'; db.getConnection((err, connection) => { if (err) { return callback(err); } connection.query(query, err => { connection.release(); if (err) { return callback(err); } return callback(null, true); }); }); }