diff --git a/src/controllers/topics.js b/src/controllers/topics.js index a33703b8ce..a794d40c8a 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -15,7 +15,7 @@ var helpers = require('./helpers'); var pagination = require('../pagination'); var utils = require('../utils'); -var topicsController = {}; +var topicsController = module.exports; topicsController.get = function (req, res, callback) { var tid = req.params.topic_id; @@ -134,170 +134,173 @@ topicsController.get = function (req, res, callback) { plugins.fireHook('filter:controllers.topic.get', { topicData: topicData, uid: req.uid }, next); }, function (data, next) { - var breadcrumbs = [ - { - text: data.topicData.category.name, - url: nconf.get('relative_path') + '/category/' + data.topicData.category.slug, - }, - { - text: data.topicData.title, - }, - ]; - - helpers.buildCategoryBreadcrumbs(data.topicData.category.parentCid, function (err, crumbs) { - if (err) { - return next(err); - } - data.topicData.breadcrumbs = crumbs.concat(breadcrumbs); - next(null, data.topicData); - }); + buildBreadcrumbs(data.topicData, next); }, - function (topicData, next) { - function findPost(index) { - for (var i = 0; i < topicData.posts.length; i += 1) { - if (parseInt(topicData.posts[i].index, 10) === parseInt(index, 10)) { - return topicData.posts[i]; - } - } - } - var description = ''; - var postAtIndex = findPost(Math.max(0, req.params.post_index - 1)); - - if (postAtIndex && postAtIndex.content) { - description = S(postAtIndex.content).decodeHTMLEntities().stripTags().s; + function (topicData) { + topicData.privileges = userPrivileges; + topicData.topicStaleDays = parseInt(meta.config.topicStaleDays, 10) || 60; + topicData['reputation:disabled'] = parseInt(meta.config['reputation:disabled'], 10) === 1; + topicData['downvote:disabled'] = parseInt(meta.config['downvote:disabled'], 10) === 1; + topicData['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; + topicData.bookmarkThreshold = parseInt(meta.config.bookmarkThreshold, 10) || 5; + topicData.postEditDuration = parseInt(meta.config.postEditDuration, 10) || 0; + topicData.postDeleteDuration = parseInt(meta.config.postDeleteDuration, 10) || 0; + topicData.scrollToMyPost = settings.scrollToMyPost; + topicData.rssFeedUrl = nconf.get('relative_path') + '/topic/' + topicData.tid + '.rss'; + if (req.uid) { + topicData.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken; } + topicData.postIndex = req.params.post_index; + topicData.pagination = pagination.create(currentPage, pageCount, req.query); + topicData.pagination.rel.forEach(function (rel) { + rel.href = nconf.get('url') + '/topic/' + topicData.slug + rel.href; + res.locals.linkTags.push(rel); + }); - if (description.length > 255) { - description = description.substr(0, 255) + '...'; + req.session.tids_viewed = req.session.tids_viewed || {}; + if (!req.session.tids_viewed[tid] || req.session.tids_viewed[tid] < Date.now() - 3600000) { + topics.increaseViewCount(tid); + req.session.tids_viewed[tid] = Date.now(); } - var ogImageUrl = ''; - if (topicData.thumb) { - ogImageUrl = topicData.thumb; - } else if (postAtIndex && postAtIndex.user && postAtIndex.user.picture) { - ogImageUrl = postAtIndex.user.picture; - } else if (meta.config['og:image']) { - ogImageUrl = meta.config['og:image']; - } else if (meta.config['brand:logo']) { - ogImageUrl = meta.config['brand:logo']; - } else { - ogImageUrl = '/logo.png'; - } + addTags(topicData, req, res); - if (typeof ogImageUrl === 'string' && ogImageUrl.indexOf('http') === -1) { - ogImageUrl = nconf.get('url') + ogImageUrl; + if (req.uid) { + topics.markAsRead([tid], req.uid, function (err, markedRead) { + if (err) { + return callback(err); + } + if (markedRead) { + topics.pushUnreadCount(req.uid); + topics.markTopicNotificationsRead([tid], req.uid); + } + }); } - description = description.replace(/\n/g, ' '); - - res.locals.metaTags = [ - { - name: 'title', - content: topicData.titleRaw, - }, - { - name: 'description', - content: description, - }, - { - property: 'og:title', - content: topicData.titleRaw, - }, - { - property: 'og:description', - content: description, - }, - { - property: 'og:type', - content: 'article', - }, - { - property: 'og:image', - content: ogImageUrl, - noEscape: true, - }, - { - property: 'og:image:url', - content: ogImageUrl, - noEscape: true, - }, - { - property: 'article:published_time', - content: utils.toISOString(topicData.timestamp), - }, - { - property: 'article:modified_time', - content: utils.toISOString(topicData.lastposttime), - }, - { - property: 'article:section', - content: topicData.category ? topicData.category.name : '', - }, - ]; - - res.locals.linkTags = [ - { - rel: 'alternate', - type: 'application/rss+xml', - href: nconf.get('url') + '/topic/' + tid + '.rss', - }, - ]; + res.render('topic', topicData); + }, + ], callback); +}; - if (topicData.category) { - res.locals.linkTags.push({ - rel: 'up', - href: nconf.get('url') + '/category/' + topicData.category.slug, - }); - } +function buildBreadcrumbs(topicData, callback) { + var breadcrumbs = [ + { + text: topicData.category.name, + url: nconf.get('relative_path') + '/category/' + topicData.category.slug, + }, + { + text: topicData.title, + }, + ]; + async.waterfall([ + function (next) { + helpers.buildCategoryBreadcrumbs(topicData.category.parentCid, next); + }, + function (crumbs, next) { + topicData.breadcrumbs = crumbs.concat(breadcrumbs); next(null, topicData); }, - ], function (err, data) { - if (err) { - return callback(err); + ], callback); +} + +function addTags(topicData, req, res) { + function findPost(index) { + for (var i = 0; i < topicData.posts.length; i += 1) { + if (parseInt(topicData.posts[i].index, 10) === parseInt(index, 10)) { + return topicData.posts[i]; + } } + } + var description = ''; + var postAtIndex = findPost(Math.max(0, req.params.post_index - 1)); - data.privileges = userPrivileges; - data.topicStaleDays = parseInt(meta.config.topicStaleDays, 10) || 60; - data['reputation:disabled'] = parseInt(meta.config['reputation:disabled'], 10) === 1; - data['downvote:disabled'] = parseInt(meta.config['downvote:disabled'], 10) === 1; - data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; - data.bookmarkThreshold = parseInt(meta.config.bookmarkThreshold, 10) || 5; - data.postEditDuration = parseInt(meta.config.postEditDuration, 10) || 0; - data.postDeleteDuration = parseInt(meta.config.postDeleteDuration, 10) || 0; - data.scrollToMyPost = settings.scrollToMyPost; - data.rssFeedUrl = nconf.get('relative_path') + '/topic/' + data.tid + '.rss'; - if (req.uid) { - data.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken; - } - data.postIndex = req.params.post_index; - data.pagination = pagination.create(currentPage, pageCount, req.query); - data.pagination.rel.forEach(function (rel) { - rel.href = nconf.get('url') + '/topic/' + data.slug + rel.href; - res.locals.linkTags.push(rel); - }); + if (postAtIndex && postAtIndex.content) { + description = S(postAtIndex.content).decodeHTMLEntities().stripTags().s; + } - req.session.tids_viewed = req.session.tids_viewed || {}; - if (!req.session.tids_viewed[tid] || req.session.tids_viewed[tid] < Date.now() - 3600000) { - topics.increaseViewCount(tid); - req.session.tids_viewed[tid] = Date.now(); - } + if (description.length > 255) { + description = description.substr(0, 255) + '...'; + } - if (req.uid) { - topics.markAsRead([tid], req.uid, function (err, markedRead) { - if (err) { - return callback(err); - } - if (markedRead) { - topics.pushUnreadCount(req.uid); - topics.markTopicNotificationsRead([tid], req.uid); - } - }); - } + var ogImageUrl = ''; + if (topicData.thumb) { + ogImageUrl = topicData.thumb; + } else if (postAtIndex && postAtIndex.user && postAtIndex.user.picture) { + ogImageUrl = postAtIndex.user.picture; + } else if (meta.config['og:image']) { + ogImageUrl = meta.config['og:image']; + } else if (meta.config['brand:logo']) { + ogImageUrl = meta.config['brand:logo']; + } else { + ogImageUrl = '/logo.png'; + } - res.render('topic', data); - }); -}; + if (typeof ogImageUrl === 'string' && ogImageUrl.indexOf('http') === -1) { + ogImageUrl = nconf.get('url') + ogImageUrl; + } + + description = description.replace(/\n/g, ' '); + res.locals.metaTags = [ + { + name: 'title', + content: topicData.titleRaw, + }, + { + name: 'description', + content: description, + }, + { + property: 'og:title', + content: topicData.titleRaw, + }, + { + property: 'og:description', + content: description, + }, + { + property: 'og:type', + content: 'article', + }, + { + property: 'og:image', + content: ogImageUrl, + noEscape: true, + }, + { + property: 'og:image:url', + content: ogImageUrl, + noEscape: true, + }, + { + property: 'article:published_time', + content: utils.toISOString(topicData.timestamp), + }, + { + property: 'article:modified_time', + content: utils.toISOString(topicData.lastposttime), + }, + { + property: 'article:section', + content: topicData.category ? topicData.category.name : '', + }, + ]; + + res.locals.linkTags = [ + { + rel: 'alternate', + type: 'application/rss+xml', + href: topicData.rssFeedUrl, + }, + ]; + + if (topicData.category) { + res.locals.linkTags.push({ + rel: 'up', + href: nconf.get('url') + '/category/' + topicData.category.slug, + }); + } +} topicsController.teaser = function (req, res, next) { var tid = req.params.topic_id; @@ -363,5 +366,3 @@ topicsController.pagination = function (req, res, callback) { res.json(paginationData); }); }; - -module.exports = topicsController; diff --git a/test/feeds.js b/test/feeds.js index 325b44a6b6..4ed9fe0937 100644 --- a/test/feeds.js +++ b/test/feeds.js @@ -181,6 +181,7 @@ describe('feeds', function () { it('should not allow access if token is correct but has no privilege', function (done) { privileges.categories.rescind(['read'], cid, 'registered-users', function (err) { + assert.ifError(err); request(nconf.get('url') + '/category/' + cid + '.rss?uid=' + fooUid + '&token=' + rssToken, { }, function (err, res, body) { assert.ifError(err); assert.equal(res.statusCode, 200);