const path = require('path');
nv_create_dirs('./nv-content/data/');
// status: pending, publish, spam
// type(暂无): comment, trackback, pingback
const db_comments = new NV_Database(path.join(process.cwd(),"./nv-content/data/comments.json"),{
columns: ['post_id','name','email','url','date','content','status','parent','user_id','ip','ua'],
index: 'id'
});
nvdb.comments = db_comments;
global.nv_insert_comment = (args) => {
var {
post_id, user_id, date, status, parent, content,
} = args;
var post = get_post( parseInt(post_id) );
if ( is_nv_error(post) ) {
return post;
}
var user = get_user_by_id(user_id);
if (user) {
args.name = user.name;
args.email = user.email || args.email;
args.url = user.url || args.url;
} else {
args.user_id = 0;
}
if (parent) {
var comment = db_comments.find(r=>r.id == parent)[0];
if (!comment) {
return new NV_Error('父评论不存在');
}
} else {
args.parent = 0;
}
if (!date) {
args.date = Date.now();
}
if (!status) {
status = 'publish';
// 评论必须经人工批准
if ( get_option('comment_moderation') ) {
status = 'pending';
}
// 评论者先前须有评论通过了审核
if ( get_option('comment_previously_approved') ) {
status = 'pending';
if (args.email) {
var prev_published_cmt = db_comments.find(r=>r.email == args.email && r.status == 'publish')[0];
if (prev_published_cmt) {
status = 'publish'
}
}
}
args.status = status;
}
if (!content) {
args.content = '';
}
args = apply_filters('nv_before_insert_comment', args);
var comment_id = db_comments.insert(args);
// 对文章评论计数
nv_set_post_fields( [post.id],{
comment_count: ( parseInt(post.comment_count) || 0 ) + 1
} )
do_action('nv_comment_inserted', {
...args,
id: comment_id,
});
return {
...args,
id: comment_id,
};
}
global.get_comment = (comment_id) => {
var comment = db_comments.find(r=>r.id == comment_id)[0];
return comment || new NV_Error('评论ID不存在');
}
global.query_comments = (args) => {
/*
args = {
name_in: Array, [String]
name_not_in: Array, [String]
email: String,
url: String,
comment: Number,
comment_in: Array, [Number]
comment_not_in: Array, [Number],
user: Number,
user_in: Array, [Number]
user_not_in: Array, [Number]
post: Number,
post_in: Array, [Number]
post_not_in: Array, [Number]
keyword: String,
parent: Number, // 0仅搜索顶层
hierarchical: Boolean // 层次显示
status: String/Array, [String] //【没有默认值!!!】空字符串、无参数则表示任意
date_query: {
after: Number, timestamp
before: Number, timespamp //默认: 小于服务器当前时间
},
meta_query: {
relation: String, AND /OR //默认 AND
opts: [
{
key: String, metaKey
value: String / Array, Array可以用IN /NOT IN/BETWEEN/NOT BETWEEN来compare
compare: String, =/!=/>/>=/</<=/LIKE/NOT LIKE/IN/NOT IN/BETWEEN/NOT BETWEEN
}
]
},
orderby: String, post_id/name/email/url/date/date/status/parent/user_id/ip/ua 默认:date
order: String, ASC/DESC, 默认:DESC
comments_per_page: Number,
current_page: Number,
fields: Array, [String]
}
*/
// 先过滤comments表
var comments = db_comments.find(r=>{
var result = [];
if (args.name_in && !args.name_in.includes(r.name)) { return false; }
if (args.name_not_in && args.name_not_in.includes(r.name) ) { return false; }
if (args.email && r.email !== args.email) { return false; }
if (args.url && r.url !== args.url) { return false; }
if (args.comment && r.id !== args.comment) { return false; }
if (args.comment_in && !args.comment_in.includes(r.id)) { return false; }
if (args.comment_not_in && args.comment_not_in.includes(r.id)) { return false; }
if (args.user && r.user_id !== args.user) { return false; }
if (args.user_in && !args.user_in.includes(r.user_id)) { return false; }
if (args.user_not_in && args.user_not_in.includes(r.user_id) ) { return false; }
if (args.post && r.post_id !== args.post) { return false; }
if (args.post_in && !args.post_in.includes(r.post_id)) { return false; }
if (args.post_not_in && args.post_not_in.includes(r.post_id) ) { return false; }
if (args.keyword) {
if ( !(r.content || '').includes(args.keyword) ) {
return false;
}
}
if (args.parent !== undefined && r.parent !== args.parent) { return false; }
//status
if (args.status) {
if ( Array.isArray(args.status) ) {
if (!args.status.includes(r.status)) {return false;}
} else {
if (r.status !== args.status) {return false;}
}
}
// date_query 默认查询已发布(小于当前时间的)
if (args.date_query == undefined) {
args.date_query = {
before: Date.now()
}
}
if (args.date_query) {
var date_query_result = [];
if (args.date_query.after) {
date_query_result.push(r.date >= args.date_query.after)
}
if (args.date_query.before) {
date_query_result.push(r.date <= args.date_query.before)
}
//只要有一个false,就是false。全部true才是true
if ( date_query_result.includes(false) ) {return false;}
}
return true;
}, args.fields )
if (args.meta_query) {
var meta_queried_comment_ids = [];
//先根据opts分别获取comment_id
var meta_query_result = [ /*[comment_ids],[comment_ids]*/ ]
args.meta_query.opts.forEach(({key,value,compare})=>{
var comment_ids = nvdb.commentmeta.find(r=>{
if (r.key !== key) {return false;}
try {
switch (compare) {
case '!=': return r.value !== value;
case '>': return r.value > value;
case '>=': return r.value >= value;
case '<=': return r.value <= value;
case 'LIKE': return r.value.toString().includes(value);
case 'NOT LIKE': return !r.value.toString().includes(value);
case 'IN': return value.includes(r.value);
case 'NOT IN': return !value.includes(r.value);
case 'BETWEEN': return r.value >= value[0] && r.value <=value[1];
case 'NOT BETWEEN': return r.value >= value[1] || r.value <=value[0];
default: return r.value == value;
}
} catch(e) {
console.log(e,`比较类型:${compare}`,`原始数据:`,r)
return false;
}
}).map(r=>r.comment_id)
meta_query_result.push(comment_ids)
})
//根据relation将每次获取的comment_id进行交集或并集
if (args.meta_query.relation == 'OR') {
// 取并集
meta_queried_comment_ids = meta_query_result.reduce( (arr1,arr2)=> arr1.concat(arr2.filter(v => !arr1.includes(v))) )
} else {
// 取交集
meta_queried_comment_ids = meta_query_result.reduce( (arr1,arr2)=> arr1.filter(v => arr2.includes(v)) )
}
//最后根据最终交或并结果的[comment_id]来过滤comments
var meta_comment_intersections = [];
comments.forEach(comment=>{
if ( meta_queried_comment_ids.includes(comment.id) ) {
meta_post_intersections.push(comment)
}
})
comments = meta_post_intersections;
}
// 至此,comments就是所有满足条件的内容。准备输出:
// 排序
if (args.orderby == 'rand') {
comments.sort(() => Math.random() - 0.5);
} else {
comments.sort((comment1,comment2)=>{
if ( typeof( comment1[args.orderby || 'date'] ) == 'string' ) {
var diff = comment1[args.orderby || 'date'].localeCompare( comment2[args.orderby || 'date'] )
} else {
var diff = comment1[args.orderby || 'date'] - comment2[args.orderby || 'date'];
}
return args.order == "ASC" ? diff : -diff;
})
}
// 分页
var current_page = parseInt(args.current_page) || 0;
if (current_page <= 0) {current_page = 1}
var comments_per_page = parseInt(args.comments_per_page) || 0;
if (comments_per_page <= 0) {comments_per_page = get_option('comments_per_page',10)}
var comments_start_index = ( current_page - 1 ) * comments_per_page;
var commentsPaged = comments.slice(comments_start_index, comments_start_index + comments_per_page);
var all_parent_level_ids = commentsPaged.map(r=>r.id);
//如果是按层次显示,那么还应该循环查找该页中所有的子级
if (args.hierarchical) {
var all_child_level_ids = [];
var getChildren = (parentIDs)=>{
var childrenIDs = db_comments.find(r=>{
if ( parentIDs.includes(r.parent) ) {
// 层级查询也应该查询相同status的数据。否则前台会显示出未审核的回复
if (args.status) {
if ( Array.isArray(args.status) ) {
if (!args.status.includes(r.status)) {return false;}
} else {
if (r.status !== args.status) {return false;}
}
}
return true;
}
}).map(r=>r.id);
if (childrenIDs.length > 0) {
all_child_level_ids = all_child_level_ids.concat(childrenIDs)
getChildren(childrenIDs)
}
}
getChildren( commentsPaged.map(r=>r.id) );
// 所有的子集id不应该包含父id
all_child_level_ids = all_child_level_ids.filter(id=>!all_parent_level_ids.includes(id))
var all_child_level_comments = db_comments.find(r=>all_child_level_ids.includes(r.id), args.fields );
// 对层次进行排序
if (args.orderby == 'rand') {
all_child_level_comments.sort(() => Math.random() - 0.5);
} else {
all_child_level_comments.sort((comment1,comment2)=>{
if ( typeof( comment1[args.orderby || 'date'] ) == 'string' ) {
var diff = comment1[args.orderby || 'date'].localeCompare( comment2[args.orderby || 'date'] )
} else {
var diff = comment1[args.orderby || 'date'] - comment2[args.orderby || 'date'];
}
return args.order == "ASC" ? diff : -diff;
})
}
commentsPaged = commentsPaged.concat( all_child_level_comments )
}
return {
data: commentsPaged,
pagination: {
current_page,
comments_per_page,
total: comments.length
}
}
}
global.delete_comment = (comment_id) => {
comment_id = parseInt(comment_id);
var comment = get_comment( comment_id );
if (is_nv_error(comment)) {return comment;}
// 删除前,调用钩子
do_action( 'nv_before_delete_comment', comment);
//如果本身是别人的parent,则将子集提升一级(子的parent变成自身的parent)
db_comments.setColumn(r=>r.parent == comment.id,{
parent: comment.parent || 0
})
//对文章的comment_count重新计数
var post = get_post(comment.post_id);
nv_set_post_fields( [comment.post_id],{
comment_count: ( parseInt(post.comment_count) || 0 ) - 1
} )
//删除meta
delete_comment_meta(comment_id);
//删除comment
db_comments.drop(r=>r.id == comment_id);
// 删除完成,调用钩子
do_action( 'nv_after_delete_comment', comment);
}
global.nv_set_comments_status = (comment_ids, target_status)=>{
// 查找和status不同的id
var before_comments = db_comments.find(r=>comment_ids.includes(r.id) && r.status !== target_status);
var ids = before_comments.map(r=>r.id);
// 有不同才设置
if (ids.length) {
db_comments.setColumn(r=>ids.includes(r.id),{status:target_status});
do_action('nv_set_comments_status',before_comments,target_status);
}
return ids;
}
global.nv_set_comment_fields = (comment_ids, obj)=>{
db_comments.setColumn(r=>comment_ids.includes(r.id),obj);
}
global.update_comment_meta = (comment_id,key,value) => {
return update_metadata('comment',comment_id,key,value);
}
global.get_comment_meta = (comment_id,key)=>{
return get_metadata('comment',comment_id,key);
}
global.delete_comment_meta = (comment_id,key) => {
return delete_metadata('comment',comment_id,key);
}