You've already forked wp-fedistream
341 lines
15 KiB
PHP
341 lines
15 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* Album custom post type.
|
||
|
|
*
|
||
|
|
* @package WP_FediStream
|
||
|
|
*/
|
||
|
|
|
||
|
|
namespace WP_FediStream\PostTypes;
|
||
|
|
|
||
|
|
// Prevent direct file access.
|
||
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Album post type class.
|
||
|
|
*
|
||
|
|
* Handles registration and management of albums/releases.
|
||
|
|
*/
|
||
|
|
class Album extends AbstractPostType {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Post type key.
|
||
|
|
*
|
||
|
|
* @var string
|
||
|
|
*/
|
||
|
|
protected string $post_type = 'fedistream_album';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Meta key prefix.
|
||
|
|
*
|
||
|
|
* @var string
|
||
|
|
*/
|
||
|
|
private const META_PREFIX = '_fedistream_album_';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Register the post type.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public function register(): void {
|
||
|
|
$labels = array(
|
||
|
|
'name' => _x( 'Albums', 'Post type general name', 'wp-fedistream' ),
|
||
|
|
'singular_name' => _x( 'Album', 'Post type singular name', 'wp-fedistream' ),
|
||
|
|
'menu_name' => _x( 'Albums', 'Admin Menu text', 'wp-fedistream' ),
|
||
|
|
'name_admin_bar' => _x( 'Album', 'Add New on Toolbar', 'wp-fedistream' ),
|
||
|
|
'add_new' => __( 'Add New', 'wp-fedistream' ),
|
||
|
|
'add_new_item' => __( 'Add New Album', 'wp-fedistream' ),
|
||
|
|
'new_item' => __( 'New Album', 'wp-fedistream' ),
|
||
|
|
'edit_item' => __( 'Edit Album', 'wp-fedistream' ),
|
||
|
|
'view_item' => __( 'View Album', 'wp-fedistream' ),
|
||
|
|
'all_items' => __( 'All Albums', 'wp-fedistream' ),
|
||
|
|
'search_items' => __( 'Search Albums', 'wp-fedistream' ),
|
||
|
|
'parent_item_colon' => __( 'Parent Albums:', 'wp-fedistream' ),
|
||
|
|
'not_found' => __( 'No albums found.', 'wp-fedistream' ),
|
||
|
|
'not_found_in_trash' => __( 'No albums found in Trash.', 'wp-fedistream' ),
|
||
|
|
'featured_image' => _x( 'Album Artwork', 'Overrides the "Featured Image" phrase', 'wp-fedistream' ),
|
||
|
|
'set_featured_image' => _x( 'Set album artwork', 'Overrides the "Set featured image" phrase', 'wp-fedistream' ),
|
||
|
|
'remove_featured_image' => _x( 'Remove album artwork', 'Overrides the "Remove featured image" phrase', 'wp-fedistream' ),
|
||
|
|
'use_featured_image' => _x( 'Use as album artwork', 'Overrides the "Use as featured image" phrase', 'wp-fedistream' ),
|
||
|
|
'archives' => _x( 'Album archives', 'The post type archive label', 'wp-fedistream' ),
|
||
|
|
'insert_into_item' => _x( 'Insert into album', 'Overrides the "Insert into post" phrase', 'wp-fedistream' ),
|
||
|
|
'uploaded_to_this_item' => _x( 'Uploaded to this album', 'Overrides the "Uploaded to this post" phrase', 'wp-fedistream' ),
|
||
|
|
'filter_items_list' => _x( 'Filter albums list', 'Screen reader text', 'wp-fedistream' ),
|
||
|
|
'items_list_navigation' => _x( 'Albums list navigation', 'Screen reader text', 'wp-fedistream' ),
|
||
|
|
'items_list' => _x( 'Albums 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' => 'albums' ),
|
||
|
|
'capability_type' => array( 'fedistream_album', 'fedistream_albums' ),
|
||
|
|
'map_meta_cap' => true,
|
||
|
|
'has_archive' => true,
|
||
|
|
'hierarchical' => false,
|
||
|
|
'menu_position' => null,
|
||
|
|
'menu_icon' => 'dashicons-album',
|
||
|
|
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'revisions' ),
|
||
|
|
'show_in_rest' => true,
|
||
|
|
'rest_base' => 'albums',
|
||
|
|
);
|
||
|
|
|
||
|
|
register_post_type( $this->post_type, $args );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add meta boxes.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public function add_meta_boxes(): void {
|
||
|
|
add_meta_box(
|
||
|
|
'fedistream_album_info',
|
||
|
|
__( 'Album Information', 'wp-fedistream' ),
|
||
|
|
array( $this, 'render_info_meta_box' ),
|
||
|
|
$this->post_type,
|
||
|
|
'normal',
|
||
|
|
'high'
|
||
|
|
);
|
||
|
|
|
||
|
|
add_meta_box(
|
||
|
|
'fedistream_album_artist',
|
||
|
|
__( 'Artist', 'wp-fedistream' ),
|
||
|
|
array( $this, 'render_artist_meta_box' ),
|
||
|
|
$this->post_type,
|
||
|
|
'side',
|
||
|
|
'high'
|
||
|
|
);
|
||
|
|
|
||
|
|
add_meta_box(
|
||
|
|
'fedistream_album_codes',
|
||
|
|
__( 'Album Codes', 'wp-fedistream' ),
|
||
|
|
array( $this, 'render_codes_meta_box' ),
|
||
|
|
$this->post_type,
|
||
|
|
'side',
|
||
|
|
'default'
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Render album 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_album_save', 'fedistream_album_nonce' );
|
||
|
|
|
||
|
|
$album_type = get_post_meta( $post->ID, self::META_PREFIX . 'type', true );
|
||
|
|
$release_date = get_post_meta( $post->ID, self::META_PREFIX . 'release_date', true );
|
||
|
|
$total_tracks = get_post_meta( $post->ID, self::META_PREFIX . 'total_tracks', true );
|
||
|
|
$total_duration = get_post_meta( $post->ID, self::META_PREFIX . 'total_duration', true );
|
||
|
|
?>
|
||
|
|
<table class="form-table">
|
||
|
|
<tr>
|
||
|
|
<th scope="row">
|
||
|
|
<label for="fedistream_album_type"><?php esc_html_e( 'Release Type', 'wp-fedistream' ); ?></label>
|
||
|
|
</th>
|
||
|
|
<td>
|
||
|
|
<select name="fedistream_album_type" id="fedistream_album_type">
|
||
|
|
<option value="album" <?php selected( $album_type, 'album' ); ?>><?php esc_html_e( 'Album', 'wp-fedistream' ); ?></option>
|
||
|
|
<option value="ep" <?php selected( $album_type, 'ep' ); ?>><?php esc_html_e( 'EP', 'wp-fedistream' ); ?></option>
|
||
|
|
<option value="single" <?php selected( $album_type, 'single' ); ?>><?php esc_html_e( 'Single', 'wp-fedistream' ); ?></option>
|
||
|
|
<option value="compilation" <?php selected( $album_type, 'compilation' ); ?>><?php esc_html_e( 'Compilation', 'wp-fedistream' ); ?></option>
|
||
|
|
<option value="live" <?php selected( $album_type, 'live' ); ?>><?php esc_html_e( 'Live Album', 'wp-fedistream' ); ?></option>
|
||
|
|
<option value="remix" <?php selected( $album_type, 'remix' ); ?>><?php esc_html_e( 'Remix Album', 'wp-fedistream' ); ?></option>
|
||
|
|
</select>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<th scope="row">
|
||
|
|
<label for="fedistream_album_release_date"><?php esc_html_e( 'Release Date', 'wp-fedistream' ); ?></label>
|
||
|
|
</th>
|
||
|
|
<td>
|
||
|
|
<input type="date" name="fedistream_album_release_date" id="fedistream_album_release_date" value="<?php echo esc_attr( $release_date ); ?>" class="regular-text">
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<th scope="row">
|
||
|
|
<label for="fedistream_album_total_tracks"><?php esc_html_e( 'Total Tracks', 'wp-fedistream' ); ?></label>
|
||
|
|
</th>
|
||
|
|
<td>
|
||
|
|
<input type="number" name="fedistream_album_total_tracks" id="fedistream_album_total_tracks" value="<?php echo esc_attr( $total_tracks ); ?>" min="1" max="999" class="small-text">
|
||
|
|
<p class="description"><?php esc_html_e( 'Auto-calculated when tracks are added.', 'wp-fedistream' ); ?></p>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<th scope="row">
|
||
|
|
<label for="fedistream_album_total_duration"><?php esc_html_e( 'Total Duration', 'wp-fedistream' ); ?></label>
|
||
|
|
</th>
|
||
|
|
<td>
|
||
|
|
<input type="number" name="fedistream_album_total_duration" id="fedistream_album_total_duration" value="<?php echo esc_attr( $total_duration ); ?>" min="0" class="small-text" readonly>
|
||
|
|
<span class="description"><?php esc_html_e( 'seconds (auto-calculated)', 'wp-fedistream' ); ?></span>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
</table>
|
||
|
|
<?php
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Render artist selection meta box.
|
||
|
|
*
|
||
|
|
* @param \WP_Post $post Post object.
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public function render_artist_meta_box( \WP_Post $post ): void {
|
||
|
|
$selected_artist = get_post_meta( $post->ID, self::META_PREFIX . 'artist', true );
|
||
|
|
|
||
|
|
$artists = get_posts(
|
||
|
|
array(
|
||
|
|
'post_type' => 'fedistream_artist',
|
||
|
|
'posts_per_page' => -1,
|
||
|
|
'post_status' => 'publish',
|
||
|
|
'orderby' => 'title',
|
||
|
|
'order' => 'ASC',
|
||
|
|
)
|
||
|
|
);
|
||
|
|
?>
|
||
|
|
<p>
|
||
|
|
<label for="fedistream_album_artist"><?php esc_html_e( 'Primary Artist', 'wp-fedistream' ); ?></label>
|
||
|
|
</p>
|
||
|
|
<select name="fedistream_album_artist" id="fedistream_album_artist" class="widefat">
|
||
|
|
<option value=""><?php esc_html_e( '— Select Artist —', 'wp-fedistream' ); ?></option>
|
||
|
|
<?php foreach ( $artists as $artist ) : ?>
|
||
|
|
<option value="<?php echo esc_attr( $artist->ID ); ?>" <?php selected( $selected_artist, $artist->ID ); ?>>
|
||
|
|
<?php echo esc_html( $artist->post_title ); ?>
|
||
|
|
</option>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
</select>
|
||
|
|
<p class="description">
|
||
|
|
<?php
|
||
|
|
if ( empty( $artists ) ) {
|
||
|
|
printf(
|
||
|
|
/* translators: %s: URL to add new artist */
|
||
|
|
esc_html__( 'No artists found. %s', 'wp-fedistream' ),
|
||
|
|
'<a href="' . esc_url( admin_url( 'post-new.php?post_type=fedistream_artist' ) ) . '">' . esc_html__( 'Add an artist first.', 'wp-fedistream' ) . '</a>'
|
||
|
|
);
|
||
|
|
}
|
||
|
|
?>
|
||
|
|
</p>
|
||
|
|
<?php
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Render album codes meta box.
|
||
|
|
*
|
||
|
|
* @param \WP_Post $post Post object.
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public function render_codes_meta_box( \WP_Post $post ): void {
|
||
|
|
$upc = get_post_meta( $post->ID, self::META_PREFIX . 'upc', true );
|
||
|
|
$catalog_number = get_post_meta( $post->ID, self::META_PREFIX . 'catalog_number', true );
|
||
|
|
?>
|
||
|
|
<p>
|
||
|
|
<label for="fedistream_album_upc"><?php esc_html_e( 'UPC/EAN', 'wp-fedistream' ); ?></label>
|
||
|
|
<input type="text" name="fedistream_album_upc" id="fedistream_album_upc" value="<?php echo esc_attr( $upc ); ?>" class="widefat" pattern="[0-9]{12,13}" title="<?php esc_attr_e( '12-13 digit UPC/EAN code', 'wp-fedistream' ); ?>">
|
||
|
|
</p>
|
||
|
|
<p>
|
||
|
|
<label for="fedistream_album_catalog_number"><?php esc_html_e( 'Catalog Number', 'wp-fedistream' ); ?></label>
|
||
|
|
<input type="text" name="fedistream_album_catalog_number" id="fedistream_album_catalog_number" value="<?php echo esc_attr( $catalog_number ); ?>" class="widefat">
|
||
|
|
</p>
|
||
|
|
<?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_album_save', 'fedistream_album_nonce' ) ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Save album type.
|
||
|
|
if ( isset( $_POST['fedistream_album_type'] ) ) {
|
||
|
|
$allowed_types = array( 'album', 'ep', 'single', 'compilation', 'live', 'remix' );
|
||
|
|
$type = sanitize_text_field( wp_unslash( $_POST['fedistream_album_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 . 'release_date', 'fedistream_album_release_date' );
|
||
|
|
$this->save_int_meta( $post_id, self::META_PREFIX . 'artist', 'fedistream_album_artist' );
|
||
|
|
$this->save_int_meta( $post_id, self::META_PREFIX . 'total_tracks', 'fedistream_album_total_tracks' );
|
||
|
|
$this->save_text_meta( $post_id, self::META_PREFIX . 'upc', 'fedistream_album_upc' );
|
||
|
|
$this->save_text_meta( $post_id, self::META_PREFIX . 'catalog_number', 'fedistream_album_catalog_number' );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get album by ID with meta.
|
||
|
|
*
|
||
|
|
* @param int $post_id Post ID.
|
||
|
|
* @return array|null Album data or null.
|
||
|
|
*/
|
||
|
|
public static function get_album( int $post_id ): ?array {
|
||
|
|
$post = get_post( $post_id );
|
||
|
|
if ( ! $post || 'fedistream_album' !== $post->post_type ) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
$artist_id = get_post_meta( $post_id, self::META_PREFIX . 'artist', true );
|
||
|
|
|
||
|
|
return array(
|
||
|
|
'id' => $post->ID,
|
||
|
|
'title' => $post->post_title,
|
||
|
|
'slug' => $post->post_name,
|
||
|
|
'description' => $post->post_content,
|
||
|
|
'excerpt' => $post->post_excerpt,
|
||
|
|
'type' => get_post_meta( $post_id, self::META_PREFIX . 'type', true ) ?: 'album',
|
||
|
|
'release_date' => get_post_meta( $post_id, self::META_PREFIX . 'release_date', true ),
|
||
|
|
'artist_id' => $artist_id,
|
||
|
|
'artist_name' => $artist_id ? get_the_title( $artist_id ) : '',
|
||
|
|
'total_tracks' => (int) get_post_meta( $post_id, self::META_PREFIX . 'total_tracks', true ),
|
||
|
|
'total_duration' => (int) get_post_meta( $post_id, self::META_PREFIX . 'total_duration', true ),
|
||
|
|
'upc' => get_post_meta( $post_id, self::META_PREFIX . 'upc', true ),
|
||
|
|
'catalog_number' => get_post_meta( $post_id, self::META_PREFIX . 'catalog_number', true ),
|
||
|
|
'artwork' => get_the_post_thumbnail_url( $post_id, 'large' ),
|
||
|
|
'url' => get_permalink( $post_id ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update album track count and duration.
|
||
|
|
*
|
||
|
|
* @param int $album_id Album post ID.
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public static function update_album_stats( int $album_id ): void {
|
||
|
|
$tracks = get_posts(
|
||
|
|
array(
|
||
|
|
'post_type' => 'fedistream_track',
|
||
|
|
'posts_per_page' => -1,
|
||
|
|
'post_status' => 'publish',
|
||
|
|
'meta_key' => '_fedistream_track_album',
|
||
|
|
'meta_value' => $album_id,
|
||
|
|
)
|
||
|
|
);
|
||
|
|
|
||
|
|
$total_tracks = count( $tracks );
|
||
|
|
$total_duration = 0;
|
||
|
|
|
||
|
|
foreach ( $tracks as $track ) {
|
||
|
|
$duration = (int) get_post_meta( $track->ID, '_fedistream_track_duration', true );
|
||
|
|
$total_duration += $duration;
|
||
|
|
}
|
||
|
|
|
||
|
|
update_post_meta( $album_id, self::META_PREFIX . 'total_tracks', $total_tracks );
|
||
|
|
update_post_meta( $album_id, self::META_PREFIX . 'total_duration', $total_duration );
|
||
|
|
}
|
||
|
|
}
|