From 96aa94ee103aaf8c3fe90f0e517f5bb2514cac39 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 6 Jan 2016 12:49:14 +0200 Subject: [PATCH] refactor categories --- src/controllers/categories.js | 309 ++++++---------------------------- src/controllers/category.js | 206 +++++++++++++++++++++++ src/controllers/index.js | 35 ++-- src/routes/index.js | 4 +- 4 files changed, 279 insertions(+), 275 deletions(-) create mode 100644 src/controllers/category.js diff --git a/src/controllers/categories.js b/src/controllers/categories.js index b2d36b91e8..33fa6c6ef8 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -1,283 +1,80 @@ "use strict"; -var categoriesController = {}, - async = require('async'), - nconf = require('nconf'), - validator = require('validator'), - db = require('../database'), - privileges = require('../privileges'), - user = require('../user'), - categories = require('../categories'), - meta = require('../meta'), - plugins = require('../plugins'), - pagination = require('../pagination'), - helpers = require('./helpers'), - utils = require('../../public/src/utils'); +var async = require('async'); +var nconf = require('nconf'); +var validator = require('validator'); +var categories = require('../categories'); +var meta = require('../meta'); +var plugins = require('../plugins'); -categoriesController.list = function(req, res, next) { - async.parallel({ - header: function (next) { - res.locals.metaTags = [{ - name: "title", - content: validator.escape(meta.config.title || 'NodeBB') - }, { - name: "description", - content: validator.escape(meta.config.description || '') - }, { - property: 'og:title', - content: '[[pages:categories]]' - }, { - property: 'og:type', - content: 'website' - }]; - - if (meta.config['brand:logo']) { - res.locals.metaTags.push({ - property: 'og:image', - content: meta.config['brand:logo'] - }); - } - - next(null); - }, - categories: function (next) { - var categoryData; - async.waterfall([ - function(next) { - categories.getCategoriesByPrivilege('cid:0:children', req.uid, 'find', next); - }, - function(_categoryData, next) { - categoryData = _categoryData; +var helpers = require('./helpers'); - var allCategories = []; - categories.flattenCategories(allCategories, categoryData); - - categories.getRecentTopicReplies(allCategories, req.uid, next); - } - ], function(err) { - next(err, categoryData); - }); - } - }, function (err, data) { - if (err) { - return next(err); - } - - data.categories.forEach(function(category) { - if (category && Array.isArray(category.posts) && category.posts.length) { - category.teaser = { - url: nconf.get('relative_path') + '/topic/' + category.posts[0].topic.slug + '/' + category.posts[0].index, - timestampISO: category.posts[0].timestamp - }; - } - }); - - data.title = '[[pages:categories]]'; - if (req.path.startsWith('/api/categories') || req.path.startsWith('/categories')) { - data.breadcrumbs = helpers.buildBreadcrumbs([{text: data.title}]); - } +var categoriesController = {}; - plugins.fireHook('filter:categories.build', {req: req, res: res, templateData: data}, function(err, data) { - if (err) { - return next(err); - } - res.render('categories', data.templateData); +categoriesController.list = function(req, res, next) { + res.locals.metaTags = [{ + name: "title", + content: validator.escape(meta.config.title || 'NodeBB') + }, { + name: "description", + content: validator.escape(meta.config.description || '') + }, { + property: 'og:title', + content: '[[pages:categories]]' + }, { + property: 'og:type', + content: 'website' + }]; + + if (meta.config['brand:logo']) { + res.locals.metaTags.push({ + property: 'og:image', + content: meta.config['brand:logo'] }); - }); -}; - -categoriesController.get = function(req, res, callback) { - var cid = req.params.category_id, - currentPage = parseInt(req.query.page, 10) || 1, - pageCount = 1, - userPrivileges; - - if ((req.params.topic_index && !utils.isNumber(req.params.topic_index)) || !utils.isNumber(cid)) { - return callback(); } + var categoryData; async.waterfall([ - function(next) { - async.parallel({ - categoryData: function(next) { - categories.getCategoryFields(cid, ['slug', 'disabled', 'topic_count'], next); - }, - privileges: function(next) { - privileges.categories.get(cid, req.uid, next); - }, - userSettings: function(next) { - user.getSettings(req.uid, next); - } - }, next); + function (next) { + categories.getCategoriesByPrivilege('cid:0:children', req.uid, 'find', next); }, - function(results, next) { - userPrivileges = results.privileges; - - if (!results.categoryData.slug || (results.categoryData && parseInt(results.categoryData.disabled, 10) === 1)) { - return callback(); - } - - if (!results.privileges.read) { - return helpers.notAllowed(req, res); - } - - if ((!req.params.slug || results.categoryData.slug !== cid + '/' + req.params.slug) && (results.categoryData.slug && results.categoryData.slug !== cid + '/')) { - return helpers.redirect(res, '/category/' + encodeURI(results.categoryData.slug)); - } - - var settings = results.userSettings; - var topicIndex = utils.isNumber(req.params.topic_index) ? parseInt(req.params.topic_index, 10) - 1 : 0; - var topicCount = parseInt(results.categoryData.topic_count, 10); - pageCount = Math.max(1, Math.ceil(topicCount / settings.topicsPerPage)); - - if (topicIndex < 0 || topicIndex > Math.max(topicCount - 1, 0)) { - return helpers.redirect(res, '/category/' + cid + '/' + req.params.slug + (topicIndex > topicCount ? '/' + topicCount : '')); - } + function (_categoryData, next) { + categoryData = _categoryData; - if (settings.usePagination && (currentPage < 1 || currentPage > pageCount)) { - return callback(); - } - - if (!settings.usePagination) { - topicIndex = Math.max(topicIndex - (settings.topicsPerPage - 1), 0); - } else if (!req.query.page) { - var index = Math.max(parseInt((topicIndex || 0), 10), 0); - currentPage = Math.ceil((index + 1) / settings.topicsPerPage); - topicIndex = 0; - } - - var set = 'cid:' + cid + ':tids', - reverse = false; - - if (settings.categoryTopicSort === 'newest_to_oldest') { - reverse = true; - } else if (settings.categoryTopicSort === 'most_posts') { - reverse = true; - set = 'cid:' + cid + ':tids:posts'; - } - - var start = (currentPage - 1) * settings.topicsPerPage + topicIndex, - stop = start + settings.topicsPerPage - 1; + var allCategories = []; + categories.flattenCategories(allCategories, categoryData); - next(null, { - cid: cid, - set: set, - reverse: reverse, - start: start, - stop: stop, - uid: req.uid - }); - }, - function(payload, next) { - user.getUidByUserslug(req.query.author, function(err, uid) { - payload.targetUid = uid; - if (uid) { - payload.set = 'cid:' + cid + ':uid:' + uid + ':tids'; - } - next(err, payload); - }); + categories.getRecentTopicReplies(allCategories, req.uid, next); }, - function(payload, next) { - categories.getCategoryById(payload, next); - }, - function(categoryData, next) { - if (categoryData.link) { - db.incrObjectField('category:' + categoryData.cid, 'timesClicked'); - return res.redirect(categoryData.link); + function (next) { + var data = { + title: '[[pages:categories]]', + categories: categoryData + }; + + if (req.path.startsWith('/api/categories') || req.path.startsWith('/categories')) { + data.breadcrumbs = helpers.buildBreadcrumbs([{text: data.title}]); } - var breadcrumbs = [ - { - text: categoryData.name, - url: nconf.get('relative_path') + '/category/' + categoryData.slug - } - ]; - helpers.buildCategoryBreadcrumbs(categoryData.parentCid, function(err, crumbs) { - if (err) { - return next(err); + data.categories.forEach(function(category) { + if (category && Array.isArray(category.posts) && category.posts.length) { + category.teaser = { + url: nconf.get('relative_path') + '/topic/' + category.posts[0].topic.slug + '/' + category.posts[0].index, + timestampISO: category.posts[0].timestamp + }; } - categoryData.breadcrumbs = crumbs.concat(breadcrumbs); - next(null, categoryData); - }); - }, - function(categoryData, next) { - if (!categoryData.children.length) { - return next(null, categoryData); - } - var allCategories = []; - categories.flattenCategories(allCategories, categoryData.children); - categories.getRecentTopicReplies(allCategories, req.uid, function(err) { - next(err, categoryData); }); - }, - function (categoryData, next) { - categoryData.privileges = userPrivileges; - categoryData.showSelect = categoryData.privileges.editable; - - res.locals.metaTags = [ - { - name: 'title', - content: categoryData.name - }, - { - property: 'og:title', - content: categoryData.name - }, - { - name: 'description', - content: categoryData.description - }, - { - property: "og:type", - content: 'website' - } - ]; - - if (categoryData.backgroundImage) { - res.locals.metaTags.push({ - name: 'og:image', - content: categoryData.backgroundImage - }); - } - - res.locals.linkTags = [ - { - rel: 'alternate', - type: 'application/rss+xml', - href: nconf.get('url') + '/category/' + cid + '.rss' - }, - { - rel: 'up', - href: nconf.get('url') - } - ]; - next(null, categoryData); + plugins.fireHook('filter:categories.build', {req: req, res: res, templateData: data}, next); } - ], function (err, data) { + ], function(err, data) { if (err) { - return callback(err); + return next(err); } - - data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; - data.rssFeedUrl = nconf.get('relative_path') + '/category/' + data.cid + '.rss'; - data.title = data.name; - data.pagination = pagination.create(currentPage, pageCount); - data.pagination.rel.forEach(function(rel) { - rel.href = nconf.get('url') + '/category/' + data.slug + rel.href; - res.locals.linkTags.push(rel); - }); - - plugins.fireHook('filter:category.build', {req: req, res: res, templateData: data}, function(err, data) { - if (err) { - return callback(err); - } - res.render('category', data.templateData); - }); + res.render('categories', data.templateData); }); }; - module.exports = categoriesController; diff --git a/src/controllers/category.js b/src/controllers/category.js new file mode 100644 index 0000000000..d3f84d9204 --- /dev/null +++ b/src/controllers/category.js @@ -0,0 +1,206 @@ +"use strict"; + + +var async = require('async'); +var nconf = require('nconf'); + +var db = require('../database'); +var privileges = require('../privileges'); +var user = require('../user'); +var categories = require('../categories'); +var meta = require('../meta'); +var plugins = require('../plugins'); +var pagination = require('../pagination'); +var helpers = require('./helpers'); +var utils = require('../../public/src/utils'); + +var categoryController = {}; + +categoryController.get = function(req, res, callback) { + var cid = req.params.category_id; + var currentPage = parseInt(req.query.page, 10) || 1; + var pageCount = 1; + var userPrivileges; + + if ((req.params.topic_index && !utils.isNumber(req.params.topic_index)) || !utils.isNumber(cid)) { + return callback(); + } + + async.waterfall([ + function(next) { + async.parallel({ + categoryData: function(next) { + categories.getCategoryFields(cid, ['slug', 'disabled', 'topic_count'], next); + }, + privileges: function(next) { + privileges.categories.get(cid, req.uid, next); + }, + userSettings: function(next) { + user.getSettings(req.uid, next); + } + }, next); + }, + function(results, next) { + userPrivileges = results.privileges; + + if (!results.categoryData.slug || (results.categoryData && parseInt(results.categoryData.disabled, 10) === 1)) { + return callback(); + } + + if (!results.privileges.read) { + return helpers.notAllowed(req, res); + } + + if ((!req.params.slug || results.categoryData.slug !== cid + '/' + req.params.slug) && (results.categoryData.slug && results.categoryData.slug !== cid + '/')) { + return helpers.redirect(res, '/category/' + encodeURI(results.categoryData.slug)); + } + + var settings = results.userSettings; + var topicIndex = utils.isNumber(req.params.topic_index) ? parseInt(req.params.topic_index, 10) - 1 : 0; + var topicCount = parseInt(results.categoryData.topic_count, 10); + pageCount = Math.max(1, Math.ceil(topicCount / settings.topicsPerPage)); + + if (topicIndex < 0 || topicIndex > Math.max(topicCount - 1, 0)) { + return helpers.redirect(res, '/category/' + cid + '/' + req.params.slug + (topicIndex > topicCount ? '/' + topicCount : '')); + } + + if (settings.usePagination && (currentPage < 1 || currentPage > pageCount)) { + return callback(); + } + + if (!settings.usePagination) { + topicIndex = Math.max(topicIndex - (settings.topicsPerPage - 1), 0); + } else if (!req.query.page) { + var index = Math.max(parseInt((topicIndex || 0), 10), 0); + currentPage = Math.ceil((index + 1) / settings.topicsPerPage); + topicIndex = 0; + } + + var set = 'cid:' + cid + ':tids', + reverse = false; + + if (settings.categoryTopicSort === 'newest_to_oldest') { + reverse = true; + } else if (settings.categoryTopicSort === 'most_posts') { + reverse = true; + set = 'cid:' + cid + ':tids:posts'; + } + + var start = (currentPage - 1) * settings.topicsPerPage + topicIndex, + stop = start + settings.topicsPerPage - 1; + + next(null, { + cid: cid, + set: set, + reverse: reverse, + start: start, + stop: stop, + uid: req.uid + }); + }, + function(payload, next) { + user.getUidByUserslug(req.query.author, function(err, uid) { + payload.targetUid = uid; + if (uid) { + payload.set = 'cid:' + cid + ':uid:' + uid + ':tids'; + } + next(err, payload); + }); + }, + function(payload, next) { + categories.getCategoryById(payload, next); + }, + function(categoryData, next) { + if (categoryData.link) { + db.incrObjectField('category:' + categoryData.cid, 'timesClicked'); + return res.redirect(categoryData.link); + } + + var breadcrumbs = [ + { + text: categoryData.name, + url: nconf.get('relative_path') + '/category/' + categoryData.slug + } + ]; + helpers.buildCategoryBreadcrumbs(categoryData.parentCid, function(err, crumbs) { + if (err) { + return next(err); + } + categoryData.breadcrumbs = crumbs.concat(breadcrumbs); + next(null, categoryData); + }); + }, + function(categoryData, next) { + if (!categoryData.children.length) { + return next(null, categoryData); + } + var allCategories = []; + categories.flattenCategories(allCategories, categoryData.children); + categories.getRecentTopicReplies(allCategories, req.uid, function(err) { + next(err, categoryData); + }); + }, + function (categoryData, next) { + categoryData.privileges = userPrivileges; + categoryData.showSelect = categoryData.privileges.editable; + + res.locals.metaTags = [ + { + name: 'title', + content: categoryData.name + }, + { + property: 'og:title', + content: categoryData.name + }, + { + name: 'description', + content: categoryData.description + }, + { + property: "og:type", + content: 'website' + } + ]; + + if (categoryData.backgroundImage) { + res.locals.metaTags.push({ + name: 'og:image', + content: categoryData.backgroundImage + }); + } + + res.locals.linkTags = [ + { + rel: 'alternate', + type: 'application/rss+xml', + href: nconf.get('url') + '/category/' + cid + '.rss' + }, + { + rel: 'up', + href: nconf.get('url') + } + ]; + + categoryData['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; + categoryData.rssFeedUrl = nconf.get('relative_path') + '/category/' + categoryData.cid + '.rss'; + categoryData.title = categoryData.name; + categoryData.pagination = pagination.create(currentPage, pageCount); + categoryData.pagination.rel.forEach(function(rel) { + rel.href = nconf.get('url') + '/category/' + categoryData.slug + rel.href; + res.locals.linkTags.push(rel); + }); + + plugins.fireHook('filter:category.build', {req: req, res: res, templateData: categoryData}, next); + next(null, categoryData); + } + ], function (err, data) { + if (err) { + return callback(err); + } + res.render('category', data.templateData); + }); +}; + + +module.exports = categoryController; diff --git a/src/controllers/index.js b/src/controllers/index.js index 7108664476..feb1759820 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -1,23 +1,19 @@ "use strict"; -var async = require('async'), - nconf = require('nconf'), - validator = require('validator'), - winston = require('winston'), - - meta = require('../meta'), - user = require('../user'), - posts = require('../posts'), - topics = require('../topics'), - plugins = require('../plugins'), - sitemap = require('../sitemap'), - categories = require('../categories'), - privileges = require('../privileges'), - helpers = require('./helpers'); +var async = require('async'); +var nconf = require('nconf'); +var validator = require('validator'); + +var meta = require('../meta'); +var user = require('../user'); +var plugins = require('../plugins'); +var sitemap = require('../sitemap'); +var helpers = require('./helpers'); var Controllers = { topics: require('./topics'), categories: require('./categories'), + category: require('./category'), unread: require('./unread'), recent: require('./recent'), popular: require('./popular'), @@ -36,7 +32,12 @@ Controllers.home = function(req, res, next) { var route = meta.config.homePageRoute || meta.config.homePageCustom || 'categories'; user.getSettings(req.uid, function(err, settings) { - if (!err && settings.homePageRoute !== 'undefined' && settings.homePageRoute !== 'none') route = settings.homePageRoute || route; + if (err) { + return next(err); + } + if (settings.homePageRoute !== 'undefined' && settings.homePageRoute !== 'none') { + route = settings.homePageRoute || route; + } var hook = 'action:homepage.get:' + route; @@ -180,7 +181,7 @@ Controllers.sitemap.render = function(req, res, next) { res.header('Content-Type', 'application/xml'); res.send(xml); }); - }) + }); }; Controllers.sitemap.getPages = function(req, res, next) { @@ -280,7 +281,7 @@ Controllers.manifest = function(req, res) { sizes: '192x192', type: 'image/png', density: 4.0 - }) + }); } res.status(200).json(manifest); diff --git a/src/routes/index.js b/src/routes/index.js index a35c5ea61e..2331fc8c95 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -51,8 +51,8 @@ function categoryRoutes(app, middleware, controllers) { setupPageRoute(app, '/recent', middleware, [], controllers.recent.get); setupPageRoute(app, '/unread', middleware, [middleware.authenticate], controllers.unread.get); - setupPageRoute(app, '/category/:category_id/:slug/:topic_index', middleware, [], controllers.categories.get); - setupPageRoute(app, '/category/:category_id/:slug?', middleware, [], controllers.categories.get); + setupPageRoute(app, '/category/:category_id/:slug/:topic_index', middleware, [], controllers.category.get); + setupPageRoute(app, '/category/:category_id/:slug?', middleware, [], controllers.category.get); } function userRoutes(app, middleware, controllers) {