@rnaga/wp-node
Version:
👉 **[View Full Documentation at rnaga.github.io/wp-node →](https://rnaga.github.io/wp-node/)**
839 lines (838 loc) • 34.9 kB
JavaScript
;
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.TermTrx = void 0;
const zod_1 = require("zod");
const common_1 = require("../common");
const components_1 = require("../core/components");
const logger_1 = require("../core/logger");
const options_1 = require("../core/options");
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 term_util_1 = require("../core/utils/term.util");
const validator_1 = require("../core/validator");
const database_1 = __importDefault(require("../database"));
const component_1 = require("../decorators/component");
const query_builder_1 = require("../query-builder");
const val = __importStar(require("../validators"));
const meta_trx_1 = require("./meta.trx");
const trx_1 = require("./trx");
let TermTrx = class TermTrx extends trx_1.Trx {
database;
logger;
components;
taxonomyUtil;
termUtil;
postUtil;
validator;
constructor(database, logger, components, taxonomyUtil, termUtil, postUtil, validator) {
super(components);
this.database = database;
this.logger = logger;
this.components = components;
this.taxonomyUtil = taxonomyUtil;
this.termUtil = termUtil;
this.postUtil = postUtil;
this.validator = validator;
}
// wp_update_term_count
// wp_update_term_count_now
async updateCount(termTaxonomyIds, taxonomy) {
const queryUtil = this.components.get(query_util_1.QueryUtil);
if (typeof taxonomy == "string") {
taxonomy = await this.taxonomyUtil.get(taxonomy);
}
if (taxonomy.isDefault || !taxonomy.props?.objectType) {
return;
}
let objectTypes = taxonomy.props.objectType.split(":");
let isAttachment = false;
if (objectTypes.includes("attachment")) {
isAttachment = true;
objectTypes = objectTypes.filter((o) => o != "attachment");
}
// To unique array
objectTypes = [...new Set(objectTypes)];
const isPostType = objectTypes.filter((objectType) => this.postUtil.getTypeObject(objectType)).length > 0;
// For posts - _update_post_term_count
for (const termTaxonomyId of termTaxonomyIds) {
let count = 0, counts;
const postStatuses = ["publish"];
if (isPostType || isAttachment) {
if (isAttachment) {
counts = await queryUtil.posts((query) => {
query.countAttachment(termTaxonomyId, postStatuses);
}, val.query.resultCount);
}
count += counts?.count ?? 0;
if (objectTypes.length > 0) {
counts = await queryUtil.posts((query) => {
query.countTerm(termTaxonomyId, postStatuses, objectTypes);
}, val.query.resultCount);
}
count += counts?.count ?? 0;
// _update_generic_term_count
}
else {
counts = await queryUtil.terms((query) => {
query.selectTermRelationships
.where("terms_relationships.term_taxonomy_id", termTaxonomyId)
.builder.count("* as count")
.first();
}, val.query.resultCount);
count = counts?.count ?? 0;
}
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("term_taxonomy"))
.update({
count,
})
.where("term_taxonomy_id", termTaxonomyId);
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to update term count - ${termTaxonomyId}`);
}
await trx.commit();
}
}
async updateTermOrder(objectId, taxonomyName, termTaxonomyIds, options) {
const { append = true } = options ?? {};
const queryUtil = this.components.get(query_util_1.QueryUtil);
termTaxonomyIds = termTaxonomyIds ?? [];
// Get terms associated with the object
const existingTerms = (await queryUtil.terms((query) => {
query.withObjectIds([objectId]).where("taxonomy", taxonomyName);
})) ?? [];
// Get term taxonomy ids excluding the passed term taxonomy ids
const existingTermTaxonomyIds = existingTerms
.filter((term) => !termTaxonomyIds?.includes(term.term_taxonomy_id))
.map((term) => term.term_taxonomy_id);
// if append is true, append the termTaxonomyIds to the existingTermTaxonomyIds
// else, append the existingTermTaxonomyIds to the termTaxonomyIds
termTaxonomyIds = append
? [...existingTermTaxonomyIds, ...termTaxonomyIds]
: [...termTaxonomyIds, ...existingTermTaxonomyIds];
let termOrder = 0;
for (const termTaxonomyId of termTaxonomyIds) {
// Check if term relationships exists for the object
const term = existingTerms.find((term) => term.term_taxonomy_id === termTaxonomyId);
// Skip if term not found
if (!term) {
continue;
}
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("term_relationships"))
.where("object_id", objectId)
.where("term_taxonomy_id", termTaxonomyId)
.update({
term_order: termOrder++,
});
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to update term order - ${termTaxonomyId}`);
}
await trx.commit();
}
}
// wp_delete_object_term_relationships
async removeObjectTermRelationships(objectId, taxonomyNames) {
const queryUtil = this.components.get(query_util_1.QueryUtil);
for (const taxonomyName of taxonomyNames) {
const termIds = ((await queryUtil.terms((query) => {
query.withObjectIds([objectId]).where("taxonomy", taxonomyName);
})) ?? []).map((term) => term.term_id);
if (termIds.length > 0) {
await this.removeObject(objectId, termIds, await this.taxonomyUtil.get(taxonomyName));
}
}
}
// wp_remove_object_terms
async removeObject(objectId, terms, taxonomy) {
const queryUtil = this.components.get(query_util_1.QueryUtil);
if (taxonomy.isDefault) {
return false;
}
if (0 >= terms.length) {
return false;
}
const termsTaxonomyIds = ((await queryUtil.terms((query, builders) => {
query.where("taxonomy", taxonomy.name).builder.where((subBuilder) => {
const subQuery = builders.get(query_builder_1.TermsQuery, subBuilder, query.alias);
for (const slugOrTermId of terms) {
if (typeof slugOrTermId == "string") {
subQuery.andWhere((query) => query
.where("slug", common_1.formatting.slug(slugOrTermId))
.or.where("name", slugOrTermId));
}
else {
subQuery.where("term_id", slugOrTermId);
}
subQuery.builder.or;
}
});
})) ?? []).map((v) => v.term_taxonomy_id);
if (0 >= termsTaxonomyIds.length) {
return false;
}
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("term_relationships"))
.where("object_id", objectId)
.whereIn("term_taxonomy_id", termsTaxonomyIds)
.del();
}
catch (e) {
await trx.rollback();
return false;
}
await trx.commit();
await this.updateCount(termsTaxonomyIds, taxonomy);
await this.updateTermOrder(objectId, taxonomy.name);
return true;
}
// wp_set_object_terms
async syncObject(objectId, namesOrTermIds, taxonomyName, append = false) {
const queryUtil = this.components.get(query_util_1.QueryUtil);
const taxonomy = await this.taxonomyUtil.get(taxonomyName);
if (taxonomy.isDefault) {
throw new Error(`Taxonomy Not Found`);
}
// Format slugs
namesOrTermIds = namesOrTermIds
.map((namesOrTermIds) => typeof namesOrTermIds == "string"
? namesOrTermIds.trim()
: namesOrTermIds)
.filter((term) => (typeof term == "string" ? term.length > 0 : true));
const oldTermTaxonomyIds = ((await queryUtil.terms((query) => {
query.withObjectIds([objectId]).where("taxonomy", taxonomyName);
})) ?? []).map((v) => v.term_taxonomy_id);
const termTaxonomyIds = [], newTermTaxonomyIds = [];
for (const nameOrTermId of namesOrTermIds) {
const terms = await queryUtil.terms((query) => {
if (typeof nameOrTermId == "string") {
query.andWhere((query) => query
.where("slug", common_1.formatting.slug(nameOrTermId))
.or.where("name", nameOrTermId));
}
else {
query.where("term_id", nameOrTermId);
}
query.where("taxonomy", taxonomyName);
});
let termTaxonomyId = 0;
if (!terms) {
// Skip if a non-existent term ID is passed.
if (typeof nameOrTermId == "number")
continue;
// Create a new term since slugOrTermId is a slug
const newTerm = await this.insert(nameOrTermId, taxonomyName);
termTaxonomyId = newTerm.term_taxonomy_id;
}
else {
termTaxonomyId = terms[0].term_taxonomy_id;
}
termTaxonomyIds.push(termTaxonomyId);
// Check if term relationships already exists
const termRelationships = (await queryUtil.terms((query) => {
query.selectTermRelationships
.where("object_id", objectId)
.where("terms_relationships.term_taxonomy_id", termTaxonomyId);
}, zod_1.z.array(val.database.wpTermRelationships))) ?? [];
if (0 < termRelationships.length) {
continue;
}
const trx = await this.database.transaction;
try {
await trx
.insert({
object_id: objectId,
term_taxonomy_id: termTaxonomyId,
})
.into(this.tables.get("term_relationships"));
}
catch (e) {
await trx.rollback();
this.logger.warn(`Failed to insert terms relationships - ${e}`, {
error: e,
});
throw e;
}
await trx.commit();
// Add new taxonomy Id for later comparison
newTermTaxonomyIds.push(termTaxonomyId);
}
if (newTermTaxonomyIds.length > 0) {
await this.updateCount(newTermTaxonomyIds, taxonomy);
}
// If append is false, remove old term relationships
if (!append) {
const deleteTermTaxonomyIds = oldTermTaxonomyIds.filter((v) => !termTaxonomyIds.includes(v));
const deleteTermIds = ((await queryUtil.terms((query) => {
query.selectTermTaxonomy
.whereIn("term_taxonomy_id", deleteTermTaxonomyIds)
.where("taxonomy", taxonomyName);
}, zod_1.z.array(val.database.wpTermTaxonomy))) ?? []).map((v) => v.term_id);
if (0 < deleteTermTaxonomyIds.length) {
await this.removeObject(objectId, deleteTermIds, taxonomy);
}
// Update term_order
// let termOrder = 0;
// const dataInsert = (
// (await queryUtil.terms((query) => {
// query.withObjectIds([objectId]).where("taxonomy", taxonomyName);
// })) ?? []
// ).map((v) => ({
// object_id: objectId,
// term_taxonomy_id: v.term_taxonomy_id,
// term_order: termOrder++,
// }));
// if (dataInsert.length > 0) {
// const trx = await this.database.transaction;
// try {
// await trx
// .insert(dataInsert)
// .into(this.tables.get("term_relationships"))
// .onConflict("term_order")
// .merge(["term_order"]);
// } catch (e) {
// await trx.rollback();
// throw new Error(`Failed to insert term object - ${e}`);
// }
// await trx.commit();
// }
await this.updateCount(termTaxonomyIds, taxonomy);
}
await this.updateTermOrder(objectId, taxonomyName, termTaxonomyIds);
return termTaxonomyIds;
}
// _split_shared_term
async splitSharedTerm(termId, termTaxonomyId
//record: boolean = false
) {
const queryUtil = this.components.get(query_util_1.QueryUtil);
// If there are no shared term_taxonomy rows, there's nothing to do here.
const sharedCount = (await queryUtil.terms((query) => {
query.selectTermTaxonomy
.where("term_id", termId)
.builder.not.__ref(query)
.where("term_taxonomy_id", termTaxonomyId)
.builder.clear("select")
.count("* as count");
}, zod_1.z.array(zod_1.z.object({ count: zod_1.z.number() })))) ?? [{ count: 0 }];
if (0 >= sharedCount[0]["count"]) {
return termId;
}
const checkTermId = await queryUtil.terms((query) => {
query.selectTermTaxonomy
.where("term_taxonomy_id", termTaxonomyId)
.builder.limit(1);
}, zod_1.z.array(val.database.wpTermTaxonomy));
if (checkTermId && checkTermId[0].term_taxonomy_id != termTaxonomyId) {
return checkTermId[0].term_taxonomy_id;
}
// / Pull up data about the currently shared slug, which we'll use to populate the new one.
const sharedTerm = await this.termUtil.get(termId);
if (!sharedTerm.props?.term_id) {
throw new Error(`Term Not Found - ${termId}`);
}
const newTermData = {
name: sharedTerm.props?.name,
slug: sharedTerm.props.slug,
term_group: sharedTerm.props.term_group,
};
const trx = await this.database.transaction;
let builder;
let newTermId = 0;
try {
await trx
.insert(newTermData)
.into(this.tables.get("terms"))
.then((r) => {
newTermId = r[0];
});
}
catch (e) {
await trx.rollback();
throw new Error(`Error to Insert - ${e}`);
}
if (0 >= newTermId) {
await trx.rollback();
throw new Error(`Failed to Insert new Term - ${termId}`);
}
try {
builder = trx
.table(this.tables.get("term_taxonomy"))
.where("term_taxonomy_id", termTaxonomyId)
.update({
term_id: newTermId,
});
await builder;
}
catch (e) {
await trx.rollback();
throw new Error(`Error to update Term Taxonomy - ${e}`);
}
const termTaxonomy = await queryUtil.terms((query) => {
query.where("term_taxonomy_id", termTaxonomyId);
});
if (!termTaxonomy || !termTaxonomy[0].taxonomy) {
await trx.rollback();
throw new Error(`Term Taxonomy not Found - ${termTaxonomyId}`);
}
const termTaxonomyName = termTaxonomy[0].taxonomy;
const childrenTermTaxonomies = (await queryUtil.terms((query) => {
query.selectTermTaxonomy
.where("parent", termId)
.where("taxonomy", termTaxonomyName);
}, zod_1.z.array(val.database.wpTermTaxonomy))) ?? [];
for (const termTaxonomy of childrenTermTaxonomies) {
try {
builder = trx
.table(this.tables.get("term_taxonomy"))
.where("term_taxonomy_id", termTaxonomy.term_taxonomy_id)
.update({
parent: newTermId,
});
await builder;
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to update child term taxonomy - ${termTaxonomy.term_id}`);
}
}
await trx.commit();
return newTermId;
}
async syncTermGroup(termGroup, aliasOf, taxonomyName) {
const queryUtil = this.components.get(query_util_1.QueryUtil);
if (aliasOf.length > 0) {
const aliasTerms = await queryUtil.terms((query) => {
query.exists("slug", aliasOf, taxonomyName);
});
if (aliasTerms && 0 <= aliasTerms[0].term_group) {
termGroup = aliasTerms[0].term_group;
}
else if (aliasTerms && aliasTerms[0].term_id) {
const aliasTermId = aliasTerms[0].term_id;
const newTermGroup = await queryUtil.terms((query) => {
query.maxGroup();
}, val.query.termsGroupMaxCountResult);
if (!newTermGroup) {
throw new Error("new Max Group not obtained");
}
termGroup = newTermGroup[0]["max"];
await this.update(aliasTermId, taxonomyName, {
termGroup,
name: aliasTerms[0].name,
});
}
}
return termGroup;
}
// wp_insert_term
async insert(name, taxonomyName, args = {}) {
let { description = "", slug = "" } = args;
const { aliasOf = "", parentId = 0 } = args;
const queryUtil = this.components.get(query_util_1.QueryUtil);
const taxonomy = await this.taxonomyUtil.get(taxonomyName);
if (taxonomy.isDefault) {
throw new Error("Invalid Taxonomy");
}
name = common_1.formatting.unslash(name);
description = common_1.formatting.unslash(description);
slug = common_1.formatting.slug(slug.length > 0 ? slug : `${name}`);
if (!name || 0 >= name.length) {
throw new Error(`A name is required for this term.`);
}
if (parentId > 0 &&
(!(await this.termUtil.get(parentId)).props ||
true !== taxonomy.props?.hierarchical)) {
throw new Error("Invalid Parent Term");
}
const data = {
name,
taxonomy: taxonomyName,
description,
parent: parentId,
};
const dupTerms = (await queryUtil.terms((query) => {
query
.where("taxonomy", taxonomyName)
.where("name", name)
.where("parent", parentId);
})) ?? [];
/*
* The `name` match in `get_terms()` doesn't differentiate accented characters,
* so we do a stricter comparison here.
*/
for (const dupTerm of dupTerms) {
if (typeof name === "string" &&
dupTerm.name?.toLowerCase() === name.toLowerCase()) {
throw new Error(`A term with the name provided already exists in this taxonomy. - ${name}`);
}
}
data.term_group = await this.syncTermGroup(0, aliasOf, taxonomyName);
const term = await this.termUtil.get(0, taxonomy.name);
term.withProps({
parent: parentId,
});
data.slug = await this.termUtil.getUniqueSlug(slug, term);
const dataInsert = this.validator.execSafeAny(val.trx.termInsert, Object.entries(data)
.map(([key, value]) => ({
[key]: common_1.formatting.unslash(value),
}))
.reduce((obj, item) => ({ ...obj, ...item }), {}));
if (!dataInsert) {
throw new Error(`Invalid Data ${JSON.stringify(data)}`);
}
const trx = await this.database.transaction;
let termId = 0;
try {
await trx
.insert({
name: dataInsert.name,
slug: dataInsert.slug,
term_group: dataInsert.term_group,
})
.into(this.tables.get("terms"))
.then((v) => {
termId = v[0];
});
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to insert term ${e}`);
}
// Check if term taxonomy already exists
const termTaxonomies = await queryUtil.terms((query) => {
query.where("term_id", termId).where("taxonomy", taxonomyName);
});
if (termTaxonomies) {
return {
term_id: termId,
term_taxonomy_id: termTaxonomies[0].term_taxonomy_id,
};
}
let termTaxonomyId = 0;
try {
await trx
.table(this.tables.get("term_taxonomy"))
.insert({
term_id: termId,
taxonomy: dataInsert.taxonomy,
description: dataInsert.description,
parent: dataInsert.parent,
})
.then((v) => {
termTaxonomyId = v[0];
});
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to insert term taxonomy ${e}`);
}
/*
* Sanity check: if we just created a term with the same parent + taxonomy + slug but a higher term_id than
* an existing term, then we have unwittingly created a duplicate term. Delete the dupe, and use the term_id
* and term_taxonomy_id of the older term instead. Then return out of the function so that the "create" hooks
* are not fired.
*
* ok, but why are we doing this just for term?
*/
const sanityCheck = await queryUtil.terms((query) => {
query
.where("slug", slug)
.where("parent", parentId)
.where("taxonomy", taxonomyName)
.where("term_id", termId)
.builder.not.__ref(query)
.where("term_taxonomy_id", termTaxonomyId);
});
if (sanityCheck && sanityCheck[0].term_id) {
termId = sanityCheck[0].term_id;
termTaxonomyId = sanityCheck[0].term_taxonomy_id;
}
sanityCheck ? await trx.rollback() : await trx.commit();
return {
term_id: termId,
term_taxonomy_id: termTaxonomyId,
};
}
// wp_update_term
async update(termId, taxonomyName, args) {
const { aliasOf = "", parentId = 0, termGroup = 0 } = args;
let { description = "", slug = "", name } = args;
const queryUtil = this.components.get(query_util_1.QueryUtil);
const taxonomy = await this.taxonomyUtil.get(taxonomyName);
if (taxonomy.isDefault) {
throw new Error("Invalid Taxonomy");
}
const term = await this.termUtil.get(termId);
if (!term.props?.term_id) {
throw new Error(`Invalid Term - ${termId}`);
}
name = name && common_1.formatting.unslash(name.length > 0 ? name : term.props.name);
description = common_1.formatting.unslash(description);
slug = common_1.formatting.slug(slug.length > 0 ? slug : `${name}`);
if (!name || 0 >= name.length) {
throw new Error(`A name is required for this term.`);
}
if (parentId > 0 &&
(!(await this.termUtil.get(parentId)).props ||
true !== taxonomy.props?.hierarchical)) {
throw new Error("Invalid Parent Term");
}
const data = {
name,
taxonomy: taxonomyName,
description,
parent: parentId,
slug,
};
// Check for duplicate slug.
const dupTerms = await queryUtil.terms((query) => {
query
.where("slug", slug)
.where("taxonomy", taxonomyName)
.builder.not.__ref(query)
.where("term_id", termId);
});
if (dupTerms) {
throw new Error(`duplicate_term_slug - ${slug} is already in use by another term.`);
}
const termTaxonomy = await queryUtil.terms((query) => {
query.where("taxonomy", taxonomyName).where("term_id", termId);
});
if (!termTaxonomy) {
throw new Error(`Term Taxonomy not found: taxonomy - ${taxonomy} termId - ${termId}`);
}
data.term_taxonomy_id = termTaxonomy[0].term_taxonomy_id;
data.term_group = await this.syncTermGroup(termGroup, aliasOf, taxonomyName);
termId = await this.splitSharedTerm(termId, termTaxonomy[0].term_taxonomy_id);
data.term_id = termId;
const dataInsert = this.validator.execSafeAny(val.trx.termUpdate, Object.entries(data)
.map(([key, value]) => ({
[key]: common_1.formatting.unslash(value),
}))
.reduce((obj, item) => ({ ...obj, ...item }), {}));
if (!dataInsert) {
throw new Error(`Invalid Data ${JSON.stringify(data)}`);
}
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("terms"))
.where("term_id", dataInsert.term_id)
.update({
name: dataInsert.name,
slug: dataInsert.slug,
term_group: dataInsert.term_group,
});
}
catch (e) {
trx.rollback();
throw new Error(`Failed to update term ${e}`);
}
try {
await trx
.table(this.tables.get("term_taxonomy"))
.where("term_taxonomy_id", dataInsert.term_taxonomy_id)
.update({
term_id: dataInsert.term_id,
taxonomy: dataInsert.taxonomy,
description: dataInsert.description,
parent: dataInsert.parent,
});
}
catch (e) {
trx.rollback();
throw new Error(`Failed to update term taxonomy ${e}`);
}
await trx.commit();
}
// wp_delete_term
async remove(termId, taxonomyName, args) {
let { default: defaultTermId } = args ?? {};
const { forceDefault } = args ?? {};
const taxonomy = await this.taxonomyUtil.get(taxonomyName);
if (taxonomy.isDefault) {
throw new Error("Invalid Taxonomy");
}
const term = await this.termUtil.get(termId);
if (!term.props?.term_id) {
throw new Error(`Invalid Term - ${termId}`);
}
const termTaxonomyId = term.props.term_taxonomy_id;
const options = this.components.get(options_1.Options);
if (taxonomyName === "category") {
const defaultCategoryId = await options.get("default_category");
if (defaultCategoryId === termId) {
return false; // Don't delete the default category.
}
defaultTermId = defaultTermId ?? defaultCategoryId;
}
// Don't delete the default custom taxonomy term.
if (taxonomy.props?.default_term) {
const taxonomyDefaultTermId = await options.get(`default_term_${taxonomyName}`);
if (taxonomyDefaultTermId === termId) {
return false;
}
defaultTermId = taxonomyDefaultTermId ?? defaultTermId;
}
if (defaultTermId) {
const defaultTerm = await this.termUtil.get(defaultTermId, taxonomyName);
if (!defaultTerm.props) {
defaultTermId = undefined;
}
}
// Update children to point to new parent.
if (taxonomy.props?.hierarchical) {
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("term_taxonomy"))
.where("parent", term.props.term_id)
.where("taxonomy", taxonomyName)
.update({
parent: term.props.parent,
});
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to update term taxonomy ${e}`);
}
await trx.commit();
}
const queryUtil = this.components.get(query_util_1.QueryUtil);
const objectIds = ((await queryUtil.terms((query) => {
query.selectTermRelationships.where("terms_relationships.term_taxonomy_id", termTaxonomyId);
}, val.query.termRelationshipsResult)) ?? []).map((term) => term.object_id);
for (const objectId of objectIds) {
if (!defaultTermId) {
await this.removeObject(objectId, [termId], taxonomy);
continue;
}
const terms = (await queryUtil.terms((query) => {
query.withObjectIds([objectId]).where("taxonomy", taxonomyName);
})) ?? [];
if (1 >= terms.length && defaultTermId) {
// - object has only one term that's being deleted.
// - attach default term to the object
await this.syncObject(objectId, [defaultTermId], taxonomyName);
continue;
}
const termIds = terms
.filter((term) => term.term_id !== termId)
.map((term) => term.term_id);
if (defaultTermId && forceDefault) {
termIds.push(defaultTermId);
}
await this.syncObject(objectId, termIds, taxonomyName);
}
const metas = (await queryUtil.meta("term", (query) => {
query.withIds([termId]);
})) ?? [];
const metaTrx = this.components.get(meta_trx_1.MetaTrx);
for (const meta of metas) {
if (!meta.meta_key)
continue;
await metaTrx.remove("term", {
objectId: termId,
key: meta.meta_key,
});
}
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("term_taxonomy"))
.where("term_taxonomy_id", termTaxonomyId)
.del();
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to delete term taxonomy ${e}`);
}
await trx.commit();
// Delete the term if no taxonomies use it.
if (!(await queryUtil.terms((query) => {
query.selectTermTaxonomy.where("term_taxonomy_id", termId);
}))) {
const trx = await this.database.transaction;
try {
await trx
.table(this.tables.get("terms"))
.where("term_id", termId)
.del();
}
catch (e) {
await trx.rollback();
throw new Error(`Failed to delete term ${e}`);
}
await trx.commit();
}
return true;
}
};
exports.TermTrx = TermTrx;
exports.TermTrx = TermTrx = __decorate([
(0, component_1.transactions)(),
__metadata("design:paramtypes", [database_1.default,
logger_1.Logger,
components_1.Components,
taxonomy_util_1.TaxonomyUtil,
term_util_1.TermUtil,
post_util_1.PostUtil,
validator_1.Validator])
], TermTrx);