You've already forked wp-fedistream
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>
332 lines
14 KiB
PHP
332 lines
14 KiB
PHP
<?php
|
|
/**
|
|
* Artist custom post type.
|
|
*
|
|
* @package WP_FediStream
|
|
*/
|
|
|
|
namespace WP_FediStream\PostTypes;
|
|
|
|
// Prevent direct file access.
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Artist post type class.
|
|
*
|
|
* Handles registration and management of artist/band profiles.
|
|
*/
|
|
class Artist extends AbstractPostType {
|
|
|
|
/**
|
|
* Post type key.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected string $post_type = 'fedistream_artist';
|
|
|
|
/**
|
|
* Meta key prefix.
|
|
*
|
|
* @var string
|
|
*/
|
|
private const META_PREFIX = '_fedistream_artist_';
|
|
|
|
/**
|
|
* Register the post type.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function register(): void {
|
|
$labels = array(
|
|
'name' => _x( 'Artists', 'Post type general name', 'wp-fedistream' ),
|
|
'singular_name' => _x( 'Artist', 'Post type singular name', 'wp-fedistream' ),
|
|
'menu_name' => _x( 'Artists', 'Admin Menu text', 'wp-fedistream' ),
|
|
'name_admin_bar' => _x( 'Artist', 'Add New on Toolbar', 'wp-fedistream' ),
|
|
'add_new' => __( 'Add New', 'wp-fedistream' ),
|
|
'add_new_item' => __( 'Add New Artist', 'wp-fedistream' ),
|
|
'new_item' => __( 'New Artist', 'wp-fedistream' ),
|
|
'edit_item' => __( 'Edit Artist', 'wp-fedistream' ),
|
|
'view_item' => __( 'View Artist', 'wp-fedistream' ),
|
|
'all_items' => __( 'All Artists', 'wp-fedistream' ),
|
|
'search_items' => __( 'Search Artists', 'wp-fedistream' ),
|
|
'parent_item_colon' => __( 'Parent Artists:', 'wp-fedistream' ),
|
|
'not_found' => __( 'No artists found.', 'wp-fedistream' ),
|
|
'not_found_in_trash' => __( 'No artists found in Trash.', 'wp-fedistream' ),
|
|
'featured_image' => _x( 'Artist Photo', 'Overrides the "Featured Image" phrase', 'wp-fedistream' ),
|
|
'set_featured_image' => _x( 'Set artist photo', 'Overrides the "Set featured image" phrase', 'wp-fedistream' ),
|
|
'remove_featured_image' => _x( 'Remove artist photo', 'Overrides the "Remove featured image" phrase', 'wp-fedistream' ),
|
|
'use_featured_image' => _x( 'Use as artist photo', 'Overrides the "Use as featured image" phrase', 'wp-fedistream' ),
|
|
'archives' => _x( 'Artist archives', 'The post type archive label', 'wp-fedistream' ),
|
|
'insert_into_item' => _x( 'Insert into artist', 'Overrides the "Insert into post" phrase', 'wp-fedistream' ),
|
|
'uploaded_to_this_item' => _x( 'Uploaded to this artist', 'Overrides the "Uploaded to this post" phrase', 'wp-fedistream' ),
|
|
'filter_items_list' => _x( 'Filter artists list', 'Screen reader text', 'wp-fedistream' ),
|
|
'items_list_navigation' => _x( 'Artists list navigation', 'Screen reader text', 'wp-fedistream' ),
|
|
'items_list' => _x( 'Artists list', 'Screen reader text', 'wp-fedistream' ),
|
|
);
|
|
|
|
$args = array(
|
|
'labels' => $labels,
|
|
'public' => true,
|
|
'publicly_queryable' => true,
|
|
'show_ui' => true,
|
|
'show_in_menu' => false, // Will be added to custom menu.
|
|
'query_var' => true,
|
|
'rewrite' => array( 'slug' => 'artists' ),
|
|
'capability_type' => array( 'fedistream_artist', 'fedistream_artists' ),
|
|
'map_meta_cap' => true,
|
|
'has_archive' => true,
|
|
'hierarchical' => false,
|
|
'menu_position' => null,
|
|
'menu_icon' => 'dashicons-groups',
|
|
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'revisions' ),
|
|
'show_in_rest' => true,
|
|
'rest_base' => 'artists',
|
|
);
|
|
|
|
register_post_type( $this->post_type, $args );
|
|
}
|
|
|
|
/**
|
|
* Add meta boxes.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function add_meta_boxes(): void {
|
|
add_meta_box(
|
|
'fedistream_artist_info',
|
|
__( 'Artist Information', 'wp-fedistream' ),
|
|
array( $this, 'render_info_meta_box' ),
|
|
$this->post_type,
|
|
'normal',
|
|
'high'
|
|
);
|
|
|
|
add_meta_box(
|
|
'fedistream_artist_social',
|
|
__( 'Social Links', 'wp-fedistream' ),
|
|
array( $this, 'render_social_meta_box' ),
|
|
$this->post_type,
|
|
'normal',
|
|
'default'
|
|
);
|
|
|
|
add_meta_box(
|
|
'fedistream_artist_members',
|
|
__( 'Band Members', 'wp-fedistream' ),
|
|
array( $this, 'render_members_meta_box' ),
|
|
$this->post_type,
|
|
'side',
|
|
'default'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render artist info meta box.
|
|
*
|
|
* @param \WP_Post $post Post object.
|
|
* @return void
|
|
*/
|
|
public function render_info_meta_box( \WP_Post $post ): void {
|
|
wp_nonce_field( 'fedistream_artist_save', 'fedistream_artist_nonce' );
|
|
|
|
$artist_type = get_post_meta( $post->ID, self::META_PREFIX . 'type', true );
|
|
$formed_date = get_post_meta( $post->ID, self::META_PREFIX . 'formed_date', true );
|
|
$location = get_post_meta( $post->ID, self::META_PREFIX . 'location', true );
|
|
$website = get_post_meta( $post->ID, self::META_PREFIX . 'website', true );
|
|
?>
|
|
<table class="form-table">
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="fedistream_artist_type"><?php esc_html_e( 'Artist Type', 'wp-fedistream' ); ?></label>
|
|
</th>
|
|
<td>
|
|
<select name="fedistream_artist_type" id="fedistream_artist_type">
|
|
<option value="solo" <?php selected( $artist_type, 'solo' ); ?>><?php esc_html_e( 'Solo Artist', 'wp-fedistream' ); ?></option>
|
|
<option value="band" <?php selected( $artist_type, 'band' ); ?>><?php esc_html_e( 'Band', 'wp-fedistream' ); ?></option>
|
|
<option value="duo" <?php selected( $artist_type, 'duo' ); ?>><?php esc_html_e( 'Duo', 'wp-fedistream' ); ?></option>
|
|
<option value="collective" <?php selected( $artist_type, 'collective' ); ?>><?php esc_html_e( 'Collective', 'wp-fedistream' ); ?></option>
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="fedistream_artist_formed_date"><?php esc_html_e( 'Formed Date', 'wp-fedistream' ); ?></label>
|
|
</th>
|
|
<td>
|
|
<input type="date" name="fedistream_artist_formed_date" id="fedistream_artist_formed_date" value="<?php echo esc_attr( $formed_date ); ?>" class="regular-text">
|
|
<p class="description"><?php esc_html_e( 'When the artist/band was formed or started their career.', 'wp-fedistream' ); ?></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="fedistream_artist_location"><?php esc_html_e( 'Location', 'wp-fedistream' ); ?></label>
|
|
</th>
|
|
<td>
|
|
<input type="text" name="fedistream_artist_location" id="fedistream_artist_location" value="<?php echo esc_attr( $location ); ?>" class="regular-text">
|
|
<p class="description"><?php esc_html_e( 'City, Country or region where the artist is based.', 'wp-fedistream' ); ?></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="fedistream_artist_website"><?php esc_html_e( 'Website', 'wp-fedistream' ); ?></label>
|
|
</th>
|
|
<td>
|
|
<input type="url" name="fedistream_artist_website" id="fedistream_artist_website" value="<?php echo esc_url( $website ); ?>" class="regular-text">
|
|
<p class="description"><?php esc_html_e( 'Official website URL.', 'wp-fedistream' ); ?></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Render social links meta box.
|
|
*
|
|
* @param \WP_Post $post Post object.
|
|
* @return void
|
|
*/
|
|
public function render_social_meta_box( \WP_Post $post ): void {
|
|
$social_links = get_post_meta( $post->ID, self::META_PREFIX . 'social_links', true );
|
|
if ( ! is_array( $social_links ) ) {
|
|
$social_links = array();
|
|
}
|
|
|
|
$platforms = array(
|
|
'mastodon' => __( 'Mastodon', 'wp-fedistream' ),
|
|
'bandcamp' => __( 'Bandcamp', 'wp-fedistream' ),
|
|
'soundcloud' => __( 'SoundCloud', 'wp-fedistream' ),
|
|
'youtube' => __( 'YouTube', 'wp-fedistream' ),
|
|
'instagram' => __( 'Instagram', 'wp-fedistream' ),
|
|
'twitter' => __( 'Twitter/X', 'wp-fedistream' ),
|
|
'facebook' => __( 'Facebook', 'wp-fedistream' ),
|
|
'tiktok' => __( 'TikTok', 'wp-fedistream' ),
|
|
'other' => __( 'Other', 'wp-fedistream' ),
|
|
);
|
|
?>
|
|
<table class="form-table">
|
|
<?php foreach ( $platforms as $key => $label ) : ?>
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="fedistream_social_<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label>
|
|
</th>
|
|
<td>
|
|
<input type="url" name="fedistream_artist_social[<?php echo esc_attr( $key ); ?>]" id="fedistream_social_<?php echo esc_attr( $key ); ?>" value="<?php echo esc_url( $social_links[ $key ] ?? '' ); ?>" class="regular-text">
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</table>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Render band members meta box.
|
|
*
|
|
* @param \WP_Post $post Post object.
|
|
* @return void
|
|
*/
|
|
public function render_members_meta_box( \WP_Post $post ): void {
|
|
$members = get_post_meta( $post->ID, self::META_PREFIX . 'members', true );
|
|
if ( ! is_array( $members ) ) {
|
|
$members = array();
|
|
}
|
|
|
|
$artist_type = get_post_meta( $post->ID, self::META_PREFIX . 'type', true );
|
|
?>
|
|
<div id="fedistream-members-wrapper" style="<?php echo 'solo' === $artist_type ? 'display:none;' : ''; ?>">
|
|
<p class="description"><?php esc_html_e( 'Add band/group members (comma-separated names).', 'wp-fedistream' ); ?></p>
|
|
<textarea name="fedistream_artist_members" id="fedistream_artist_members" rows="5" class="large-text"><?php echo esc_textarea( implode( "\n", $members ) ); ?></textarea>
|
|
<p class="description"><?php esc_html_e( 'One member per line.', 'wp-fedistream' ); ?></p>
|
|
</div>
|
|
<script>
|
|
jQuery(document).ready(function($) {
|
|
$('#fedistream_artist_type').on('change', function() {
|
|
if ($(this).val() === 'solo') {
|
|
$('#fedistream-members-wrapper').hide();
|
|
} else {
|
|
$('#fedistream-members-wrapper').show();
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Save post meta.
|
|
*
|
|
* @param int $post_id Post ID.
|
|
* @param \WP_Post $post Post object.
|
|
* @return void
|
|
*/
|
|
public function save_meta( int $post_id, \WP_Post $post ): void {
|
|
if ( ! $this->can_save( $post_id, 'fedistream_artist_save', 'fedistream_artist_nonce' ) ) {
|
|
return;
|
|
}
|
|
|
|
// Save artist type.
|
|
if ( isset( $_POST['fedistream_artist_type'] ) ) {
|
|
$allowed_types = array( 'solo', 'band', 'duo', 'collective' );
|
|
$type = sanitize_text_field( wp_unslash( $_POST['fedistream_artist_type'] ) );
|
|
if ( in_array( $type, $allowed_types, true ) ) {
|
|
update_post_meta( $post_id, self::META_PREFIX . 'type', $type );
|
|
}
|
|
}
|
|
|
|
// Save other fields.
|
|
$this->save_date_meta( $post_id, self::META_PREFIX . 'formed_date', 'fedistream_artist_formed_date' );
|
|
$this->save_text_meta( $post_id, self::META_PREFIX . 'location', 'fedistream_artist_location' );
|
|
$this->save_url_meta( $post_id, self::META_PREFIX . 'website', 'fedistream_artist_website' );
|
|
|
|
// Save social links.
|
|
if ( isset( $_POST['fedistream_artist_social'] ) && is_array( $_POST['fedistream_artist_social'] ) ) {
|
|
$social_links = array();
|
|
foreach ( $_POST['fedistream_artist_social'] as $key => $url ) {
|
|
$clean_key = sanitize_key( $key );
|
|
$clean_url = esc_url_raw( wp_unslash( $url ) );
|
|
if ( ! empty( $clean_url ) ) {
|
|
$social_links[ $clean_key ] = $clean_url;
|
|
}
|
|
}
|
|
update_post_meta( $post_id, self::META_PREFIX . 'social_links', $social_links );
|
|
}
|
|
|
|
// Save members.
|
|
if ( isset( $_POST['fedistream_artist_members'] ) ) {
|
|
$members_text = sanitize_textarea_field( wp_unslash( $_POST['fedistream_artist_members'] ) );
|
|
$members = array_filter( array_map( 'trim', explode( "\n", $members_text ) ) );
|
|
update_post_meta( $post_id, self::META_PREFIX . 'members', $members );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get artist by ID with meta.
|
|
*
|
|
* @param int $post_id Post ID.
|
|
* @return array|null Artist data or null.
|
|
*/
|
|
public static function get_artist( int $post_id ): ?array {
|
|
$post = get_post( $post_id );
|
|
if ( ! $post || 'fedistream_artist' !== $post->post_type ) {
|
|
return null;
|
|
}
|
|
|
|
return array(
|
|
'id' => $post->ID,
|
|
'name' => $post->post_title,
|
|
'slug' => $post->post_name,
|
|
'bio' => $post->post_content,
|
|
'excerpt' => $post->post_excerpt,
|
|
'type' => get_post_meta( $post_id, self::META_PREFIX . 'type', true ) ?: 'solo',
|
|
'formed_date' => get_post_meta( $post_id, self::META_PREFIX . 'formed_date', true ),
|
|
'location' => get_post_meta( $post_id, self::META_PREFIX . 'location', true ),
|
|
'website' => get_post_meta( $post_id, self::META_PREFIX . 'website', true ),
|
|
'social_links' => get_post_meta( $post_id, self::META_PREFIX . 'social_links', true ) ?: array(),
|
|
'members' => get_post_meta( $post_id, self::META_PREFIX . 'members', true ) ?: array(),
|
|
'photo' => get_the_post_thumbnail_url( $post_id, 'large' ),
|
|
'url' => get_permalink( $post_id ),
|
|
);
|
|
}
|
|
}
|