$post_type, 'posts_per_page' => -1, 'post_status' => 'any', 'fields' => 'ids', ) ); foreach ( $posts as $post_id ) { wp_delete_post( $post_id, true ); } } } /** * Delete all plugin taxonomy terms. * * @return void */ private static function delete_terms(): void { $taxonomies = array( 'fedistream_genre', 'fedistream_mood', 'fedistream_license', ); foreach ( $taxonomies as $taxonomy ) { $terms = get_terms( array( 'taxonomy' => $taxonomy, 'hide_empty' => false, 'fields' => 'ids', ) ); if ( ! is_wp_error( $terms ) ) { foreach ( $terms as $term_id ) { wp_delete_term( $term_id, $taxonomy ); } } } } /** * Install default taxonomy terms. * * Called on first load after activation when taxonomies are registered. * * @return void */ public static function install_defaults(): void { if ( ! get_option( 'wp_fedistream_install_defaults' ) ) { return; } // Install default genres. Genre::install_defaults(); // Install default moods. Mood::install_defaults(); // Install default licenses. License::install_defaults(); // Clear the flag. delete_option( 'wp_fedistream_install_defaults' ); } /** * Create custom database tables. * * @return void */ private static function create_tables(): void { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); // Track plays table. $table_plays = $wpdb->prefix . 'fedistream_plays'; $sql_plays = "CREATE TABLE $table_plays ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, track_id bigint(20) unsigned NOT NULL, user_id bigint(20) unsigned DEFAULT NULL, remote_actor varchar(255) DEFAULT NULL, played_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, play_duration int(11) unsigned DEFAULT 0, PRIMARY KEY (id), KEY track_id (track_id), KEY user_id (user_id), KEY played_at (played_at) ) $charset_collate;"; // Playlist tracks table (many-to-many relationship). $table_playlist_tracks = $wpdb->prefix . 'fedistream_playlist_tracks'; $sql_playlist_tracks = "CREATE TABLE $table_playlist_tracks ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, playlist_id bigint(20) unsigned NOT NULL, track_id bigint(20) unsigned NOT NULL, position int(11) unsigned NOT NULL DEFAULT 0, added_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY playlist_track (playlist_id, track_id), KEY playlist_id (playlist_id), KEY track_id (track_id), KEY position (position) ) $charset_collate;"; // ActivityPub followers table. $table_followers = $wpdb->prefix . 'fedistream_followers'; $sql_followers = "CREATE TABLE $table_followers ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, artist_id bigint(20) unsigned NOT NULL, follower_uri varchar(2083) NOT NULL, follower_name varchar(255) DEFAULT NULL, follower_icon varchar(2083) DEFAULT NULL, inbox varchar(2083) DEFAULT NULL, shared_inbox varchar(2083) DEFAULT NULL, activity_data longtext DEFAULT NULL, followed_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY artist_follower (artist_id, follower_uri(191)), KEY artist_id (artist_id), KEY followed_at (followed_at) ) $charset_collate;"; // WooCommerce purchases table. $table_purchases = $wpdb->prefix . 'fedistream_purchases'; $sql_purchases = "CREATE TABLE $table_purchases ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, user_id bigint(20) unsigned NOT NULL, content_type varchar(50) NOT NULL, content_id bigint(20) unsigned NOT NULL, order_id bigint(20) unsigned NOT NULL, purchased_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY user_content (user_id, content_type, content_id), KEY user_id (user_id), KEY content_type (content_type), KEY content_id (content_id), KEY order_id (order_id) ) $charset_collate;"; // User favorites table. $table_favorites = $wpdb->prefix . 'fedistream_favorites'; $sql_favorites = "CREATE TABLE $table_favorites ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, user_id bigint(20) unsigned NOT NULL, content_type varchar(50) NOT NULL, content_id bigint(20) unsigned NOT NULL, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY user_content (user_id, content_type, content_id), KEY user_id (user_id), KEY content_type (content_type), KEY content_id (content_id), KEY created_at (created_at) ) $charset_collate;"; // User follows table (local follows, not ActivityPub). $table_user_follows = $wpdb->prefix . 'fedistream_user_follows'; $sql_user_follows = "CREATE TABLE $table_user_follows ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, user_id bigint(20) unsigned NOT NULL, artist_id bigint(20) unsigned NOT NULL, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY user_artist (user_id, artist_id), KEY user_id (user_id), KEY artist_id (artist_id), KEY created_at (created_at) ) $charset_collate;"; // Listening history table. $table_history = $wpdb->prefix . 'fedistream_listening_history'; $sql_history = "CREATE TABLE $table_history ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, user_id bigint(20) unsigned NOT NULL, track_id bigint(20) unsigned NOT NULL, played_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY user_id (user_id), KEY track_id (track_id), KEY played_at (played_at), KEY user_played (user_id, played_at) ) $charset_collate;"; // Notifications table. $table_notifications = $wpdb->prefix . 'fedistream_notifications'; $sql_notifications = "CREATE TABLE $table_notifications ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, user_id bigint(20) unsigned NOT NULL, type varchar(50) NOT NULL, title varchar(255) NOT NULL, message text NOT NULL, data longtext DEFAULT NULL, is_read tinyint(1) unsigned NOT NULL DEFAULT 0, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, read_at datetime DEFAULT NULL, PRIMARY KEY (id), KEY user_id (user_id), KEY type (type), KEY is_read (is_read), KEY created_at (created_at), KEY user_unread (user_id, is_read) ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql_plays ); dbDelta( $sql_playlist_tracks ); dbDelta( $sql_followers ); dbDelta( $sql_purchases ); dbDelta( $sql_favorites ); dbDelta( $sql_user_follows ); dbDelta( $sql_history ); dbDelta( $sql_notifications ); } /** * Create required directories. * * @return void */ private static function create_directories(): void { $directories = array( WP_FEDISTREAM_PATH . 'cache/twig', ); foreach ( $directories as $directory ) { if ( ! file_exists( $directory ) ) { wp_mkdir_p( $directory ); } } // Create .htaccess to protect cache directory. $htaccess = WP_FEDISTREAM_PATH . 'cache/.htaccess'; if ( ! file_exists( $htaccess ) ) { file_put_contents( $htaccess, 'Deny from all' ); } } /** * Set default plugin options. * * @return void */ private static function set_default_options(): void { $defaults = array( 'wp_fedistream_enable_activitypub' => 1, 'wp_fedistream_enable_woocommerce' => 0, 'wp_fedistream_enable_prometheus' => 0, 'wp_fedistream_audio_formats' => array( 'mp3', 'wav', 'flac', 'ogg' ), 'wp_fedistream_max_upload_size' => 50, // MB 'wp_fedistream_default_license' => 'all-rights-reserved', // License management options. 'wp_fedistream_license_key' => '', 'wp_fedistream_license_server_url' => '', 'wp_fedistream_license_server_secret' => '', 'wp_fedistream_license_status' => 'unchecked', 'wp_fedistream_license_data' => array(), 'wp_fedistream_license_last_check' => 0, ); foreach ( $defaults as $option => $value ) { if ( false === get_option( $option ) ) { add_option( $option, $value ); } } } /** * Schedule cron events. * * @return void */ private static function schedule_events(): void { if ( ! wp_next_scheduled( 'wp_fedistream_daily_cleanup' ) ) { wp_schedule_event( time(), 'daily', 'wp_fedistream_daily_cleanup' ); } } /** * Unschedule cron events. * * @return void */ private static function unschedule_events(): void { $timestamp = wp_next_scheduled( 'wp_fedistream_daily_cleanup' ); if ( $timestamp ) { wp_unschedule_event( $timestamp, 'wp_fedistream_daily_cleanup' ); } } /** * Delete custom database tables. * * @return void */ private static function delete_tables(): void { global $wpdb; $tables = array( $wpdb->prefix . 'fedistream_plays', $wpdb->prefix . 'fedistream_playlist_tracks', $wpdb->prefix . 'fedistream_followers', $wpdb->prefix . 'fedistream_purchases', $wpdb->prefix . 'fedistream_reactions', $wpdb->prefix . 'fedistream_favorites', $wpdb->prefix . 'fedistream_user_follows', $wpdb->prefix . 'fedistream_listening_history', $wpdb->prefix . 'fedistream_notifications', ); foreach ( $tables as $table ) { // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $wpdb->query( "DROP TABLE IF EXISTS $table" ); } } /** * Delete plugin options. * * @return void */ private static function delete_options(): void { global $wpdb; // Delete all options starting with wp_fedistream_. $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name LIKE %s", 'wp_fedistream_%' ) ); } /** * Delete user meta. * * @return void */ private static function delete_user_meta(): void { global $wpdb; // Delete all user meta starting with wp_fedistream_. $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE meta_key LIKE %s", 'wp_fedistream_%' ) ); } /** * Delete transients. * * @return void */ private static function delete_transients(): void { global $wpdb; // Delete all transients starting with wp_fedistream_. $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name LIKE %s OR option_name LIKE %s", '_transient_wp_fedistream_%', '_transient_timeout_wp_fedistream_%' ) ); } }