@rnaga/wp-node
Version:
👉 **[View Full Documentation at rnaga.github.io/wp-node →](https://rnaga.github.io/wp-node/)**
273 lines (272 loc) • 11.3 kB
JavaScript
;
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 __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostUtil = void 0;
const config_1 = require("../../config");
const component_1 = require("../../decorators/component");
const components_1 = require("../components");
const current_1 = require("../current");
const post_1 = require("../post");
const query_util_1 = require("./query.util");
let PostUtil = class PostUtil {
config;
components;
constructor(config, components) {
this.config = config;
this.components = components;
}
toPost(post) {
return this.components.get(post_1.Post, [post.ID, post]);
}
toPosts(posts) {
return posts.map((post) => this.toPost(post));
}
async get(id) {
return await this.components.asyncGet(post_1.Post, [id]);
}
async getBySlug(slug) {
const queryUtil = this.components.get(query_util_1.QueryUtil);
const posts = await queryUtil.posts((query) => query.where("post_name", slug).builder.limit(1));
const postId = posts?.[0]?.ID;
return postId ? await this.get(postId) : undefined;
}
// is_post_publicly_viewable
async isPubliclyViewable(postIdOrPost) {
const post = typeof postIdOrPost == "number"
? await this.get(postIdOrPost)
: postIdOrPost;
if (!post.props?.ID || 0 >= post.props.ID) {
return false;
}
return (this.isTypeViewable(post.props.post_type) &&
this.isStatusViewable(post.props.post_status));
}
getViewableTypes() {
return Object.keys(this.config.config.posts.types).filter((type) => this.isTypeViewable(type));
}
// is_post_type_viewable
isTypeViewable(typeObjectOrString) {
const typeObject = typeof typeObjectOrString === "string"
? this.getTypeObject(typeObjectOrString)
: typeObjectOrString;
if (!typeObject) {
return false;
}
return (typeObject.publiclyQueryable || (typeObject._builtin && typeObject.public));
}
// https://github.com/WordPress/WordPress/blob/master/wp-includes/post.php
// is_post_status_viewable
isStatusViewable(statusObjectOrString) {
const statusObject = typeof statusObjectOrString === "string"
? this.getStatusObject(statusObjectOrString)
: statusObjectOrString;
if (!statusObject ||
true == statusObject.internal ||
true == statusObject.protected) {
return false;
}
return true == statusObject._builtin && true == statusObject.public;
}
// https://github.com/WordPress/WordPress/blob/master/wp-includes/post.php
// get_post_status_object
getStatusObject(status) {
return !status || !this.config.config.posts.statuses[status]
? undefined
: this.config.config.posts.statuses[status];
}
// https://github.com/WordPress/WordPress/blob/master/wp-includes/post.php
// get_post_status
async getStatus(post, parent) {
if (!post?.props) {
const current = this.components.get(current_1.Current);
if (!current.post) {
return undefined;
}
post = current.post;
}
const postParent = parent ??
(await this.components.asyncGet(post_1.Post, [post.props?.post_parent]));
let postStatus = post.props?.post_status;
if ("attachment" === post.props?.post_type && "inherit" === postStatus) {
if (0 === post.props.post_parent ||
!postParent.props ||
post.props.ID === post.props.post_parent) {
// Unattached attachments with inherit status are assumed to be published.
postStatus = "publish";
}
else if ("trash" === (await this.getStatus(postParent))) {
// Get parent status prior to trashing.
postStatus = await postParent.meta.get("_wp_trash_meta_status");
if (!postStatus) {
// Assume publish as above.
postStatus = "publish";
}
}
else {
postStatus = await this.getStatus(postParent);
}
}
else if ("attachment" === post.props?.post_type &&
!["private", "trash", "auto-draft"].includes(post.props?.post_status ?? "")) {
/*
* Ensure uninherited attachments have a permitted status either 'private', 'trash', 'auto-draft'.
* This is to match the logic in wp_insert_post().
*
* Note: 'inherit' is excluded from this check as it is resolved to the parent post's
* status in the logic block above.
*/
postStatus = "publish";
}
return postStatus;
}
// get_attached_file
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getAttachedFile(postId, unfiltered = false) {
const post = await this.get(postId);
if (!post.props) {
return undefined;
}
let file = await post.meta.get("_wp_attached_file");
if (!file) {
return undefined;
}
// If the file is relative, prepend upload dir.
if (file && !file.startsWith("/") && !/^.:\\/.test(file)) {
file = `${this.config.config.staticAssetsPath}/${file}`;
}
return file;
}
// wp_get_attachment_metadata
async getAttachmentMetadata(postId) {
const post = await this.get(postId);
if (!post.props) {
return undefined;
}
const meta = await post.meta.get("_wp_attachment_metadata");
if (!meta) {
return undefined;
}
return meta;
}
getTypeObject(name) {
const type = this.config.config.posts.types[name];
if (!type) {
return undefined;
}
type.capabilities = {
...(type.capabilities ?? {}),
...this.getCapabilities(type),
};
return type;
}
// get_post_type_capabilities
getCapabilities(args) {
const capabilityType = !Array.isArray(args?.capabilityType)
? [args.capabilityType, args.capabilityType + "s"]
: args.capabilityType;
// Singular base for meta capabilities, plural base for primitive capabilities.
const [singular_base, plural_base] = capabilityType;
let defaultCapabilities = {
// Meta capabilities.
edit_post: "edit_" + singular_base,
read_post: "read_" + singular_base,
delete_post: "delete_" + singular_base,
// Primitive capabilities used outside of map_meta_cap():
edit_posts: "edit_" + plural_base,
edit_others_posts: "edit_others_" + plural_base,
delete_posts: "delete_" + plural_base,
publish_posts: "publish_" + plural_base,
read_private_posts: "read_private_" + plural_base,
};
// Primitive capabilities used within map_meta_cap():
if (args.mapMetaCap) {
defaultCapabilities = {
...defaultCapabilities,
...{
read: "read",
delete_private_posts: "delete_private_" + plural_base,
delete_published_posts: "delete_published_" + plural_base,
delete_others_posts: "delete_others_" + plural_base,
edit_private_posts: "edit_private_" + plural_base,
edit_published_posts: "edit_published_" + plural_base,
},
};
}
const capabilities = {
...defaultCapabilities,
...(args.capabilities ?? {}),
};
// Post creation capability simply maps to edit_posts by default:
if (!capabilities || !capabilities["create_posts"]) {
capabilities["create_posts"] = capabilities["edit_posts"];
}
return capabilities;
}
// wp_unique_post_slug
async getUniqueSlug(slug, post, maxSuffix = 10) {
const queryUtil = this.components.get(query_util_1.QueryUtil);
if (typeof post === "number") {
post = await this.get(post);
}
slug = slug?.trim();
const postId = post.props?.ID ?? 0;
const postParent = post.props?.post_parent ?? 0;
const postType = post.props?.post_type ?? "";
const postStatus = post.props?.post_status ?? "";
const postTypeObject = this.getTypeObject(postType);
if (["draft", "pending", "auto-draft"].includes(postStatus) ||
("inherit" === postStatus && "revision" === postType) ||
"user_request" === postType ||
("nav_menu_item" == postType && postTypeObject?.hierarchical)) {
return slug ?? post.props?.post_name;
}
slug = this.truncateSlug(slug);
if (!slug || 0 >= slug.length) {
return slug;
}
for (let suffix = 0; suffix < maxSuffix; suffix++) {
const newSlug = 0 >= suffix ? slug : `${slug}-${suffix + 1}`;
const posts = await queryUtil.posts((query) => {
query
.where("post_name", newSlug)
.builder.not.__ref(query)
.where("ID", postId);
if (postTypeObject?.hierarchical) {
query
.whereIn("post_type", ["attachment", postType])
.where("post_parent", postParent);
}
});
if (!posts) {
return newSlug;
}
}
return `${slug}-${Math.floor(Math.random() * (maxSuffix + 999990010 - maxSuffix + 1) + maxSuffix + 1)}`;
}
// _truncate_post_slug
truncateSlug(slug, length = 200) {
if (slug.length > length) {
const decodedSlug = decodeURIComponent(slug);
if (decodedSlug === slug) {
slug = slug.substring(0, length);
}
else {
slug = encodeURIComponent(decodedSlug).slice(0, length);
}
}
return slug.replace(/-+$/, ""); // Remove trailing hyphens
}
};
exports.PostUtil = PostUtil;
exports.PostUtil = PostUtil = __decorate([
(0, component_1.component)(),
__metadata("design:paramtypes", [config_1.Config, components_1.Components])
], PostUtil);