prefix . 'agolegal_rat'; } public static function create_table(): void { global $wpdb; $table = self::table(); $table = self::table(); $charset = $wpdb->get_charset_collate(); $sql = "CREATE TABLE {$table} ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT '', purpose text DEFAULT '', legal_basis varchar(120) DEFAULT '', data_categories text DEFAULT '', data_subjects varchar(255) DEFAULT '', recipients text DEFAULT '', international_transfer tinyint(1) DEFAULT 0, transfer_safeguards text DEFAULT '', retention varchar(120) DEFAULT '', security_measures text DEFAULT '', created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) {$charset};"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); update_option( 'agolegal_rat_db_version', self::DB_VERSION ); } public static function all(): array { global $wpdb; $table = self::table(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table; query is safe. return $wpdb->get_results( "SELECT * FROM {$table} ORDER BY name ASC" ) ?: []; } public static function get( int $id ): ?object { global $wpdb; $table = self::table(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table; query is safe. return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table} WHERE id = %d", $id ) ) ?: null; } public static function upsert( array $d, int $id = 0 ): int { global $wpdb; $row = [ 'name' => sanitize_text_field( $d['name'] ?? '' ), 'purpose' => sanitize_textarea_field( $d['purpose'] ?? '' ), 'legal_basis' => sanitize_text_field( $d['legal_basis'] ?? '' ), 'data_categories' => sanitize_textarea_field( $d['data_categories'] ?? '' ), 'data_subjects' => sanitize_text_field( $d['data_subjects'] ?? '' ), 'recipients' => sanitize_textarea_field( $d['recipients'] ?? '' ), 'international_transfer' => ! empty( $d['international_transfer'] ) ? 1 : 0, 'transfer_safeguards' => sanitize_textarea_field( $d['transfer_safeguards'] ?? '' ), 'retention' => sanitize_text_field( $d['retention'] ?? '' ), 'security_measures' => sanitize_textarea_field( $d['security_measures'] ?? '' ), 'updated_at' => current_time( 'mysql' ), ]; if ( $id > 0 ) { $wpdb->update( self::table(), $row, [ 'id' => $id ] ); return $id; } $row['created_at'] = current_time( 'mysql' ); $wpdb->insert( self::table(), $row ); return (int) $wpdb->insert_id; } public static function delete( int $id ): void { global $wpdb; $wpdb->delete( self::table(), [ 'id' => $id ] ); } public static function export_csv(): string { $rows = self::all(); $csv = "Name,Purpose,Legal Basis,Data Categories,Subjects,Recipients,International Transfer,Safeguards,Retention,Security Measures,Updated\n"; foreach ( $rows as $r ) { $csv .= sprintf( '"%s","%s","%s","%s","%s","%s",%s,"%s","%s","%s","%s"' . "\n", str_replace( '"', '""', $r->name ), str_replace( '"', '""', $r->purpose ), str_replace( '"', '""', $r->legal_basis ), str_replace( '"', '""', $r->data_categories ), str_replace( '"', '""', $r->data_subjects ), str_replace( '"', '""', $r->recipients ), $r->international_transfer ? 'yes' : 'no', str_replace( '"', '""', $r->transfer_safeguards ), str_replace( '"', '""', $r->retention ), str_replace( '"', '""', $r->security_measures ), $r->updated_at ); } return $csv; } /** Seed with 3 default common WordPress processings. */ public static function seed_defaults(): void { global $wpdb; $table = self::table(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table; query is safe. if ( (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" ) > 0 ) return; $defaults = [ [ 'name' => 'Comentarios del sitio', 'purpose' => 'Permitir a los visitantes dejar comentarios en artículos.', 'legal_basis' => 'Consentimiento del titular', 'data_categories' => 'Nombre, email, IP, contenido del comentario', 'data_subjects' => 'Visitantes del sitio', 'recipients' => 'Solo administradores del sitio', 'retention' => 'Indefinido hasta que el titular solicite eliminación', 'security_measures' => 'Acceso restringido por rol, base de datos en servidor del sitio', ], [ 'name' => 'Formulario de contacto', 'purpose' => 'Recibir consultas de visitantes.', 'legal_basis' => 'Consentimiento del titular', 'data_categories' => 'Nombre, email, mensaje, IP', 'data_subjects' => 'Visitantes que envían el formulario', 'recipients' => 'Administradores del sitio', 'retention' => '12 meses desde el último contacto', 'security_measures' => 'Almacenamiento en base de datos del sitio, acceso restringido', ], [ 'name' => 'Cookies analíticas', 'purpose' => 'Medir uso del sitio para mejorar la experiencia.', 'legal_basis' => 'Consentimiento del titular (opt-in)', 'data_categories' => 'Identificadores de cookies, comportamiento de navegación', 'data_subjects' => 'Visitantes que aceptan analytics', 'recipients' => 'Proveedor de analytics (configurar)', 'international_transfer' => 1, 'transfer_safeguards' => 'Cláusulas contractuales tipo del proveedor', 'retention' => '14 meses (configurable en el proveedor)', 'security_measures' => 'Cifrado en tránsito (TLS), anonimización de IP cuando aplica', ], ]; foreach ( $defaults as $d ) self::upsert( $d ); } }