You've already forked wp-fedistream
feat: Initial release v0.1.0
WP FediStream - Stream music over ActivityPub Features: - Custom post types: Artist, Album, Track, Playlist - Custom taxonomies: Genre, Mood, License - User roles: Artist, Label - Admin dashboard with statistics - Frontend templates and shortcodes - Audio player with queue management - ActivityPub integration with actor support - WooCommerce product types for albums/tracks - User library with favorites and history - Notification system (in-app and email) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
462
includes/Installer.php
Normal file
462
includes/Installer.php
Normal file
@@ -0,0 +1,462 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin installer class.
|
||||
*
|
||||
* @package WP_FediStream
|
||||
*/
|
||||
|
||||
namespace WP_FediStream;
|
||||
|
||||
use WP_FediStream\Roles\Capabilities;
|
||||
use WP_FediStream\Taxonomies\Genre;
|
||||
use WP_FediStream\Taxonomies\Mood;
|
||||
use WP_FediStream\Taxonomies\License;
|
||||
|
||||
// Prevent direct file access.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles plugin activation, deactivation, and uninstallation.
|
||||
*/
|
||||
class Installer {
|
||||
|
||||
/**
|
||||
* Plugin activation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function activate(): void {
|
||||
self::create_tables();
|
||||
self::create_directories();
|
||||
self::set_default_options();
|
||||
self::schedule_events();
|
||||
|
||||
// Install roles and capabilities.
|
||||
Capabilities::install();
|
||||
|
||||
// Store installed version.
|
||||
update_option( 'wp_fedistream_version', WP_FEDISTREAM_VERSION );
|
||||
|
||||
// Flush rewrite rules for custom post types.
|
||||
flush_rewrite_rules();
|
||||
|
||||
// Install default taxonomy terms (after rewrite rules flush).
|
||||
// Schedule for next page load since taxonomies need to be registered first.
|
||||
update_option( 'wp_fedistream_install_defaults', 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin deactivation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function deactivate(): void {
|
||||
self::unschedule_events();
|
||||
|
||||
// Flush rewrite rules.
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin uninstallation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function uninstall(): void {
|
||||
// Only run if uninstall is explicitly requested.
|
||||
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::delete_tables();
|
||||
self::delete_options();
|
||||
self::delete_user_meta();
|
||||
self::delete_transients();
|
||||
self::delete_posts();
|
||||
self::delete_terms();
|
||||
|
||||
// Remove roles and capabilities.
|
||||
Capabilities::uninstall();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all plugin posts.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function delete_posts(): void {
|
||||
$post_types = array(
|
||||
'fedistream_artist',
|
||||
'fedistream_album',
|
||||
'fedistream_track',
|
||||
'fedistream_playlist',
|
||||
);
|
||||
|
||||
foreach ( $post_types as $post_type ) {
|
||||
$posts = get_posts(
|
||||
array(
|
||||
'post_type' => $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_audio_formats' => array( 'mp3', 'wav', 'flac', 'ogg' ),
|
||||
'wp_fedistream_max_upload_size' => 50, // MB
|
||||
'wp_fedistream_default_license' => 'all-rights-reserved',
|
||||
);
|
||||
|
||||
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_%'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user