- on category setParent dialog do not show children of current category
- break recursion if category parentCid is equal to child cid to prevent
infinite loop
- dont allow setting the parentCid of a category to one of it's children
v1.18.x
Baris Usakli 6 years ago
parent 9a9f2af9c1
commit 3c611d85ed

@ -240,8 +240,13 @@ define('admin/manage/category', [
} }
Category.launchParentSelector = function () { Category.launchParentSelector = function () {
var parents = [parseInt(ajaxify.data.category.cid, 10)];
var categories = ajaxify.data.allCategories.filter(function (category) { var categories = ajaxify.data.allCategories.filter(function (category) {
return category && !category.disabled && parseInt(category.cid, 10) !== parseInt(ajaxify.data.category.cid, 10); var isChild = parents.includes(parseInt(category.parentCid, 10));
if (isChild) {
parents.push(parseInt(category.cid, 10));
}
return category && !category.disabled && parseInt(category.cid, 10) !== parseInt(ajaxify.data.category.cid, 10) && !isChild;
}); });
categorySelector.modal(categories, function (parentCid) { categorySelector.modal(categories, function (parentCid) {

@ -2,6 +2,7 @@
'use strict'; 'use strict';
var async = require('async'); var async = require('async');
var _ = require('lodash');
var db = require('../database'); var db = require('../database');
var user = require('../user'); var user = require('../user');
@ -219,7 +220,13 @@ Categories.getChildren = function (cids, uid, callback) {
}); });
async.each(categories, function (category, next) { async.each(categories, function (category, next) {
getChildrenRecursive(category, uid, next); Categories.getCategoryField(category.cid, 'parentCid', function (err, parentCid) {
if (err) {
return next(err);
}
category.parentCid = parentCid;
getChildrenRecursive(category, uid, next);
});
}, function (err) { }, function (err) {
callback(err, categories.map(function (c) { callback(err, categories.map(function (c) {
return c && c.children; return c && c.children;
@ -263,12 +270,37 @@ function getChildrenRecursive(category, uid, callback) {
}, },
function (next) { function (next) {
async.each(category.children, function (child, next) { async.each(category.children, function (child, next) {
if (parseInt(category.parentCid, 10) === parseInt(child.cid, 10)) {
return next();
}
getChildrenRecursive(child, uid, next); getChildrenRecursive(child, uid, next);
}, next); }, next);
}, },
], callback); ], callback);
} }
Categories.getChildrenCids = function (rootCid, callback) {
function recursive(currentCid, callback) {
db.getSortedSetRange('cid:' + currentCid + ':children', 0, -1, function (err, childrenCids) {
if (err) {
return callback(err);
}
if (!childrenCids.length) {
return callback();
}
async.eachSeries(childrenCids, function (childCid, next) {
allCids.push(parseInt(childCid, 10));
recursive(childCid, next);
}, callback);
});
}
var allCids = [];
recursive(rootCid, function (err) {
callback(err, _.uniq(allCids));
});
}
Categories.flattenCategories = function (allCategories, categoryData) { Categories.flattenCategories = function (allCategories, categoryData) {
categoryData.forEach(function (category) { categoryData.forEach(function (category) {
if (category) { if (category) {

@ -92,6 +92,12 @@ module.exports = function (Categories) {
} }
async.waterfall([ async.waterfall([
function (next) { function (next) {
Categories.getChildrenCids(cid, next);
},
function (childrenCids, next) {
if (childrenCids.includes(parseInt(newParent, 10))) {
return next(new Error('[[error:cant-set-child-as-parent]]'));
}
Categories.getCategoryField(cid, 'parentCid', next); Categories.getCategoryField(cid, 'parentCid', next);
}, },
function (oldParent, next) { function (oldParent, next) {

@ -338,6 +338,31 @@ describe('Categories', function () {
}); });
}); });
it('should error if you try to set child as parent', function (done) {
var child1Cid;
var parentCid;
async.waterfall([
function (next) {
Categories.create({ name: 'parent 1', description: 'poor parent' }, next);
},
function (category, next) {
parentCid = category.cid;
Categories.create({ name: 'child1', description: 'wanna be parent', parentCid: parentCid }, next);
},
function (category, next) {
child1Cid = category.cid;
var updateData = {};
updateData[parentCid] = {
parentCid: child1Cid,
};
socketCategories.update({ uid: adminUid }, updateData, function (err) {
assert.equal(err.message, '[[error:cant-set-child-as-parent]]');
next();
});
},
], done);
});
it('should update category data', function (done) { it('should update category data', function (done) {
var updateData = {}; var updateData = {};
updateData[cid] = { updateData[cid] = {

Loading…
Cancel
Save