Refactored Custom Form Table Structure

This commit is contained in:
witzig 2017-03-20 19:37:09 +01:00
parent 477aff95d5
commit c3ee53bd4b
3 changed files with 178 additions and 84 deletions

View file

@ -204,49 +204,7 @@ function applyUpdate(update, callback) {
});
}
function verifyInnodbFileFormat(callback) {
db.getConnection((err, connection) => {
if (err) {
return callback(err);
}
connection.query('SELECT @@GLOBAL.innodb_file_format as value', [], (err, rows) => {
if (err) {
return callback(err);
}
let format = rows && rows[0] && rows[0].value;
if (!format || format.toLowerCase() !== 'barracuda') {
log.warn('sql', 'Temporary setting innodb_file_format to barracuda');
log.warn('sql', 'Please modify the [mysqld] section of your my.cnf');
log.warn('sql', '------------------------------');
log.warn('sql', '[mysqld]');
log.warn('sql', 'innodb_file_per_table = 1');
log.warn('sql', 'innodb_file_format = barracuda');
log.warn('sql', '------------------------------');
connection.query('SET GLOBAL innodb_file_per_table = 1; SET GLOBAL innodb_file_format = Barracuda', [], err => {
connection.release();
if (err) {
return callback(err);
}
callback(null);
});
} else {
return callback(null);
}
});
});
}
module.exports = callback => {
verifyInnodbFileFormat(err => {
if (err) {
return callback(err);
}
runUpdates(err => {
if (err) {
return callback(err);
@ -256,5 +214,4 @@ module.exports = callback => {
return callback(null, true);
});
});
});
};

View file

@ -42,8 +42,7 @@ module.exports.list = (listId, callback) => {
return callback(err);
}
let query = 'SELECT * FROM custom_forms WHERE list=? ORDER BY id';
connection.query(query, [listId], (err, rows) => {
connection.query('SELECT * FROM custom_forms WHERE list=? ORDER BY id', [listId], (err, rows) => {
connection.release();
if (err) {
return callback(err);
@ -67,17 +66,34 @@ module.exports.get = (id, callback) => {
return callback(err);
}
let query = 'SELECT * FROM custom_forms WHERE id=? LIMIT 1';
connection.query(query, [id], (err, rows) => {
connection.query('SELECT * FROM custom_forms WHERE id=? LIMIT 1', [id], (err, rows) => {
if (err) {
connection.release();
return callback(err);
}
let form = rows && rows[0] && tools.convertKeys(rows[0]) || false;
if (!form) {
connection.release();
return callback(new Error('Selected form not found'));
}
connection.query('SELECT * FROM custom_forms_data WHERE form=?', [id], (err, data_rows = []) => {
connection.release();
if (err) {
return callback(err);
}
let form = rows && rows[0] && tools.convertKeys(rows[0]) || false;
data_rows.forEach(data_row => {
let modelKey = tools.fromDbKey(data_row.data_key);
form[modelKey] = data_row.data_value;
});
return callback(null, form);
});
});
});
};
@ -116,15 +132,66 @@ module.exports.create = (listId, form, callback) => {
return callback(err);
}
let query = 'INSERT INTO custom_forms (' + keys.join(', ') + ') VALUES (' + values.map(() => '?').join(',') + ')';
connection.query(query, values, (err, result) => {
let filtered = filterKeysAndValues(keys, values, 'exclude', ['mail_', 'web_']);
let query = 'INSERT INTO custom_forms (' + filtered.keys.join(', ') + ') VALUES (' + filtered.values.map(() => '?').join(',') + ')';
connection.query(query, filtered.values, (err, result) => {
connection.release();
if (err) {
return callback(err);
}
let formId = result && result.insertId || false;
return callback(null, formId);
let formId = result && result.insertId;
if (!formId) {
return callback(new Error('Invalid custom_forms insertId'));
}
let jobs = 1;
let error = null;
let done = err => {
jobs--;
error = err ? err : error; // One's enough
jobs === 0 && callback(error, formId)
};
filtered = filterKeysAndValues(keys, values, 'include', ['mail_', 'web_']);
filtered.keys.forEach((key, index) => {
jobs++;
db.getConnection((err, connection) => {
if (err) {
return done(err);
}
connection.query('INSERT INTO custom_forms_data (form, data_key, data_value) VALUES (?, ?, ?)', [formId, key, filtered.values[index]], (err, result) => {
if (err) {
connection.release();
return done(err);
}
let dataId = result && result.insertId;
if (!dataId) {
connection.release();
return done(new Error('Invalid custom_forms_data insertId'));
}
connection.query('UPDATE custom_forms SET `' + key + '`=? WHERE id=?', [dataId, formId], (err, result) => {
connection.release();
if (err) {
return done(err);
}
return done(null);
});
});
});
});
done(null);
});
});
};
@ -163,21 +230,61 @@ module.exports.update = (id, updates, callback) => {
return callback(err);
}
values.push(id);
let filtered = filterKeysAndValues(keys, values, 'exclude', ['mail_', 'web_']);
let query = 'UPDATE custom_forms SET ' + filtered.keys.map(key => '`' + key + '`=?').join(', ') + ' WHERE id=? LIMIT 1';
connection.query('UPDATE custom_forms SET ' + keys.map(key => '`' + key + '`=?').join(', ') + ' WHERE id=? LIMIT 1', values, (err, result) => {
connection.query(query, filtered.values.concat(id), (err, result) => {
connection.release();
if (err) {
return callback(err);
}
let affectedRows = result && result.affectedRows;
let jobs = 1;
let error = null;
let done = err => {
jobs--;
error = err ? err : error; // One's enough
if (jobs === 0) {
if (error) {
return callback(error);
}
// Save then validate, as otherwise their work get's lost ...
err = testForMjmlErrors(keys, values);
if (err) {
return callback(err);
}
return callback(null, result && result.affectedRows || false);
return callback(null, affectedRows);
}
};
filtered = filterKeysAndValues(keys, values, 'include', ['mail_', 'web_']);
filtered.keys.forEach((key, index) => {
jobs++;
db.getConnection((err, connection) => {
if (err) {
return done(err);
}
connection.query('UPDATE custom_forms_data SET data_value=? WHERE data_key=? AND form=?', [filtered.values[index], key, id], (err, result) => {
connection.release();
if (err) {
return done(err);
}
return done(null);
});
});
});
done(null);
});
});
};
@ -194,8 +301,7 @@ module.exports.delete = (formId, callback) => {
return callback(err);
}
let query = 'SELECT * FROM custom_forms WHERE id=? LIMIT 1';
connection.query(query, [formId], (err, rows) => {
connection.query('SELECT * FROM custom_forms WHERE id=? LIMIT 1', [formId], (err, rows) => {
if (err) {
connection.release();
return callback(err);
@ -243,6 +349,26 @@ function setDefaultValues(form) {
return form;
}
function filterKeysAndValues(keysIn, valuesIn, method = 'include', prefixes = []) {
let values = [];
let prefixMatch = key => (
prefixes.some(prefix => key.startsWith(prefix))
);
let keys = keysIn.filter((key, index) => {
if ((method === 'include' && prefixMatch(key)) || (method === 'exclude' && !prefixMatch(key))) {
values.push(valuesIn[index]);
return true;
}
return false;
});
return {
keys,
values
};
}
function testForMjmlErrors(keys, values) {
let testLayout = '<mjml><mj-body><mj-container>{{{body}}}</mj-container></mj-body></mjml>';

View file

@ -10,27 +10,38 @@ CREATE TABLE `custom_forms` (
`description` text,
`fields_shown_on_subscribe` varchar(255) DEFAULT '',
`fields_shown_on_manage` varchar(255) DEFAULT '',
`layout` mediumtext,
`form_input_style` mediumtext,
`mail_confirm_html` text,
`mail_confirm_text` text,
`mail_subscription_confirmed_html` text,
`mail_subscription_confirmed_text` text,
`mail_unsubscribe_confirmed_html` text,
`mail_unsubscribe_confirmed_text` text,
`web_confirm_notice` text,
`web_manage_address` text,
`web_manage` text,
`web_subscribe` text,
`web_subscribed` text,
`web_unsubscribe_notice` text,
`web_unsubscribe` text,
`web_updated_notice` text,
`layout` longtext,
`form_input_style` longtext,
`mail_confirm_html` int(11) unsigned DEFAULT NULL,
`mail_confirm_text` int(11) unsigned DEFAULT NULL,
`mail_subscription_confirmed_html` int(11) unsigned DEFAULT NULL,
`mail_subscription_confirmed_text` int(11) unsigned DEFAULT NULL,
`mail_unsubscribe_confirmed_html` int(11) unsigned DEFAULT NULL,
`mail_unsubscribe_confirmed_text` int(11) unsigned DEFAULT NULL,
`web_confirm_notice` int(11) unsigned DEFAULT NULL,
`web_manage_address` int(11) unsigned DEFAULT NULL,
`web_manage` int(11) unsigned DEFAULT NULL,
`web_subscribe` int(11) unsigned DEFAULT NULL,
`web_subscribed` int(11) unsigned DEFAULT NULL,
`web_unsubscribe_notice` int(11) unsigned DEFAULT NULL,
`web_unsubscribe` int(11) unsigned DEFAULT NULL,
`web_updated_notice` int(11) unsigned DEFAULT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `list` (`list`),
CONSTRAINT `custom_forms_ibfk_1` FOREIGN KEY (`list`) REFERENCES `lists` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARSET=utf8mb4;
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# Create table to store custom form data
CREATE TABLE `custom_forms_data` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`form` int(11) unsigned NOT NULL,
`data_key` varchar(255) DEFAULT '',
`data_value` longtext,
PRIMARY KEY (`id`),
KEY `form` (`form`),
CONSTRAINT `custom_forms_data_ibfk_1` FOREIGN KEY (`form`) REFERENCES `custom_forms` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# Add default_form to lists
ALTER TABLE `lists` ADD COLUMN `default_form` int(11) unsigned DEFAULT NULL AFTER `cid`;