$record Aufbereitete Mail. * @return int ID der Mail, 0 bei einem Fehler. */ public static function insert( array $record ) { global $wpdb; // Die Tabelle einer Site, auf der das Plugin netzwerkweit aktiviert // wurde, entsteht erst beim ersten Backend-Aufruf -- hier sicherheitshalber. Wp360_Staging_Guard_Database::maybe_upgrade(); $inserted = $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- eigene Tabelle, dafuer gibt es keine WordPress-API. Wp360_Staging_Guard_Database::table_name(), array( 'created_at' => gmdate( 'Y-m-d H:i:s' ), 'subject' => (string) ( $record['subject'] ?? '' ), 'recipients' => (string) wp_json_encode( $record['recipients'] ?? array() ), 'sender' => (string) ( $record['sender'] ?? '' ), 'headers' => (string) ( $record['headers'] ?? '' ), 'body' => (string) ( $record['body'] ?? '' ), 'is_html' => empty( $record['is_html'] ) ? 0 : 1, 'attachments' => (string) wp_json_encode( $record['attachments'] ?? array() ), ), array( '%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s' ) ); if ( false === $inserted ) { return 0; } $id = (int) $wpdb->insert_id; self::prune(); return $id; } /** Entfernt Mails ueber der Grenze und aelter als die eingestellte Aufbewahrung. */ public static function prune() { global $wpdb; $table = Wp360_Staging_Guard_Database::table_name(); $days = (int) Wp360_Staging_Guard_Settings::get()['mail_keep_days']; $cutoff = gmdate( 'Y-m-d H:i:s', time() - $days * DAY_IN_SECONDS ); $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE created_at < %s", $cutoff ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- eigene Tabelle, Name aus Praefix und Konstante. // Die ID der ersten Mail, die ueber der Grenze liegt (neueste zuerst). $limit = max( 1, self::limit() ); $boundary = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$table} ORDER BY id DESC LIMIT 1 OFFSET %d", $limit ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- siehe oben. if ( null !== $boundary ) { $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE id <= %d", (int) $boundary ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- siehe oben. } } /** * Die neuesten Mails ohne Text (fuer die Liste). * * @param int $limit Hoechstzahl. * @param string $search Suchtext (Betreff, Empfaenger, Absender); leer = alle. * @return array> */ public static function recent( $limit = 50, $search = '' ) { global $wpdb; $table = Wp360_Staging_Guard_Database::table_name(); $limit = max( 1, (int) $limit ); $rows = $wpdb->get_results( $wpdb->prepare( "SELECT id, created_at, subject, recipients, sender, is_html, attachments FROM {$table} ORDER BY id DESC LIMIT %d", $limit ), ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- eigene Tabelle. return array_map( array( __CLASS__, 'hydrate' ), is_array( $rows ) ? $rows : array() ); } /** * Eine Mail mit Text. * * @param int $id ID. * @return array|null */ public static function get( $id ) { global $wpdb; $table = Wp360_Staging_Guard_Database::table_name(); $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table} WHERE id = %d", (int) $id ), ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- eigene Tabelle. return is_array( $row ) ? self::hydrate( $row ) : null; } public static function delete( $id ) { global $wpdb; return (bool) $wpdb->delete( Wp360_Staging_Guard_Database::table_name(), array( 'id' => (int) $id ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- eigene Tabelle. } /** Entfernt alle aufgefangenen Mails. */ public static function delete_all() { global $wpdb; $table = Wp360_Staging_Guard_Database::table_name(); // DELETE statt TRUNCATE: braucht kein DROP-Recht und meldet Fehler. $wpdb->query( "DELETE FROM {$table}" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- eigene Tabelle. } /** @return int Zahl der gespeicherten Mails. */ public static function count() { global $wpdb; $table = Wp360_Staging_Guard_Database::table_name(); return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- eigene Tabelle. } /** * Wandelt eine Tabellenzeile in die Form, die der Rest des Plugins nutzt. * * @param array $row Zeile. * @return array */ private static function hydrate( array $row ) { $recipients = json_decode( (string) ( $row['recipients'] ?? '' ), true ); $attachments = json_decode( (string) ( $row['attachments'] ?? '' ), true ); $row['id'] = (int) ( $row['id'] ?? 0 ); $row['is_html'] = ! empty( $row['is_html'] ); $row['recipients'] = is_array( $recipients ) ? $recipients : array(); $row['attachments'] = is_array( $attachments ) ? $attachments : array(); return $row; } }