@rnaga/wp-node
Version:
👉 **[View Full Documentation at rnaga.github.io/wp-node →](https://rnaga.github.io/wp-node/)**
907 lines (906 loc) • 36.6 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostTrx = void 0;
const zod_1 = require("zod");
const common_1 = require("../common");
const config_1 = require("../config");
const components_1 = require("../core/components");
const current_1 = require("../core/current");
const options_1 = require("../core/options");
const comment_util_1 = require("../core/utils/comment.util");
const date_time_util_1 = require("../core/utils/date-time.util");
const link_util_1 = require("../core/utils/link.util");
const post_util_1 = require("../core/utils/post.util");
const query_util_1 = require("../core/utils/query.util");
const taxonomy_util_1 = require("../core/utils/taxonomy.util");
const validator_1 = require("../core/validator");
const database_1 = __importDefault(require("../database"));
const component_1 = require("../decorators/component");
const val = __importStar(require("../validators"));
const comment_trx_1 = require("./comment.trx");
const meta_trx_1 = require("./meta.trx");
const options_trx_1 = require("./options.trx");
const revision_trx_1 = require("./revision.trx");
const term_trx_1 = require("./term.trx");
const trx_1 = require("./trx");
const logger_1 = require("../core/logger");
let PostTrx = class PostTrx extends trx_1.Trx {
database;
logger;
components;
config;
postUtil;
taxonomyUtil;
commentUtil;
constructor(database, logger, components, config, postUtil, taxonomyUtil, commentUtil // private validator: Validator
) {
super(components);
this.database = database;
this.logger = logger;
this.components = components;
this.config = config;
this.postUtil = postUtil;
this.taxonomyUtil = taxonomyUtil;
this.commentUtil = commentUtil;
}
// update_posts_count
async updateCount() {
const queryUtil = this.components.get(query_util_1.QueryUtil);
const counts = await queryUtil.posts((query) => {
query.countPublished();
}, val.query.resultCount); //z.array(z.object({ count: z.number() })));
const count = counts?.count ?? 0;
const optionsTrx = this.components.get(options_trx_1.OptionsTrx);
await optionsTrx.insert("post_count", `${count}`);
}
// part of remove_user_from_blog
async changeAuthor(fromUserId, toUserId) {
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("posts"))
.where("post_author", fromUserId)
.update({
post_author: toUserId,
});
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to change author from: ${fromUserId} to: ${toUserId} - ${e}`);
}
await trx.commit();
return true;
}
// wp_insert_post
async upsert(input) {
const current = this.components.get(current_1.Current);
const options = this.components.get(options_1.Options);
const dateTimeUtil = this.components.get(date_time_util_1.DateTimeUtil);
let update = false;
let previousStatus = "new";
let postBefore = undefined;
let desiredPostSlug = undefined;
// Update
if (input.ID && 0 < input.ID) {
update = true;
postBefore = await this.postUtil.get(input.ID);
if (!postBefore.props) {
throw new Error(`Post not found - ${input.ID}`);
}
input.guid = postBefore.props.guid;
previousStatus = postBefore.props.post_status;
desiredPostSlug = await postBefore.meta.get("_wp_desired_post_slug");
// Combine input with existing record
input = {
...postBefore.props,
post_categeory: ((await postBefore.terms("category")) ?? []).map((v) => v.term_id),
tags_input: ((await postBefore.terms("post_tag")) ?? []).map((v) => v.term_id),
...input,
};
}
const parsedInput = val.trx.postUpsert.parse(input);
const postDate = dateTimeUtil.get(input.post_date);
const data = {
ID: parsedInput.ID ?? 0,
context: parsedInput.context,
file: parsedInput.file,
guid: parsedInput.guid,
post_date: postDate.mySQLDatetime,
post_date_gmt: postDate.mySQLGMTDatetime,
meta_input: parsedInput.meta_input,
post_status: parsedInput.post_status ?? "draft",
post_type: parsedInput.post_type ?? "post",
post_title: parsedInput.post_title,
post_content: parsedInput.post_content,
post_excerpt: parsedInput.post_excerpt,
post_name: parsedInput.post_name,
post_parent: parsedInput.post_parent,
pinged: parsedInput.pinged,
import_id: parsedInput.import_id,
post_content_filtered: parsedInput.post_content_filtered,
tags_input: parsedInput.tags_input,
tax_input: parsedInput.tax_input,
};
data.post_name =
parsedInput.post_name ??
(update && postBefore && postBefore.props
? postBefore.props.post_name
: "");
const postTypeObject = this.postUtil.getTypeObject(data.post_type);
// Check empry fields
if (["editor", "title", "excerpt"].every((v) => postTypeObject?.supports.includes(v)) &&
!parsedInput.post_content &&
!parsedInput.post_title &&
!parsedInput.post_excerpt) {
throw new Error("Content, title, and excerpt are empty.");
}
if (data.post_type == "attachment" &&
!["inherit", "private", "trash", "auto-draft"].includes(data.post_status)) {
data.post_status = "inherit";
}
let postCategory = [];
if (Array.isArray(parsedInput.post_categeory)) {
postCategory = parsedInput.post_categeory.filter((v) => v > 0);
}
else if (update && !parsedInput.post_categeory) {
postCategory = !postBefore
? []
: (await postBefore.terms("category"))?.map((term) => term.term_id) ??
[];
}
// Make sure we set a valid category.
if (0 >= postCategory.length &&
"post" === data.post_type &&
"auto-draft" !== data.post_status) {
const defaultCategory = (await options.get("default_category")) ?? [];
if (!Array.isArray(defaultCategory)) {
postCategory = [defaultCategory];
}
}
data.post_categeory = postCategory;
/*
* Don't allow contributors to set the post slug for pending review posts.
*
* For new posts check the primitive capability, for updates check the meta capability.
*/
if ("pending" === data.post_status &&
((!update &&
postTypeObject?.capabilities &&
!(await current.user?.can(postTypeObject.capabilities["publish_posts"]))) ||
(update && !(await current.user?.can("publish_post", data.ID))))) {
data.post_name = "";
}
const validator = this.components.get(validator_1.Validator);
/*
* Create a valid post name. Drafts and pending posts are allowed to have
* an empty post name.
*/
if (0 >= data.post_name.length) {
if (!["draft", "pending", "auto-draft"].includes(data.post_status)) {
data.post_name =
validator.fieldSafe("posts", "post_title", data.post_title) ?? "";
}
else {
data.post_name = "";
}
}
else {
// New post, or slug has changed.
data.post_name =
validator.fieldSafe("posts", "post_title", data.post_name) ?? "";
}
data.post_modified = data.post_date;
data.post_modified_gmt = data.post_date_gmt;
if (update) {
const currentDateTime = dateTimeUtil.get();
data.post_modified = currentDateTime.mySQLDatetime;
data.post_modified_gmt = currentDateTime.mySQLGMTDatetime;
}
if ("attachment" !== data.post_type) {
const postDate = dateTimeUtil.get(data.post_date_gmt);
if ("publish" === data.post_status && postDate.isFuture()) {
data.post_status = "future";
}
else if ("future" === data.post_status && !postDate.isFuture()) {
data.post_status = "publish";
}
}
// Comment status.
data.comment_status = parsedInput.comment_status
? parsedInput.comment_status
: update
? "closed"
: await this.commentUtil.getDefaultStatus(data.post_type);
// These variables are needed by compact() later.
data.post_author =
parsedInput.post_author > 0
? parsedInput.post_author
: current.user?.props?.ID ?? -1;
data.ping_status =
parsedInput.ping_status ??
this.commentUtil.getDefaultStatus(data.post_type, "pingback");
data.to_ping = data.to_ping
? validator.fieldSafe("posts", "to_ping", parsedInput.to_ping)
: "";
/*
* The 'wp_insert_post_parent' filter expects all variables to be present.
* Previously, these variables would have already been extracted
*/
data.menu_order = parsedInput.menu_order ?? 0;
data.post_password = parsedInput.post_password ?? "";
if ("private" === data.post_status) {
data.post_password = "";
}
const postNameTrashedSuffix = this.config.config.constants.TRASHED_SUFFIX_TO_POST_NAME_FOR_POST;
/*
* If the post is being untrashed and it has a desired slug stored in post meta,
* reassign it.
*/
if ("trash" === previousStatus && "trash" !== data.post_status) {
data.post_name = data.post_name.endsWith(postNameTrashedSuffix)
? data.post_name.replace(postNameTrashedSuffix, "")
: data.post_name;
if (desiredPostSlug) {
data.post_name = desiredPostSlug;
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
await metaTrx.remove("post", {
objectId: data.ID,
key: "_wp_desired_post_slug",
});
}
}
// When trashing an existing post, change its slug to allow non-trashed posts to use it.
if ("trash" === data.post_status &&
"trash" !== previousStatus &&
"new" !== previousStatus &&
postBefore?.props?.post_name &&
!postBefore.props.post_name.endsWith(postNameTrashedSuffix)) {
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
await metaTrx.upsert("post", data.ID, "_wp_desired_post_slug", data.post_name);
data.post_name = `${postBefore.props.post_name}${postNameTrashedSuffix}`;
}
data.post_name = await this.postUtil.getUniqueSlug(data.post_name, data.ID);
// Don't unslash.
data.post_mime_type = parsedInput.post_mime_type ?? "";
let dataUpsert = {};
try {
dataUpsert = validator.execAny(update ? val.trx.postUpdate : val.trx.postInsert, Object.entries(data)
.map(([key, value]) => ({
[key]: common_1.formatting.unslash(value),
}))
.reduce((obj, item) => ({ ...obj, ...item }), {}));
}
catch (e) {
this.logger.warn(`parse error: ${e}`, { data });
throw e;
}
if (!dataUpsert) {
throw new Error(`Invalid post data - ${JSON.stringify(data)}`);
}
dataUpsert.post_date = data.post_date;
dataUpsert.post_date_gmt = data.post_date_gmt;
let trx = await this.database.transaction;
try {
if (update) {
await trx
.table(this.tables.get("posts"))
.where("ID", data.ID)
.update(dataUpsert);
}
else {
await trx
.insert(dataUpsert)
.into(this.tables.get("posts"))
.then((v) => {
data.ID = v[0];
});
}
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to insert post - ${e}`);
}
await trx.commit();
const post = await this.postUtil.get(data.ID);
if (!post.props) {
throw new Error(`Post Not Found - ${data.ID}`);
}
const postId = post.props.ID;
// Set slug with title
if (0 >= data.post_name.length &&
!["draft", "pending", "auto-draft"].includes(data.post_status)) {
data.post_name = await this.postUtil.getUniqueSlug(common_1.formatting.slug(data.post_title), post);
trx = await this.database.transaction;
try {
await trx.table(this.tables.get("posts")).where("ID", postId).update({
post_name: data.post_name,
});
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to update slug - ${e}`);
}
await trx.commit();
}
// Sync categories
const taxonomyCategory = await this.taxonomyUtil.get("category");
if (!taxonomyCategory.isDefault &&
taxonomyCategory.props?.objectType == data.post_type) {
await this.syncCategories(post.props.ID, data.post_categeory);
}
// Sync tags
const taxonomyPostTag = await this.taxonomyUtil.get("post_tag");
if (data.tags_input &&
!taxonomyPostTag.isDefault &&
taxonomyPostTag.props?.objectType == data.post_type) {
await this.syncTerms(postId, data.tags_input);
}
let taxonomyInput = data.tax_input;
// Add default term for all associated custom taxonomies.
if ("auto-draft" !== data.post_status) {
for (const taxonomy of await this.taxonomyUtil.getList({
objectType: post.props.post_type,
})) {
if (!taxonomy.props?.default_term) {
continue;
}
// Filter out empty terms.
if (taxonomyInput && taxonomyInput[taxonomy.name]) {
taxonomyInput[taxonomy.name] = taxonomyInput[taxonomy.name].filter((v) => typeof v == "number" || v.length > 0);
}
// Passed custom taxonomy list overwrites the existing list if not empty.
const terms = ((await this.components.get(query_util_1.QueryUtil).terms((query) => {
query.withObjectIds([postId]).where("taxonomy", taxonomy.name);
})) ?? []).map((v) => v.term_id);
if (terms.length > 0 &&
(!taxonomyInput || !taxonomyInput[taxonomy.name])) {
taxonomyInput = { ...taxonomyInput, [taxonomy.name]: terms };
}
// Set default term id
if (taxonomy.props.default_term &&
(!taxonomyInput || !taxonomyInput[taxonomy.name])) {
taxonomyInput = {
...taxonomyInput,
[taxonomy.name]: [taxonomy.props.default_term],
};
}
}
}
for (const [taxonomyName, tags] of Object.entries(taxonomyInput ?? {})) {
const taxonomy = await this.taxonomyUtil.get(taxonomyName);
if (taxonomy.isDefault) {
continue;
}
if (taxonomy.props?.capabilities?.["assign_terms"] &&
(await current.user?.can(taxonomy.props?.capabilities["assign_terms"]))) {
await this.syncTerms(postId, tags, taxonomy.name);
}
}
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
const metaInput = data.meta_input;
if (metaInput) {
for (const [key, value] of Object.entries(metaInput)) {
await metaTrx.upsert("post", postId, key, value, {
serialize: typeof value == "object" || Array.isArray(value),
});
}
}
// Set GUID.
if (0 >= post.props.guid.length) {
const linkUtil = this.components.get(link_util_1.LinkUtil);
trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("posts"))
.where("ID", postId)
.update({
guid: await linkUtil.getPermalink(post),
});
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to udpate guid - ${e}`);
}
await trx.commit();
}
if ("attachment" === data.post_type) {
if (0 < data.file.length) {
await this.syncAttachedFile(postId, data.file);
}
if (0 < data.context.length) {
await metaTrx.upsert("post", postId, "_wp_attachment_context", data.context);
}
}
return postId;
}
// wp_delete_post
async remove(postId, force = false) {
const EMPTY_TRASH_DAYS = this.config.config.constants.EMPTY_TRASH_DAYS;
const queryUtil = this.components.get(query_util_1.QueryUtil);
const posts = await queryUtil.posts((query) => {
query.where("ID", postId);
});
if (!posts) {
return false;
}
const post = await this.postUtil.get(postId);
if (!post.props) {
return false;
}
const postType = post.props.post_type;
if (!force &&
("post" === postType || "page" === postType) &&
"trash" === (await this.postUtil.getStatus(post)) &&
EMPTY_TRASH_DAYS > 0) {
return await this.trash(postId);
}
if ("attachment" === postType) {
return await this.removeAttachment(postId, force);
}
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
await metaTrx.remove("post", {
objectId: postId,
key: "_wp_trash_meta_status",
});
await metaTrx.remove("post", {
objectId: postId,
key: "_wp_trash_meta_time",
});
const taxonomyUtil = this.components.get(taxonomy_util_1.TaxonomyUtil);
const taxonomies = await taxonomyUtil.getList({
objectType: postType,
});
const termTrx = this.components.get(term_trx_1.TermTrx);
await termTrx.removeObjectTermRelationships(postId, taxonomies.map((taxonomy) => taxonomy.name));
const postTypeObject = this.postUtil.getTypeObject(postType);
if (postTypeObject?.hierarchical) {
// Point children of this page to its parent, also clean the cache of affected children.
const children = await queryUtil.posts((query) => {
query.where("ID", postId).where("post_type", postType);
});
if (children) {
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("posts"))
.where("post_parent", postId)
.where("post_type", postType)
.update({
post_parent: post.props.post_parent,
});
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to update post - ${e}`);
}
await trx.commit();
}
}
const revisionsIds = ((await queryUtil.posts((query) => {
query.where("post_parent", postId).where("post_type", "revision");
})) ?? []).map((post) => post.ID);
const revisionTrx = this.components.get(revision_trx_1.RevisionTrx);
for (const revisionId of revisionsIds) {
await revisionTrx.remove(revisionId);
}
// Point all attachments to this post up one level.
let trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("posts"))
.where("post_parent", postId)
.where("post_type", "attachment")
.update({
post_parent: post.props.post_parent,
});
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to update attachment - ${e} `);
}
await trx.commit();
const commentIds = ((await queryUtil.comments((query) => {
const { column } = query.alias;
query
.where("post_ID", postId)
.builder.orderBy(column("comments", "comment_ID"), "desc");
})) ?? []).map((comment) => comment.comment_ID);
const commentTrx = this.components.get(comment_trx_1.CommentTrx);
for (const commentId of commentIds) {
await commentTrx.remove(commentId, true);
}
await metaTrx.removeObject("post", postId);
trx = await this.database.transaction;
try {
await trx.table(this.tables.get("posts")).where("ID", postId).del();
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to delete post - ${e}`);
}
await trx.commit();
return post;
}
// wp_insert_attachment
async insertAttachment(input, args) {
const { file, parentPostId } = args ?? {};
input = {
...input,
file: file ?? input.file,
post_parent: parentPostId ?? input.post_parent,
post_type: "attachment",
};
return this.upsert(input);
}
// wp_update_attachment_metadata
async syncAttachmentMetadata(postId, args) {
const { data, remove = false } = args;
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
const key = "_wp_attachment_metadata";
if (true !== remove) {
await metaTrx.upsert("post", postId, key, data, {
serialize: true,
});
}
else {
await metaTrx.remove("post", {
objectId: postId,
key,
});
}
}
// wp_delete_attachment
async removeAttachment(postId, force = false) {
const EMPTY_TRASH_DAYS = this.config.config.constants.EMPTY_TRASH_DAYS;
const MEDIA_TRASH = this.config.config.constants.MEDIA_TRASH;
const post = await this.postUtil.get(postId);
if (!post.props || "attachment" == post.props.post_status) {
return false;
}
if (!force &&
EMPTY_TRASH_DAYS > 0 &&
MEDIA_TRASH &&
"trash" !== post.props.post_status) {
return await this.trash(postId);
}
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
await metaTrx.remove("post", {
objectId: postId,
key: "_wp_trash_meta_status",
});
await metaTrx.remove("post", {
objectId: postId,
key: "_wp_trash_meta_time",
});
const queryUtil = this.components.get(query_util_1.QueryUtil);
// const attachmentMeta = await queryUtil.meta(
// "post",
// (query) => {
// query
// .withIds([postId])
// .withKeys(["_wp_attachment_metadata"])
// .builder.first();
// },
// val.database.wpPostMeta
// );
// const backupSize = await queryUtil.meta(
// "post",
// (query) => {
// query
// .withIds([postId])
// .withKeys(["_wp_attachment_backup_sizes"])
// .builder.first();
// },
// val.database.wpPostMeta
// );
// const file = await this.postUtil.getAttachedFile(postId);
// wp_delete_object_term_relationships
const termTrx = this.components.get(term_trx_1.TermTrx);
await termTrx.removeObjectTermRelationships(postId, [
"category",
"post_tag",
]);
//await termTrx.syncObject(postId, [], "category");
//await termTrx.syncObject(postId, [], "post_tag");
const taxonomyUtil = this.components.get(taxonomy_util_1.TaxonomyUtil);
const taxonomies = await taxonomyUtil.getList({
objectType: post.props.post_type,
});
for (const taxonomy of taxonomies) {
if (!["category", "post_tag"].includes(taxonomy.name)) {
await termTrx.removeObjectTermRelationships(postId, [taxonomy.name]);
///await termTrx.syncObject(postId, [], taxonomy.name);
}
}
// Delete all for any posts.
await metaTrx.remove("post", {
key: "_thumbnail_id",
value: `${postId}`,
deleteAll: true,
});
const comments = (await queryUtil.comments((query) => {
const { column } = query.alias;
query
.where("post_ID", postId)
.builder.orderBy(column("comments", "comment_ID"), "desc");
})) ?? [];
const commentTrx = this.components.get(comment_trx_1.CommentTrx);
for (const comment of comments) {
await commentTrx.remove(comment.comment_ID, true);
}
await metaTrx.removeObject("post", postId);
const trx = await this.database.transaction;
try {
await trx.table(this.tables.get("posts")).where("ID", postId).del();
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to delete post - ${e}`);
}
await trx.commit();
// wp_delete_attachment_files
return post;
}
// wp_untrash_post
async untrash(postId) {
const post = await this.postUtil.get(postId);
if (!post.props || "trash" !== post.props.post_status) {
return false;
}
const previousStatus = await post.meta.get("_wp_trash_meta_status");
const newStatus = "attachment" === post.props.post_type
? "inherit"
: previousStatus
? previousStatus
: "draft";
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
await metaTrx.remove("post", {
objectId: postId,
key: "_wp_trash_meta_status",
});
await metaTrx.remove("post", {
objectId: postId,
key: "_wp_trash_meta_time",
});
const postUpdated = await this.upsert({
ID: postId,
post_status: newStatus,
});
if (!postUpdated) {
return false;
}
await this.untrashComments(post);
return post;
}
// wp_untrash_post_comments
async untrashComments(postIdOrPost) {
let post;
if (typeof postIdOrPost == "number") {
post = await this.postUtil.get(postIdOrPost);
}
else {
post = postIdOrPost;
}
if (!post.props) {
return false;
}
const postId = post.props.ID;
const commentStatuses = await post.meta.get("_wp_trash_meta_comments_status");
if (!commentStatuses) {
return true;
}
const groupByStatus = new Map();
for (const [k, v] of Object.entries(commentStatuses)) {
groupByStatus.set(`${v}`, [
...(groupByStatus.get(`${v}`) ?? []),
parseInt(k),
]);
}
for (const [k, v] of groupByStatus.entries()) {
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("comments"))
.whereIn("comment_ID", v)
.update({
comment_approved: k,
});
}
catch (e) {
trx.rollback();
throw new Error(`Failed to update post comments - ${e}`);
}
await trx.commit();
}
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
await metaTrx.remove("post", {
objectId: postId,
key: "_wp_trash_meta_comments_status",
});
return true;
}
// wp_trash_post
async trash(postId) {
const EMPTY_TRASH_DAYS = this.config.config.constants.EMPTY_TRASH_DAYS;
const post = await this.postUtil.get(postId);
if (!post.props || "trash" == post.props.post_status) {
return undefined;
}
if (!EMPTY_TRASH_DAYS) {
await this.remove(postId);
return post;
}
const previousStatus = post.props.post_status;
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
await metaTrx.upsert("post", postId, "_wp_trash_meta_status", previousStatus);
await metaTrx.upsert("post", postId, "_wp_trash_meta_time", (0, common_1.currentUnixTimestamp)());
const postUpdated = await this.upsert({
ID: postId,
post_status: "trash",
});
if (!postUpdated) {
return undefined;
}
await this.trashComments(postId);
return post;
}
// wp_trash_post_comments
async trashComments(postOrId) {
const post = typeof postOrId == "number"
? await this.postUtil.get(postOrId)
: postOrId;
if (!post?.props) {
return false;
}
const postId = post.props.ID;
const queryUtil = this.components.get(query_util_1.QueryUtil);
const comments = await queryUtil.comments((query) => {
query.where("post_ID", postId);
}, zod_1.z.array(val.database.wpComments.pick({
comment_ID: true,
comment_approved: true,
})));
if (!comments) {
return false;
}
const statuses = {};
comments.forEach((comments) => {
statuses[comments.comment_ID] = comments.comment_approved;
});
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
await metaTrx.upsert("post", postId, "_wp_trash_meta_comments_status", statuses, {
serialize: true,
});
// Set status for all comments to post-trashed.
const trx = await this.database.transaction;
let result = 0;
try {
await trx
.table(this.tables.get("comments"))
.where("comment_post_ID", postId)
.update({
comment_approved: "post-trashed",
})
.then((v) => {
result = v;
});
}
catch (e) {
trx.rollback();
throw new Error(`Failed to update post comments - ${e}`);
}
await trx.commit();
return result;
}
// update_attached_file
async syncAttachedFile(postId, file) {
const post = await this.postUtil.get(postId);
if (!post.props) {
return;
}
const staticAssetsPath = this.config.config.staticAssetsPath;
file = file
.replace(new RegExp(`^${staticAssetsPath}`), "")
.replace(/^\/+/, "");
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
if (file.length > 0) {
await metaTrx.upsert("post", postId, "_wp_attached_file", file);
}
else {
await metaTrx.remove("post", {
objectId: postId,
key: "_wp_attached_file",
});
}
}
// wp_set_post_categories
async syncCategories(postId, namesOrTermIds, append = false) {
const post = await this.postUtil.get(postId);
if (!post.props) {
return;
}
if (0 >= namesOrTermIds.length) {
const taxonomy = await this.taxonomyUtil.get("category");
if (!taxonomy.props?.default_term) {
return;
}
if ("auto-draft" !== post.props.post_status) {
namesOrTermIds = [taxonomy.props?.default_term];
}
}
const termTrx = this.components.get(term_trx_1.TermTrx);
return await termTrx.syncObject(postId, namesOrTermIds, "category", append);
}
async syncTerms(postId, slugsOrTermIds, taxonomyName = "post_tag", append = false) {
const post = await this.postUtil.get(postId);
if (!post.props) {
return;
}
/*
* Hierarchical taxonomies must always pass IDs rather than names so that
* children with the same names but different parents aren't confused.
*/
if (await this.taxonomyUtil.isHierarchical(taxonomyName)) {
slugsOrTermIds = slugsOrTermIds.map((slugOrTermId) => typeof slugOrTermId == "string" ? parseInt(slugOrTermId) : slugOrTermId);
}
const termTrx = this.components.get(term_trx_1.TermTrx);
return await termTrx.syncObject(postId, slugsOrTermIds, taxonomyName, append);
}
};
exports.PostTrx = PostTrx;
exports.PostTrx = PostTrx = __decorate([
(0, component_1.transactions)(),
__metadata("design:paramtypes", [database_1.default,
logger_1.Logger,
components_1.Components,
config_1.Config,
post_util_1.PostUtil,
taxonomy_util_1.TaxonomyUtil,
comment_util_1.CommentUtil // private validator: Validator
])
], PostTrx);