Appearance
WordPress Compatibility
Introduction
A site moves from WordPress to kitloom by pointing kitloom at its database. Nothing is converted: kitloom reads the tables, options and meta as WordPress and its plugins left them, and the site keeps its content, its addresses and its settings.
The move is one way. kitloom writes new arrays as JSON (see Data), so WordPress is not expected to read the database back.
What is picked up
WordPress itself
| What | Where WordPress keeps it | kitloom |
|---|---|---|
| Posts, pages, attachments, revisions | posts, postmeta | kitloom/wp-schema |
| Categories, tags, custom taxonomies | terms, term_taxonomy, term_relationships, termmeta | kitloom/wp-schema |
| Comments | comments, commentmeta | kitloom/wp-schema |
| Users and roles | users, usermeta ({prefix}capabilities), the {prefix}user_roles option | kitloom/wp-schema, kitloom/permissions |
| Addresses | permalink_structure, category_base, tag_base, show_on_front, page_on_front, page_for_posts | kitloom/site |
| Site settings | blogname, blogdescription, date_format, posts_per_page, sticky_posts… | kitloom/settings, kitloom/site |
| Page templates | _wp_page_template meta | kitloom/site |
| Menus | nav_menu terms, nav_menu_item posts with _menu_item_* meta, locations in theme_mods_{stylesheet} | kitloom/navigation |
| Widgets | sidebars_widgets, widget_{type} options | kitloom/site |
| Media | attachment posts, _wp_attached_file, _wp_attachment_metadata, _thumbnail_id; files under /wp-content/uploads/Y/m/ | kitloom/media |
Plugins
| Plugin | What is kept | kitloom |
|---|---|---|
| Rank Math SEO | rank-math-options-titles, -general, -sitemap, -instant-indexing options; rank_math_title, rank_math_description, rank_math_robots, rank_math_canonical_url, rank_math_primary_category… meta | kitloom/seo |
| Rank Math Redirections, 404 Monitor | rank_math_redirections, rank_math_redirections_cache, rank_math_404_logs tables; their keys in rank-math-options-general | kitloom/redirects |
| Rank Math Link Counter | rank_math_internal_links, rank_math_internal_meta tables | kitloom/internal-links |
| ACF, Secure Custom Fields | field groups and fields as acf-field-group / acf-field posts; values under the field's meta key with the _{name} reference; options as options_{name} | kitloom/custom-fields |
| ACF post types and taxonomies | acf-post-type, acf-taxonomy posts | kitloom/post-types |
| Contact Form 7 | wpcf7_contact_form posts and their _mail, _mail_2, _additional_settings meta; [contact-form-7] shortcodes | kitloom/forms |
| WooCommerce | product posts, product_cat, product_tag, product_type, product_visibility; _price, _sku, _stock… meta; orders in the HPOS tables (wc_orders, wc_orders_meta, wc_order_addresses, woocommerce_order_items…); woocommerce_* options | kitloom/shop |
| Slide Anything | sa_slider posts with sa_* meta; [slide-anything] shortcodes | kitloom/slider |
Content can also come in as a file: kitloom/import-export reads and writes WXR, the format of WordPress's Tools → Import / Export.
A module for a plugin's data
When a module replaces a WordPress plugin, the plugin's data is the module's data model. The site moves over and the module works with what is there.
1. Find out how the plugin stores things
Install the plugin on a WordPress site, use every feature, and look at what it wrote: its tables (SHOW CREATE TABLE), its options (SELECT * FROM wp_options WHERE option_name LIKE 'plugin%'), the meta keys of the records it touched. Note the formats — serialized arrays, on/off or 1/0 flags, IDs as strings.
Save samples as fixtures in the module's tests/Fixtures/ — rows exactly as the plugin wrote them. kitloom/custom-fields keeps a snapshot of every field type as Secure Custom Fields stores it.
2. Keep its tables and keys
php
// The plugin's table, created only when the site never had the plugin.
if (! Schema::hasTable('rank_math_redirections')) {
Schema::create('rank_math_redirections', function (Blueprint $table): void {
$table->id();
$table->text('sources');
$table->text('url_to');
$table->unsignedSmallInteger('header_code');
// …the rest as the plugin creates them
});
}Use the plugin's option names and meta keys as they are. Name them once, in a class of the module — RankMathKeys, ContactForm7Dictionary — so the rest of the code speaks in plain names.
3. Read both formats, write JSON
php
use Kitloom\WpSchema\Support\StoredArray;
$sources = StoredArray::toArray($row->sources); // serialized by the plugin or JSON by kitloom
$row->sources = StoredArray::encode($sources); // JSON from now onOptions that are one array with many keys — Rank Math keeps whole screens in one option — are read and written key by key: change the keys your module owns and leave the others as they are.
4. Test against what the plugin wrote
php
#[Test]
public function sources_are_read_from_what_rank_math_saved(): void
{
$saved = 'a:1:{i:0;a:3:{s:6:"ignore";s:4:"case";s:7:"pattern";s:8:"Old-Page";s:10:"comparison";s:5:"exact";}}';
$this->assertEquals([new Source('Old-Page', Comparison::Exact, ignoreCase: true)], Sources::decode($saved));
}Run the module on a copy of a real site's database before calling it done: the plugin's data has cases no fixture thought of.
What kitloom does not do
- Run WordPress plugins or themes. PHP code written for WordPress does not run; a plugin's data is supported when a kitloom module for it exists.
- Keep the database readable by WordPress. New arrays are JSON; WordPress would not understand them. Moving back is not supported.
- Import through the admin. Data moves with the database — or as a WXR file with
kitloom/import-export.