158 lines
4.8 KiB
PHP
158 lines
4.8 KiB
PHP
<?php
|
|
/**
|
|
* Database schema creation and versioned migrations.
|
|
*
|
|
* @package MediaRightsAudit\Core
|
|
*/
|
|
|
|
namespace MediaRightsAudit\Core;
|
|
|
|
/**
|
|
* Manages all custom table creation and schema migrations.
|
|
*
|
|
* Migration methods are idempotent: they rely on dbDelta's ALTER TABLE
|
|
* diffing and can be run multiple times without side effects.
|
|
*/
|
|
class Database {
|
|
|
|
/**
|
|
* Creates all tables. Called on plugin activation.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function create_tables(): void {
|
|
self::migration_100();
|
|
self::migration_101();
|
|
}
|
|
|
|
/**
|
|
* Applies any pending migrations based on the currently installed schema version.
|
|
*
|
|
* Called on admin_init by Plugin::check_db_version().
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function run_migrations(): void {
|
|
$raw = get_option( 'robotstxt_mediaaudit_db_version', '0.0.0' );
|
|
$current = is_string( $raw ) ? $raw : '0.0.0';
|
|
|
|
if ( version_compare( $current, '1.0.0', '<' ) ) {
|
|
self::migration_100();
|
|
}
|
|
|
|
if ( version_compare( $current, '1.0.1', '<' ) ) {
|
|
self::migration_101();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Drops all plugin tables. Used by uninstall.php.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function drop_tables(): void {
|
|
global $wpdb;
|
|
$wpdb->query( "DROP TABLE IF EXISTS `{$wpdb->prefix}mra_external_results`" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
|
|
$wpdb->query( "DROP TABLE IF EXISTS `{$wpdb->prefix}mra_media_usage`" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
|
|
$wpdb->query( "DROP TABLE IF EXISTS `{$wpdb->prefix}mra_media_index`" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
|
|
}
|
|
|
|
/**
|
|
* Truncates all plugin tables, removing all data while preserving the table structure.
|
|
*
|
|
* Used by the Tools page "Reset all data" operation.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function truncate_all(): void {
|
|
global $wpdb;
|
|
|
|
// phpcs:disable WordPress.DB.DirectDatabaseQuery
|
|
$wpdb->query( "TRUNCATE TABLE `{$wpdb->prefix}mra_external_results`" );
|
|
$wpdb->query( "TRUNCATE TABLE `{$wpdb->prefix}mra_media_usage`" );
|
|
$wpdb->query( "TRUNCATE TABLE `{$wpdb->prefix}mra_media_index`" );
|
|
// phpcs:enable WordPress.DB.DirectDatabaseQuery
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Migrations
|
|
// -------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Migration 1.0.0 — creates the initial three tables.
|
|
*
|
|
* @return void
|
|
*/
|
|
private static function migration_100(): void {
|
|
global $wpdb;
|
|
|
|
$charset_collate = $wpdb->get_charset_collate();
|
|
|
|
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
|
|
|
dbDelta(
|
|
"CREATE TABLE {$wpdb->prefix}mra_media_index (
|
|
attachment_id bigint(20) unsigned NOT NULL,
|
|
file_url text NOT NULL,
|
|
file_name varchar(255) NOT NULL DEFAULT '',
|
|
mime_type varchar(100) NOT NULL DEFAULT '',
|
|
file_size bigint(20) unsigned NOT NULL DEFAULT 0,
|
|
internal_scanned_at datetime DEFAULT NULL,
|
|
external_status enum('pending','queued','scanned','matches','error') NOT NULL DEFAULT 'pending',
|
|
external_scanned_at datetime DEFAULT NULL,
|
|
created_at datetime NOT NULL,
|
|
PRIMARY KEY (attachment_id),
|
|
KEY external_status (external_status)
|
|
) {$charset_collate};"
|
|
);
|
|
|
|
dbDelta(
|
|
"CREATE TABLE {$wpdb->prefix}mra_media_usage (
|
|
usage_id bigint(20) unsigned NOT NULL auto_increment,
|
|
attachment_id bigint(20) unsigned NOT NULL,
|
|
post_id bigint(20) unsigned NOT NULL,
|
|
post_type varchar(20) NOT NULL DEFAULT '',
|
|
context enum('featured','content','meta') NOT NULL DEFAULT 'featured',
|
|
meta_key varchar(255) DEFAULT NULL,
|
|
created_at datetime NOT NULL,
|
|
PRIMARY KEY (usage_id),
|
|
KEY attachment_id (attachment_id),
|
|
KEY post_id (post_id)
|
|
) {$charset_collate};"
|
|
);
|
|
|
|
dbDelta(
|
|
"CREATE TABLE {$wpdb->prefix}mra_external_results (
|
|
result_id bigint(20) unsigned NOT NULL auto_increment,
|
|
attachment_id bigint(20) unsigned NOT NULL,
|
|
provider enum('google_vision','tineye') NOT NULL,
|
|
raw_response json DEFAULT NULL,
|
|
match_count int(10) unsigned NOT NULL DEFAULT 0,
|
|
top_domains json DEFAULT NULL,
|
|
created_at datetime NOT NULL,
|
|
PRIMARY KEY (result_id),
|
|
UNIQUE KEY attachment_provider (attachment_id,provider)
|
|
) {$charset_collate};"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Migration 1.0.1 — adds 'queued' to the external_status ENUM.
|
|
*
|
|
* Uses ALTER TABLE directly because dbDelta cannot modify ENUM column definitions.
|
|
* Safe to re-run: MariaDB/MySQL treats an identical MODIFY as a no-op.
|
|
*
|
|
* @return void
|
|
*/
|
|
private static function migration_101(): void {
|
|
global $wpdb;
|
|
|
|
// phpcs:disable WordPress.DB.DirectDatabaseQuery,WordPress.DB.DirectDatabaseQuery.SchemaChange
|
|
$wpdb->query(
|
|
"ALTER TABLE `{$wpdb->prefix}mra_media_index`
|
|
MODIFY COLUMN external_status
|
|
enum('pending','queued','scanned','matches','error') NOT NULL DEFAULT 'pending'"
|
|
);
|
|
// phpcs:enable WordPress.DB.DirectDatabaseQuery,WordPress.DB.DirectDatabaseQuery.SchemaChange
|
|
}
|
|
}
|