get_charset_collate(); $facets = $wpdb->prefix . 'facetcore_facets'; $values = $wpdb->prefix . 'facetcore_values'; $productValues = $wpdb->prefix . 'facetcore_product_values'; dbDelta("CREATE TABLE {$facets} ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, name varchar(200) NOT NULL, slug varchar(190) NOT NULL, priority int(11) NOT NULL DEFAULT 0, enabled tinyint(1) NOT NULL DEFAULT 1, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY slug (slug), KEY enabled_priority (enabled,priority,id) ) {$charset};"); dbDelta("CREATE TABLE {$values} ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, facet_id bigint(20) unsigned NOT NULL, label varchar(200) NOT NULL, sort_order int(11) NOT NULL DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY facet_label (facet_id,label), KEY facet_sort (facet_id,sort_order,id) ) {$charset};"); /* * The two composite directions are deliberate: * - facet/value/product: reduce the catalog for a selected value. * - product/facet/value: discover the remaining facets/values for candidates. */ dbDelta("CREATE TABLE {$productValues} ( product_id bigint(20) unsigned NOT NULL, facet_id bigint(20) unsigned NOT NULL, value_id bigint(20) unsigned NOT NULL, PRIMARY KEY (product_id,facet_id,value_id), KEY facet_value_product (facet_id,value_id,product_id), KEY facet_product_value (facet_id,product_id,value_id), KEY value_product (value_id,product_id) ) {$charset};"); update_option('facetcore_schema_version', self::SCHEMA_VERSION, false); if (get_option('facetcore_max_facets', null) === null) { add_option('facetcore_max_facets', 10, '', false); } } public static function uninstall(): void { global $wpdb; // 1. Drop FacetCore custom database tables $tables = [ $wpdb->prefix . 'facetcore_product_values', $wpdb->prefix . 'facetcore_values', $wpdb->prefix . 'facetcore_facets', ]; foreach ($tables as $table) { // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $table comes from the fixed list of the plugin's own prefixed tables above. $wpdb->query("DROP TABLE IF EXISTS `{$table}`"); } // 2. Delete all FacetCore options and transients $wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE `option_name` LIKE 'facetcore\_%' OR `option_name` LIKE '\_transient\_facetcore\_%' OR `option_name` LIKE '\_transient\_timeout\_facetcore\_%'" ); // 3. Delete all Finder configuration posts and associated postmeta $postIds = $wpdb->get_col($wpdb->prepare( "SELECT ID FROM `{$wpdb->posts}` WHERE `post_type` = %s", TableConfiguration::TYPE )); if (!empty($postIds)) { foreach ($postIds as $postId) { wp_delete_post((int) $postId, true); } } // Clean up any remaining or orphaned FacetCore postmeta $wpdb->query("DELETE FROM `{$wpdb->postmeta}` WHERE `meta_key` LIKE '\_facetcore\_%'"); } }