From 9fd64549a3dc5e2ef32862a5e77a94a60bc3c778 Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Mon, 5 Dec 2016 17:55:04 -0700
Subject: [PATCH] Use async instead of Promises
---
src/admin/search.js | 200 ++++++++++++++++++++++++-----------------
src/socket.io/admin.js | 7 +-
test/search-admin.js | 4 +-
3 files changed, 123 insertions(+), 88 deletions(-)
diff --git a/src/admin/search.js b/src/admin/search.js
index 940c202cf4..8f567071bf 100644
--- a/src/admin/search.js
+++ b/src/admin/search.js
@@ -2,48 +2,13 @@
var fs = require('fs');
var path = require('path');
+var async = require('async');
var sanitizeHTML = require('sanitize-html');
var languages = require('../languages');
var utils = require('../../public/src/utils');
var Translator = require('../../public/src/modules/translator').Translator;
-function walk(directory) {
- return new Promise(function (resolve, reject) {
- utils.walk(directory, function (err, data) {
- if (err) {
- reject(err);
- } else {
- resolve(data);
- }
- });
- });
-}
-
-function readFile(path) {
- return new Promise(function (resolve, reject) {
- fs.readFile(path, function (err, data) {
- if (err) {
- reject(err);
- } else {
- resolve(data.toString());
- }
- });
- });
-}
-
-function loadLanguage(language, namespace) {
- return new Promise(function (resolve, reject) {
- languages.get(language, namespace, function (err, data) {
- if (err || !data || !Object.keys(data).length) {
- reject(err);
- } else {
- resolve(data);
- }
- });
- });
-}
-
function filterDirectories(directories) {
return directories.map(function (dir) {
// get the relative path
@@ -51,13 +16,21 @@ function filterDirectories(directories) {
}).filter(function (dir) {
// exclude partials
// only include subpaths
- return !dir.includes('/partials/') && /\/.*\//.test(dir);
+ // exclude category.tpl, group.tpl, category-analytics.tpl
+ return !dir.includes('/partials/') &&
+ /\/.*\//.test(dir) &&
+ !/category|group|category\-analytics$/.test(dir);
});
}
-function getAdminNamespaces() {
- return walk(path.resolve(__dirname, '../../public/templates/admin'))
- .then(filterDirectories);
+function getAdminNamespaces(callback) {
+ utils.walk(path.resolve(__dirname, '../../public/templates/admin'), function (err, directories) {
+ if (err) {
+ return callback(err);
+ }
+
+ callback(null, filterDirectories(directories));
+ });
}
function sanitize(html) {
@@ -78,68 +51,133 @@ function simplify(translations) {
.replace(/[\t ]+/g, ' ');
}
+function nsToTitle(namespace) {
+ return namespace.replace('admin/', '').split('/').map(function (str) {
+ return str[0].toUpperCase() + str.slice(1);
+ }).join(' > ');
+}
+
+var fallbackCacheInProgress = {};
var fallbackCache = {};
-function initFallback(namespace) {
- return readFile(path.resolve(__dirname, '../../public/templates/', namespace + '.tpl'))
- .then(function (template) {
- var translations = sanitize(template);
- translations = simplify(translations);
- translations = Translator.removePatterns(translations);
-
- return {
- namespace: namespace,
- translations: translations,
- };
+function initFallback(namespace, callback) {
+ fs.readFile(path.resolve(__dirname, '../../public/templates/', namespace + '.tpl'), function (err, file) {
+ if (err) {
+ return callback(err);
+ }
+
+ var template = file.toString();
+
+ var translations = sanitize(template);
+ translations = Translator.removePatterns(translations);
+ translations = simplify(translations);
+ translations += '\n' + nsToTitle(namespace);
+
+ callback(null, {
+ namespace: namespace,
+ translations: translations,
});
+ });
}
-function fallback(namespace) {
- // use cache if exists, else make it
- fallbackCache[namespace] = fallbackCache[namespace] || initFallback(namespace);
- return fallbackCache[namespace];
+function fallback(namespace, callback) {
+ if (fallbackCache[namespace]) {
+ return callback(null, fallbackCache[namespace]);
+ }
+ if (fallbackCacheInProgress[namespace]) {
+ return fallbackCacheInProgress[namespace].push(callback);
+ }
+
+ fallbackCacheInProgress[namespace] = [function (err, params) {
+ if (err) {
+ return callback(err);
+ }
+
+ callback(null, params);
+ }];
+ initFallback(namespace, function (err, params) {
+ fallbackCacheInProgress[namespace].forEach(function (fn) {
+ fn(err, params);
+ });
+ fallbackCacheInProgress[namespace] = null;
+ fallbackCache[namespace] = params;
+ });
}
-function initDict(language) {
- return getAdminNamespaces().then(function (namespaces) {
- return Promise.all(namespaces.map(function (namespace) {
- return loadLanguage(language, namespace)
- .then(function (translations) {
+function initDict(language, callback) {
+ getAdminNamespaces(function (err, namespaces) {
+ if (err) {
+ return callback(err);
+ }
+
+ async.map(namespaces, function (namespace, cb) {
+ async.waterfall([
+ function (next) {
+ languages.get(language, namespace, next);
+ },
+ function (translations, next) {
+ if (!translations || !Object.keys(translations).length) {
+ return next(Error('No translations for ' + language + '/' + namespace));
+ }
+
// join all translations into one string separated by newlines
var str = Object.keys(translations).map(function (key) {
return translations[key];
}).join('\n');
- return {
+ next(null, {
namespace: namespace,
translations: str,
- };
- })
- // TODO: Use translator to get title for admin route?
- .catch(function () {
- // no translations for this route, fallback to template
- return fallback(namespace);
- })
- .catch(function () {
- // no fallback, just return blank
- return {
- namespace: namespace,
- translations: '',
- };
- });
- }));
+ });
+ }
+ ], function (err, params) {
+ if (err) {
+ return fallback(namespace, function (err, params) {
+ if (err) {
+ return cb({
+ namespace: namespace,
+ translations: '',
+ });
+ }
+
+ cb(null, params);
+ });
+ }
+
+ cb(null, params);
+ });
+ }, callback);
});
}
+var cacheInProgress = {};
var cache = {};
-function getDict(language) {
- // use cache if exists, else make it
- cache[language] = cache[language] || initDict(language);
- return cache[language];
+function getDictionary(language, callback) {
+ if (cache[language]) {
+ return callback(null, cache[language]);
+ }
+ if (cacheInProgress[language]) {
+ return cacheInProgress[language].push(callback);
+ }
+
+ cacheInProgress[language] = [function (err, params) {
+ if (err) {
+ return callback(err);
+ }
+
+ callback(null, params);
+ }];
+ initDict(language, function (err, params) {
+ cacheInProgress[language].forEach(function (fn) {
+ fn(err, params);
+ });
+ cacheInProgress[language] = null;
+ cache[language] = params;
+ });
}
-module.exports.getDict = getDict;
+module.exports.getDictionary = getDictionary;
module.exports.filterDirectories = filterDirectories;
module.exports.simplify = simplify;
module.exports.sanitize = sanitize;
diff --git a/src/socket.io/admin.js b/src/socket.io/admin.js
index 00d90067f7..141d567f11 100644
--- a/src/socket.io/admin.js
+++ b/src/socket.io/admin.js
@@ -15,7 +15,7 @@ var emailer = require('../emailer');
var db = require('../database');
var analytics = require('../analytics');
var index = require('./index');
-var getAdminSearchDict = require('../admin/search').getDict;
+var getAdminSearchDict = require('../admin/search').getDictionary;
var SocketAdmin = {
user: require('./admin/user'),
@@ -284,10 +284,7 @@ SocketAdmin.getSearchDict = function (socket, data, callback) {
return callback(err);
}
var lang = settings.userLang || meta.config.defaultLang || 'en-GB';
- getAdminSearchDict(lang)
- .then(function (results) {
- callback(null, results);
- }, callback);
+ getAdminSearchDict(lang, callback);
});
};
diff --git a/test/search-admin.js b/test/search-admin.js
index 5351018057..216d26d35f 100644
--- a/test/search-admin.js
+++ b/test/search-admin.js
@@ -2,7 +2,7 @@
/*global require*/
var assert = require('assert');
-var search = require('../src/admin/search.js');
+var search = require('../src/admin/search');
describe('admin search', function () {
describe('filterDirectories', function () {
@@ -60,7 +60,7 @@ describe('admin search', function () {
assert.equal(
search.simplify(
'Pellentesque tristique {{senectus}}habitant morbi' +
- 'liquam tincidunt {{mauris.eu}}risus'
+ 'liquam tincidunt {mauris.eu}risus'
),
'Pellentesque tristique habitant morbi' +
'liquam tincidunt risus'