Refactored Custom Form Table Structure
This commit is contained in:
		
							parent
							
								
									477aff95d5
								
							
						
					
					
						commit
						c3ee53bd4b
					
				
					 3 changed files with 178 additions and 84 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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`;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue