UNPKG

@rnaga/wp-node

Version:

👉 **[View Full Documentation at rnaga.github.io/wp-node →](https://rnaga.github.io/wp-node/)**

531 lines (530 loc) • 22 kB
"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.SeederTrx = 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 logger_1 = require("../core/logger"); const options_1 = require("../core/options"); const date_time_util_1 = require("../core/utils/date-time.util"); const query_util_1 = require("../core/utils/query.util"); const roles_util_1 = require("../core/utils/roles.util"); const user_util_1 = require("../core/utils/user.util"); const database_1 = __importDefault(require("../database")); const component_1 = require("../decorators/component"); const defaults = __importStar(require("../defaults")); 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 post_trx_1 = require("./post.trx"); const site_trx_1 = require("./site.trx"); const term_trx_1 = require("./term.trx"); const trx_1 = require("./trx"); let SeederTrx = class SeederTrx extends trx_1.Trx { components; logger; database; config; optionsTrx; metaTrx; queryUtil; siteTrx; postTrx; termTrx; constructor(components, logger, database, config, optionsTrx, metaTrx, queryUtil, siteTrx, postTrx, termTrx) { super(components); this.components = components; this.logger = logger; this.database = database; this.config = config; this.optionsTrx = optionsTrx; this.metaTrx = metaTrx; this.queryUtil = queryUtil; this.siteTrx = siteTrx; this.postTrx = postTrx; this.termTrx = termTrx; } async currentDbVersion() { const optionsComponent = this.components.get(options_1.Options); return await optionsComponent.get("db_version"); } // populate_options async populateOptions(options) { const siteUrl = options.siteUrl; if (!siteUrl) { throw new Error("siteurl not found"); } let seeds = defaults.options(this.config, { siteUrl, }); const currentDbVersion = parseInt((await this.currentDbVersion()) ?? "0"); const optionsComponent = this.components.get(options_1.Options); const dbVersion = this.config.config.constants.WP_DB_VERSION; // 3.3.0 if (!this.config.isMultiSite()) { seeds["initial_db_version"] = currentDbVersion > 0 && currentDbVersion < dbVersion ? currentDbVersion : dbVersion; } // 3.0.0 multisite. if (this.config.isMultiSite()) { seeds["permalink_structure"] = "/%year%/%monthnum%/%day%/%postname%/"; } if (options) { seeds = { ...seeds, ...options }; } // Set autoload to no for these options. const fatOptions = [ "moderation_keys", "recently_edited", "disallowed_keys", "uninstall_plugins", "auto_plugin_theme_update_emails", ]; for (const [key, value] of Object.entries(seeds)) { await this.optionsTrx.insert(key, value, { seriazlie: Array.isArray(value), upsert: false, autoload: fatOptions.includes(key) ? "no" : "yes", force: true, }); } const home = await optionsComponent.get("home"); if (!home) { await this.optionsTrx.insert("home", siteUrl); } } // populate_roles async populateRoles() { const roleUtils = this.components.get(roles_util_1.RolesUtil); const seed = roleUtils.reformatInDB({ administrator: defaults.roles.administrator, editor: defaults.roles.editor, author: defaults.roles.author, contributor: defaults.roles.contributor, subscriber: defaults.roles.subscriber, }); const key = `${this.tables.prefix}user_roles`; return await this.optionsTrx.insert(key, seed, { seriazlie: true, autoload: "yes", force: true, }); } async validMultisite() { if (!this.config.isMultiSite()) { return false; } const site = await this.queryUtil.sites((query) => { query.where("id", 1); }); if (!site) { return false; } const blog = await this.queryUtil.blogs((query) => { query.where("blog_id", 1); }); return blog ? true : false; } // populate_network_meta async populateSitemeta(siteId, meta = { admin_email: "", subdomain_install: true }) { const userUtil = this.components.get(user_util_1.UserUtil); const current = this.components.get(current_1.Current); const optionsComponent = this.components.get(options_1.Options); const subdomainInstall = meta["subdomain_install"]; const validMultisite = await this.validMultisite(); let email = meta["admin_email"]; // If a user with the provided email does not exist, default to the current user as the new network admin. let siteUser = current.user; if (0 < email.length) { const user = await this.queryUtil.users((query) => { query.where("user_email", email).builder.first(); }, val.database.wpUsers); if (user) siteUser = await userUtil.get(user.ID); } if (!siteUser?.props) { this.logger.warn("User not found", { siteUser }); return; } const siteUserLogin = siteUser.props.user_login; const siteUserId = siteUser.props.ID; if (0 >= email.length) { if (siteUser.props.user_email && 0 < siteUser.props.user_email.length) { email = siteUser.props.user_email; } else { throw new Error(`Admin email is not specified`); } } const template = await optionsComponent.get("template"); const stylesheet = await optionsComponent.get("stylesheet"); let allowedThemes = stylesheet ?? ""; if (template && template !== stylesheet) { allowedThemes = template; } const defaultTheme = this.config.config.constants.WP_DEFAULT_THEME; if (defaultTheme !== stylesheet && defaultTheme !== template) { allowedThemes = defaultTheme; } const siteAdmins = new Set(); if (!validMultisite) { siteAdmins.add(siteUserLogin); ((await this.queryUtil.users((query) => { query.withRoles(["administrator"]); })) ?? []).forEach((user) => { siteAdmins.add(user.user_login); }); } else { const result = await optionsComponent.get("site_admins", { siteId, }); if (Array.isArray(result)) { result.forEach((email) => siteAdmins.add(email)); } } const uploadFiletypes = [ ...this.config.config.extensions.misc, ...this.config.config.extensions.audio, ...this.config.config.extensions.video, ]; const siteUrl = (await optionsComponent.get("siteurl")) ?? ""; let sitemeta = { site_name: "My Network", admin_email: email, // Make sure to define 'email' before using it admin_user_id: siteUserId, // Make sure to define 'site_user' before using it registration: "none", upload_filetypes: uploadFiletypes.join(" "), // Make sure to define 'upload_filetypes' before using it blog_upload_space: 100, fileupload_maxk: 1500, site_admins: Array.from(siteAdmins), // Make sure to define 'site_admins' before using it allowedthemes: { [allowedThemes]: true }, // Make sure to define 'allowed_themes' before using it illegal_names: [ "www", "web", "root", "admin", "main", "invite", "administrator", "files", ], wpmu_upgrade_site: this.config.config.constants.WP_DB_VERSION, // Make sure to define 'wp_db_version' before using it welcome_email: defaults.seeder.sitemeta.emailSiteWelcome, // Make sure to define 'welcome_email' before using it first_post: `Welcome to %s. This is your first post. Edit or delete it, then start writing!`, // Make sure to define 'site_link' before using it // @todo - Network admins should have a method of editing the network siteurl (used for cookie hash). siteurl: `${siteUrl}/`, add_new_users: "0", upload_space_check_disabled: validMultisite ? await optionsComponent.get("upload_space_check_disabled", { siteId }) : "1", subdomain_install: subdomainInstall, // Make sure to define 'subdomain_install' before using it ms_files_rewriting: validMultisite ? await optionsComponent.get("ms_files_rewriting", { siteId }) : "0", user_count: await optionsComponent.get("user_count", { siteId }), initial_db_version: await optionsComponent.get("initial_db_version"), active_sitewide_plugins: [], WPLANG: this.config.config.constants.WPLANG, }; if (!subdomainInstall) { sitemeta["illegal_names"].push("blog"); } sitemeta = { ...sitemeta, ...meta }; await this.metaTrx.bulkUpsertObject("site", siteId, sitemeta); } // populate_network async populateSite(input, options) { let { siteId = undefined } = input; const { domain = "", email = "", siteName = "", path = "/" } = input; const { subdomainInstall } = options ?? {}; const errors = []; if (0 >= domain.length) { errors.push("You must provide a domain name."); } if (0 >= siteName.length) { errors.push("You must provide a name for your network of sites."); } // Check for network collision. if (siteId && (await this.queryUtil.sites((query) => { query.where("id", siteId); }))) { errors.push(`The network already exists. - ${siteId}`); } if (!zod_1.z.email().safeParse(email).success) { errors.push(`You must provide a valid email address. - ${email}`); } if (0 < errors.length) { throw new Error(errors.join("\n")); } siteId = await this.siteTrx.insert({ domain, path, id: siteId, }); if (!siteId) { throw new Error(`Failed to insert site - ${domain}`); } await this.populateSitemeta(siteId, { admin_email: email, site_name: siteName, subdomain_install: subdomainInstall ?? false, }); /* * When upgrading from single to multisite, assume the current site will * become the main site of the network. When using populate_network() * to create another network in an existing multisite environment, skip * these steps since the main site of the new network has not yet been * created. */ if (await this.validMultisite()) { return true; } // Create a primary blog (blogId = 1) const trx = await this.database.transaction; //let blogId = 0; try { await trx .insert({ site_id: siteId, blog_id: 1, domain, path, registered: common_1.formatting.dateMySQL(), }) .into(this.tables.get("blogs")); } catch (e) { await trx.rollback(); throw new Error(`Failed to create blog - ${e}`); } await trx.commit(); const result = await this.queryUtil.meta("site", (query) => { query.withKeys(["admin_user_id"]).withIds([siteId], { joinPrimary: false, }); }); if (!result) { throw new Error(`site user not found - ${siteId}`); } const siteUserId = common_1.formatting.primitive(result[0].meta_value); const current = this.components.get(current_1.Current); await this.metaTrx.upsert("user", siteUserId, "source_domain", domain); await this.metaTrx.upsert("user", siteUserId, "primary_blog", current.site?.props.blog.blog_id); return subdomainInstall; } // wp_install_defaults async populateContent(userId) { const optionsComponent = this.components.get(options_1.Options); const categoryName = "Uncategorized"; const categorySlug = common_1.formatting.slug("Uncategorized"); let categoryTerm; try { categoryTerm = await this.termTrx.insert(categoryName, "category", { slug: categorySlug, }); } catch (e) { this.logger.info(`${e}`, { "termTrx.tables.index": this.termTrx.tables.index, }); const categoryTerms = await this.queryUtil.terms((query) => { query.where("taxonomy", "category").where("terms.name", categoryName); }); // This never happens if (!categoryTerms) { throw new Error(`categoryTerm not found - ${categoryName}`); } categoryTerm = categoryTerms[0]; } const homeUrl = await optionsComponent.get("home"); const validMultisite = await this.validMultisite(); const dateTimeUtil = this.components.get(date_time_util_1.DateTimeUtil); const dateTime = dateTimeUtil.get(); const postId = await this.postTrx.upsert({ post_author: userId, post_content: defaults.seeder.content.firstPost, post_title: `Hello world!`, post_name: common_1.formatting.slug("hello-world"), post_date: dateTime.mySQLDatetime, post_date_gmt: dateTime.mySQLGMTDatetime, guid: `${homeUrl}/?p=1`, comment_count: 1, post_status: "publish", }); if (validMultisite) { await this.postTrx.updateCount(); } await this.termTrx.syncObject(postId, [categoryTerm.term_taxonomy_id], "category"); // Default comment. const commentTrx = this.components.get(comment_trx_1.CommentTrx); await commentTrx.upsert({ comment_post_ID: postId, comment_author: "A WordPress Commenter", comment_author_email: "wapuu@wordpress.example", comment_author_url: "https://wordpress.org/", comment_date: dateTime.mySQLDatetime, comment_date_gmt: dateTime.mySQLGMTDatetime, comment_content: defaults.seeder.content.commentContent, comment_type: "comment", }); // First page. await this.postTrx.upsert({ post_author: userId, post_content: defaults.seeder.content.firstPage, comment_status: "closed", post_title: "Sample Page", post_name: "sample-page", post_date: dateTime.mySQLDatetime, post_date_gmt: dateTime.mySQLGMTDatetime, guid: `${homeUrl}/?page_id=2`, post_type: "page", post_status: "publish", meta_input: { _wp_page_template: "default", }, }); let privacyPolicyContent = undefined; if (validMultisite) { const current = this.components.get(current_1.Current); const siteId = current.site?.props.site.id ?? 1; privacyPolicyContent = await optionsComponent.get("default_privacy_policy_content", { siteId, }); } else { privacyPolicyContent = defaults.seeder.content.privacyPage; } if (privacyPolicyContent) { const privacyPageId = await this.postTrx.upsert({ post_author: userId, post_content: privacyPolicyContent, comment_status: "closed", post_title: "Privacy Policy", post_name: "privacy-policy", guid: `${homeUrl}/?page_id=3`, meta_input: { _wp_page_template: "default", }, }); await this.optionsTrx.insert("wp_page_for_privacy_policy", privacyPageId); } // Set up default widgets for default theme. await this.optionsTrx.insert("widget_block", defaults.seeder.content.widgetData, { seriazlie: true, }); await this.optionsTrx.insert("sidebars_widgets", defaults.seeder.content.sidebarsWidgets, { seriazlie: true, }); const userUtil = this.components.get(user_util_1.UserUtil); const user = await userUtil.get(userId); const role = await user.role(); if (!validMultisite) { await this.metaTrx.upsert("user", userId, "show_welcome_panel", 1); } else if (!role.isSuperAdmin() && (await this.queryUtil.meta("user", (query) => { query .withIds([userId], { joinPrimary: false }) .withKeys(["show_welcome_panel"]); }))) { await this.metaTrx.upsert("user", userId, "show_welcome_panel", 2); } if (validMultisite) { if (!user.props) { throw new Error(`User not found - ${userId}`); } const userEmail = user.props.user_email; await this.optionsTrx.insert("admin_email", userEmail); const metaToDelete = await this.queryUtil.meta("user", (query) => { query.builder.not .__ref(query) .withIds([userId]) .withKeys([`${this.tables.prefix}capabilities`]); }); if (metaToDelete) { for (const meta of metaToDelete) { await this.metaTrx.remove("user", { objectId: meta.user_id, key: `${this.tables.prefix}capabilities`, }); } } /* * Delete any caps that snuck into the previously active blog. (Hardcoded to blog 1 for now.) * TODO: Get previous_blog_id. */ if (!role.isSuperAdmin() && 1 != user.props.ID) { await this.metaTrx.remove("user", { objectId: user.props.ID, key: `${this.config.config.tablePrefix}1_capabilities`, }); } } } }; exports.SeederTrx = SeederTrx; exports.SeederTrx = SeederTrx = __decorate([ (0, component_1.transactions)(), __metadata("design:paramtypes", [components_1.Components, logger_1.Logger, database_1.default, config_1.Config, options_trx_1.OptionsTrx, meta_trx_1.MetaTrx, query_util_1.QueryUtil, site_trx_1.SiteTrx, post_trx_1.PostTrx, term_trx_1.TermTrx]) ], SeederTrx);