added stuff to manage a top album ranking
This commit is contained in:
parent
55e0ad611c
commit
23560bb1fc
286
album-scores.php
Normal file
286
album-scores.php
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit; // Exit if accessed directly
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlbumScoreManager {
|
||||||
|
|
||||||
|
private $scrobbles_table;
|
||||||
|
private $scores_table;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
global $wpdb;
|
||||||
|
$this->scrobbles_table = 'song_scrobbles'; // Added $wpdb->prefix for table names
|
||||||
|
$this->scores_table = 'album_scores';
|
||||||
|
|
||||||
|
// Add admin menu
|
||||||
|
add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
|
||||||
|
|
||||||
|
// Enqueue admin scripts
|
||||||
|
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
|
||||||
|
|
||||||
|
// Add AJAX handler
|
||||||
|
add_action( 'wp_ajax_asm_update_score', array( $this, 'ajax_update_score' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue custom JavaScript for handling AJAX requests
|
||||||
|
*/
|
||||||
|
public function enqueue_admin_scripts( $hook ) {
|
||||||
|
// Only enqueue on our plugin's admin page
|
||||||
|
if ( $hook !== 'toplevel_page_album-score-manager' ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enqueue the script
|
||||||
|
wp_enqueue_script(
|
||||||
|
'asm-admin-script',
|
||||||
|
plugin_dir_url( __FILE__ ) . 'js/asm-admin.js', // You'll create this file next
|
||||||
|
array( 'jquery' ),
|
||||||
|
'1.1',
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
// Localize script to pass AJAX URL and nonce
|
||||||
|
wp_localize_script(
|
||||||
|
'asm-admin-script',
|
||||||
|
'asm_ajax_obj',
|
||||||
|
array(
|
||||||
|
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||||
|
'nonce' => wp_create_nonce( 'asm_ajax_nonce' ),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new menu item under the WordPress admin sidebar
|
||||||
|
*/
|
||||||
|
public function add_admin_menu() {
|
||||||
|
add_menu_page(
|
||||||
|
'Album Score Manager', // Page title
|
||||||
|
'Album Scores', // Menu title
|
||||||
|
'manage_options', // Capability
|
||||||
|
'album-score-manager', // Menu slug
|
||||||
|
array( $this, 'admin_page' ), // Callback function
|
||||||
|
'dashicons-awards', // Icon
|
||||||
|
6 // Position
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin page callback
|
||||||
|
*/
|
||||||
|
public function admin_page() {
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
// Fetch albums sorted by total plays
|
||||||
|
$albums = $wpdb->get_results(
|
||||||
|
"SELECT album_name, COUNT(*) as play_count
|
||||||
|
FROM `{$this->scrobbles_table}`
|
||||||
|
WHERE album_name IS NOT NULL
|
||||||
|
GROUP BY album_name
|
||||||
|
ORDER BY play_count DESC",
|
||||||
|
OBJECT
|
||||||
|
);
|
||||||
|
|
||||||
|
// Fetch existing scores
|
||||||
|
$existing_scores = $wpdb->get_results(
|
||||||
|
"SELECT album_name, score, author, cover_url FROM `{$this->scores_table}`",
|
||||||
|
ARRAY_A
|
||||||
|
);
|
||||||
|
|
||||||
|
$scores_assoc = array();
|
||||||
|
foreach ( $existing_scores as $score ) {
|
||||||
|
$scores_assoc[ $score['album_name'] ] = array(
|
||||||
|
'score' => $score['score'],
|
||||||
|
'author' => $score['author'],
|
||||||
|
'cover_url' => $score['cover_url'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare latest author and cover_url from song_scrobbles
|
||||||
|
$latest_entries = $this->get_latest_song_scrobbles( $albums );
|
||||||
|
|
||||||
|
?>
|
||||||
|
<div class="wrap">
|
||||||
|
<h1>Album Score Manager</h1>
|
||||||
|
<table class="widefat fixed striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Album Name</th>
|
||||||
|
<th>Author</th>
|
||||||
|
<th>Cover</th>
|
||||||
|
<th>Total Plays</th>
|
||||||
|
<th>Score</th>
|
||||||
|
<th>Status</th> <!-- Column to show update status -->
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if ( ! empty( $albums ) ) : ?>
|
||||||
|
<?php foreach ( $albums as $album ) :
|
||||||
|
$album_name = esc_html( $album->album_name );
|
||||||
|
$play_count = intval( $album->play_count );
|
||||||
|
|
||||||
|
// Fetch latest song_scrobbles entry for this album
|
||||||
|
$latest_entry = isset( $latest_entries[ $album->album_name ] ) ? $latest_entries[ $album->album_name ] : null;
|
||||||
|
|
||||||
|
$latest_author = $latest_entry ? esc_html( $latest_entry->author ) : '';
|
||||||
|
$latest_cover_url = $latest_entry ? esc_url( $latest_entry->cover_url ) : '';
|
||||||
|
|
||||||
|
// Existing scores
|
||||||
|
$current_score = isset( $scores_assoc[ $album->album_name ]['score'] ) ? esc_html( $scores_assoc[ $album->album_name ]['score'] ) : '';
|
||||||
|
$current_author = isset( $scores_assoc[ $album->album_name ]['author'] ) ? esc_html( $scores_assoc[ $album->album_name ]['author'] ) : $latest_author;
|
||||||
|
$current_cover_url = isset( $scores_assoc[ $album->album_name ]['cover_url'] ) ? esc_url( $scores_assoc[ $album->album_name ]['cover_url'] ) : $latest_cover_url;
|
||||||
|
?>
|
||||||
|
<tr id="asm-row-<?php echo esc_attr( $album->album_name ); ?>">
|
||||||
|
<td><?php echo $album_name; ?></td>
|
||||||
|
<td><?php echo $current_author; ?></td>
|
||||||
|
<td>
|
||||||
|
<img loading="lazy" src="<?php echo $current_cover_url; ?>" width=128>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td><?php echo $play_count; ?></td>
|
||||||
|
<td>
|
||||||
|
<select class="asm-score-dropdown" data-cover="<?php echo $current_cover_url; ?>" data-author="<?php echo $current_author; ?>" data-album="<?php echo esc_attr( $album->album_name ); ?>" style="width: 100%;">
|
||||||
|
<option value="">-- Select Score --</option>
|
||||||
|
<?php
|
||||||
|
$score_options = array( 'F', 'C', 'B', 'A', 'S', 'S+' );
|
||||||
|
foreach ( $score_options as $option ) : ?>
|
||||||
|
<option value="<?php echo $option; ?>" <?php selected( $current_score, $option ); ?>>
|
||||||
|
<?php echo $option; ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="asm-status">
|
||||||
|
<!-- Status messages will appear here -->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else : ?>
|
||||||
|
<tr>
|
||||||
|
<td colspan="6">No albums found.</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the latest song_scrobbles entry for each album
|
||||||
|
*
|
||||||
|
* @param array $albums Array of album objects
|
||||||
|
* @return array Associative array with album_name as key and latest entry as value
|
||||||
|
*/
|
||||||
|
private function get_latest_song_scrobbles( $albums ) {
|
||||||
|
global $wpdb; // Ensure $wpdb is declared as global
|
||||||
|
|
||||||
|
if ( empty( $albums ) ) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize an array to hold the latest entries
|
||||||
|
$latest_entries = array();
|
||||||
|
|
||||||
|
foreach ( $albums as $album ) {
|
||||||
|
$latest_entry = $wpdb->get_row( $wpdb->prepare(
|
||||||
|
"SELECT author, cover_url
|
||||||
|
FROM `{$this->scrobbles_table}`
|
||||||
|
WHERE album_name = %s
|
||||||
|
ORDER BY id DESC
|
||||||
|
LIMIT 1",
|
||||||
|
$album->album_name
|
||||||
|
) );
|
||||||
|
|
||||||
|
if ( $latest_entry ) {
|
||||||
|
$latest_entries[ $album->album_name ] = $latest_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $latest_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AJAX handler to update a single album's score
|
||||||
|
*/
|
||||||
|
public function ajax_update_score() {
|
||||||
|
// Check nonce
|
||||||
|
check_ajax_referer( 'asm_ajax_nonce', 'nonce' );
|
||||||
|
|
||||||
|
// Check user capabilities
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( 'Unauthorized user.' );
|
||||||
|
wp_die();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and sanitize input
|
||||||
|
$album = isset( $_POST['album'] ) ? sanitize_text_field( $_POST['album'] ) : '';
|
||||||
|
$score = isset( $_POST['score'] ) ? sanitize_text_field( $_POST['score'] ) : '';
|
||||||
|
$cover_url = isset( $_POST['cover_url'] ) ? esc_url_raw( $_POST['cover_url'] ) : '';
|
||||||
|
$author = isset( $_POST['author'] ) ? sanitize_text_field( $_POST['author'] ) : '';
|
||||||
|
|
||||||
|
// Validate input
|
||||||
|
$valid_scores = array( 'F', 'C', 'B', 'A', 'S', 'S+' );
|
||||||
|
if ( empty( $album ) || empty( $score ) || ! in_array( $score, $valid_scores, true ) ) {
|
||||||
|
wp_send_json_error( 'Invalid input.' );
|
||||||
|
wp_die();
|
||||||
|
}
|
||||||
|
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
// Check if the album already has a score
|
||||||
|
$existing = $wpdb->get_var( $wpdb->prepare(
|
||||||
|
"SELECT id FROM `{$this->scores_table}` WHERE `album_name` = %s",
|
||||||
|
$album
|
||||||
|
) );
|
||||||
|
|
||||||
|
if ( $existing ) {
|
||||||
|
// Update existing record
|
||||||
|
$updated_rows = $wpdb->update(
|
||||||
|
$this->scores_table,
|
||||||
|
array(
|
||||||
|
'score' => $score,
|
||||||
|
'author' => $author,
|
||||||
|
'cover_url' => $cover_url,
|
||||||
|
),
|
||||||
|
array( 'id' => $existing ),
|
||||||
|
array( '%s', '%s', '%s' ),
|
||||||
|
array( '%d' )
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( false !== $updated_rows ) {
|
||||||
|
wp_send_json_success( 'Score updated successfully.' );
|
||||||
|
} else {
|
||||||
|
wp_send_json_error( 'Failed to update score.' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Insert new record
|
||||||
|
$inserted_rows = $wpdb->insert(
|
||||||
|
$this->scores_table,
|
||||||
|
array(
|
||||||
|
'album_name' => $album,
|
||||||
|
'score' => $score,
|
||||||
|
'author' => $author,
|
||||||
|
'cover_url' => $cover_url,
|
||||||
|
),
|
||||||
|
array( '%s', '%s', '%s', '%s' )
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( false !== $inserted_rows ) {
|
||||||
|
wp_send_json_success( 'Score added successfully.' );
|
||||||
|
} else {
|
||||||
|
wp_send_json_error( 'Failed to add score.' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_die();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
js/asm-admin.js
Normal file
49
js/asm-admin.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
jQuery(document).ready(function($) {
|
||||||
|
// Listen for changes on any score dropdown
|
||||||
|
$('.asm-score-dropdown').on('change', function() {
|
||||||
|
var dropdown = $(this);
|
||||||
|
var album = dropdown.data('album');
|
||||||
|
var score = dropdown.val();
|
||||||
|
|
||||||
|
// Get the author and cover_url from the respective inputs in the same row
|
||||||
|
var row = $('#asm-row-' + album);
|
||||||
|
var author = dropdown.data('author');
|
||||||
|
var cover_url = dropdown.data('cover');
|
||||||
|
|
||||||
|
// Status cell
|
||||||
|
var statusCell = row.find('.asm-status');
|
||||||
|
|
||||||
|
if (score === '') {
|
||||||
|
// If no score is selected, do not proceed
|
||||||
|
statusCell.html('<span style="color: orange;">No score selected.</span>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show loading message
|
||||||
|
statusCell.html('<span style="color: blue;">Updating...</span>');
|
||||||
|
|
||||||
|
// AJAX request
|
||||||
|
$.ajax({
|
||||||
|
url: asm_ajax_obj.ajax_url,
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
action: 'asm_update_score',
|
||||||
|
nonce: asm_ajax_obj.nonce,
|
||||||
|
album: album,
|
||||||
|
score: score,
|
||||||
|
author: author,
|
||||||
|
cover_url: cover_url
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
statusCell.html('<span style="color: green;">' + response.data + '</span>');
|
||||||
|
} else {
|
||||||
|
statusCell.html('<span style="color: red;">' + response.data + '</span>');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
statusCell.html('<span style="color: red;">AJAX error.</span>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -13,8 +13,10 @@ if (!defined('ABSPATH')) {
|
|||||||
|
|
||||||
// Include the separate plugins
|
// Include the separate plugins
|
||||||
require_once(plugin_dir_path(__FILE__) . 'album-collage-generator.php');
|
require_once(plugin_dir_path(__FILE__) . 'album-collage-generator.php');
|
||||||
|
require_once(plugin_dir_path(__FILE__) . 'album-scores.php');
|
||||||
require_once(plugin_dir_path(__FILE__) . 'scrobble-handler.php');
|
require_once(plugin_dir_path(__FILE__) . 'scrobble-handler.php');
|
||||||
|
|
||||||
// Initialize both classes
|
// Initialize both classes
|
||||||
new AlbumCollageGenerator();
|
new AlbumCollageGenerator();
|
||||||
new ScrobbleHandler();
|
new ScrobbleHandler();
|
||||||
|
new AlbumScoreManager();
|
||||||
|
Loading…
Reference in New Issue
Block a user